Skip to content

Commit

Permalink
feat: implemented-example
Browse files Browse the repository at this point in the history
Implemented example
  • Loading branch information
ezranbayantemur committed Jan 5, 2022
1 parent 33fc8b5 commit dc995e0
Show file tree
Hide file tree
Showing 14 changed files with 357 additions and 68 deletions.
36 changes: 13 additions & 23 deletions example/android/app/src/main/AndroidManifest.xml
@@ -1,27 +1,17 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.reactnativertmp">
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.reactnativertmp">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />

<application
android:name=".MainApplication"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:allowBackup="false"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
</application>
<application android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="false" android:theme="@style/AppTheme">
<activity android:name=".MainActivity" android:label="@string/app_name" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode" android:launchMode="singleTask" android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
</application>

</manifest>
Expand Up @@ -10,7 +10,7 @@
import com.facebook.soloader.SoLoader;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import com.reactnativertmp.RtmpPackage;
import com.reactnativertmp.RTMPPackage;

public class MainApplication extends Application implements ReactApplication {

Expand All @@ -27,7 +27,7 @@ protected List<ReactPackage> getPackages() {
List<ReactPackage> packages = new PackageList(this).getPackages();
// Packages that cannot be autolinked yet can be added manually here, for RtmpExample:
// packages.add(new MyReactNativePackage());
packages.add(new RtmpPackage());
packages.add(new RTMPPackage());
return packages;
}

Expand Down
21 changes: 21 additions & 0 deletions example/src/App.styles.tsx
@@ -0,0 +1,21 @@
import { StyleSheet } from 'react-native';

export default StyleSheet.create({
container: {
flex: 1,
},
publisher_camera: {
flex: 1,
width: '100%',
height: '100%',
},
footer_container: {
position: 'absolute',
bottom: 10,
left: 0,
right: 0,
justifyContent: 'space-between',
padding: 10,
flexDirection: 'row',
},
});
104 changes: 87 additions & 17 deletions example/src/App.tsx
@@ -1,25 +1,95 @@
import * as React from 'react';
import React, { useRef, useState } from 'react';

import { StyleSheet, View } from 'react-native';
import { RtmpView } from 'react-native-rtmp';
import { View } from 'react-native';
import RTMPPublisher from 'react-native-rtmp';

import styles from './App.styles';

import Button from './components/Button';
import LiveBadge from './components/LiveBadge';
import usePermissions from './hooks/usePermissions';

const PUBLISH_URL = 'YOUR-PUBLISH-URL';

export default function App() {
const publisherRef = useRef(null);
const [isStreaming, setIsStreaming] = useState<boolean>();
const [isMuted, setIsMuted] = useState<boolean>();

const { permissionGranted } = usePermissions();

function handleOnConnectionFailedRtmp() {
console.log('Connection Failed');
}

function handleOnConnectionStartedRtmp() {
console.log('Connection Started');
}

function handleOnConnectionSuccessRtmp() {
console.log('Connected');
setIsStreaming(true);
}

function handleOnDisconnectRtmp() {
console.log('Disconnected');
setIsStreaming(false);
}

function handleOnNewBitrateRtmp() {
console.log('New Bitrate Received');
}

function handleUnmute() {
publisherRef.current.unmute();
setIsMuted(false);
}

function handleMute() {
publisherRef.current.mute();
setIsMuted(true);
}

function handleStartStream() {
publisherRef.current.startStream();
}

function handleStopStream() {
publisherRef.current.stopStream();
}

function handleSwitchCamera() {
publisherRef.current.switchCamera();
}

return (
<View style={styles.container}>
<RtmpViewManager color="#32a852" style={styles.box} />
{permissionGranted && (
<RTMPPublisher
ref={publisherRef}
publishUrl={PUBLISH_URL}
style={styles.publisher_camera}
onConnectionFailedRtmp={handleOnConnectionFailedRtmp}
onConnectionStartedRtmp={handleOnConnectionStartedRtmp}
onConnectionSuccessRtmp={handleOnConnectionSuccessRtmp}
onDisconnectRtmp={handleOnDisconnectRtmp}
onNewBitrateRtmp={handleOnNewBitrateRtmp}
/>
)}
<View style={styles.footer_container}>
{isMuted ? (
<Button title="Unmute" onPress={handleUnmute} />
) : (
<Button title="Mute" onPress={handleMute} />
)}
{isStreaming ? (
<Button title="Stop Stream" onPress={handleStopStream} />
) : (
<Button title="Start Stream" onPress={handleStartStream} />
)}
<Button title="Switch Camera" onPress={handleSwitchCamera} />
</View>
{isStreaming && <LiveBadge />}
</View>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
box: {
width: 60,
height: 60,
marginVertical: 20,
},
});
14 changes: 14 additions & 0 deletions example/src/components/Button/Button.styles.tsx
@@ -0,0 +1,14 @@
import { StyleSheet } from 'react-native';

export default StyleSheet.create({
container: {
backgroundColor: '#039be5',
alignItems: 'center',
justifyContent: 'center',
padding: 5,
borderRadius: 5,
},
title: {
color: '#FFFFFF',
},
});
19 changes: 19 additions & 0 deletions example/src/components/Button/Button.tsx
@@ -0,0 +1,19 @@
import React from 'react';
import { TouchableOpacity, Text } from 'react-native';

import styles from './Button.styles';

export interface ButtonProps {
title: string;
onPress: () => void;
}

const Button = ({ title, onPress }: ButtonProps) => {
return (
<TouchableOpacity style={styles.container} onPress={onPress}>
<Text style={styles.title}>{title}</Text>
</TouchableOpacity>
);
};

export default Button;
1 change: 1 addition & 0 deletions example/src/components/Button/index.ts
@@ -0,0 +1 @@
export { default } from './Button';
26 changes: 26 additions & 0 deletions example/src/components/LiveBadge/LiveBadge.styles.tsx
@@ -0,0 +1,26 @@
import { StyleSheet } from 'react-native';

export default StyleSheet.create({
container: {
backgroundColor: '#eceff1',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
padding: 5,
borderRadius: 10,
position: 'absolute',
margin: 10,
borderColor: '#bdbdbd',
borderWidth: 1,
},
title: {
color: '#000',
fontWeight: 'bold',
},
dot: {
backgroundColor: 'red',
padding: 6,
borderRadius: 20,
marginRight: 5,
},
});
15 changes: 15 additions & 0 deletions example/src/components/LiveBadge/LiveBadge.tsx
@@ -0,0 +1,15 @@
import React from 'react';
import { View, Text } from 'react-native';

import styles from './LiveBadge.styles';

const LiveBadge = () => {
return (
<View style={styles.container}>
<View style={styles.dot} />
<Text style={styles.title}>LIVE</Text>
</View>
);
};

export default LiveBadge;
1 change: 1 addition & 0 deletions example/src/components/LiveBadge/index.ts
@@ -0,0 +1 @@
export { default } from './LiveBadge';
39 changes: 39 additions & 0 deletions example/src/hooks/usePermissions.ts
@@ -0,0 +1,39 @@
import { useState, useEffect } from 'react';
import { PermissionsAndroid, Platform } from 'react-native';

const CAMERA_PERMISSION = PermissionsAndroid.PERMISSIONS.CAMERA;
const AUDIO_PERMISSION = PermissionsAndroid.PERMISSIONS.CAMERA;

function usePermissions() {
const [permissionGranted, setPermissionGranted] = useState<boolean>(false);

useEffect(() => {
getPermissions();
}, []);

async function getPermissions() {
if (Platform.OS !== 'android') {
return;
}

const cameraPermission = await PermissionsAndroid.check(CAMERA_PERMISSION);
const audioPermission = await PermissionsAndroid.check(AUDIO_PERMISSION);

if (cameraPermission && audioPermission) {
return setPermissionGranted(true);
}

const hasPermissions = await PermissionsAndroid.requestMultiple([
CAMERA_PERMISSION,
AUDIO_PERMISSION,
]);

if (hasPermissions) {
return setPermissionGranted(true);
}
}

return { permissionGranted };
}

export default usePermissions;
15 changes: 15 additions & 0 deletions src/Component.tsx
@@ -0,0 +1,15 @@
import { requireNativeComponent, ViewStyle } from 'react-native';

export interface RTMPPublisherProps {
style?: ViewStyle;
ref: any;
publishURL: string;
onLayoutChange?: () => void;
onConnectionFailedRtmp?: () => void;
onConnectionStartedRtmp?: () => void;
onConnectionSuccessRtmp?: () => void;
onDisconnectRtmp?: () => void;
onNewBitrateRtmp?: () => void;
}

export default requireNativeComponent<RTMPPublisherProps>('RTMPPublisher');

0 comments on commit dc995e0

Please sign in to comment.