Skip to content

Commit

Permalink
feat: add API example
Browse files Browse the repository at this point in the history
  • Loading branch information
LichKing-2234 committed Oct 22, 2020
1 parent 69a7a96 commit 652c346
Show file tree
Hide file tree
Showing 11 changed files with 861 additions and 4,493 deletions.
5 changes: 5 additions & 0 deletions example/agora.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"appId": YOUR_APP_ID,
"channelId": "APIExample",
"token": YOUR_TOEKN
}
1 change: 1 addition & 0 deletions example/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ android {
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
multiDexEnabled true
}
splits {
abi {
Expand Down
9 changes: 8 additions & 1 deletion example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,15 @@
"start": "react-native start"
},
"dependencies": {
"@react-native-community/masked-view": "^0.1.10",
"@react-navigation/native": "^5.7.1",
"@react-navigation/stack": "^5.7.1",
"react": "16.11.0",
"react-native": "0.62.2"
"react-native": "0.62.2",
"react-native-gesture-handler": "^1.7.0",
"react-native-reanimated": "^1.10.1",
"react-native-safe-area-context": "^3.1.1",
"react-native-screens": "^2.9.0"
},
"devDependencies": {
"@babel/core": "^7.9.6",
Expand Down
99 changes: 80 additions & 19 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,92 @@
import * as React from 'react';
import { StyleSheet, View, Text } from 'react-native';
import RtcEngine, { RtcChannel } from 'react-native-agora';
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* Generated with the TypeScript template
* https://github.com/react-native-community/react-native-template-typescript
*
* @format
*/

export default function App() {
const [result, setResult] = React.useState<string>();
import React from 'react';
import {
SafeAreaView,
StyleSheet,
SectionList,
Text,
View,
TouchableOpacity,
} from 'react-native';

React.useEffect(() => {
RtcEngine.create('2b4b76e458cf439aa7cd313b9504f0a4').then(() => {
RtcChannel.create('xxx').then((channel: RtcChannel) => {
setResult(channel.channelId);
});
});
}, []);
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';

import Basic from './examples/basic';
import Advanced from './examples/advanced';

const Stack = createStackNavigator();

const DATA = [Basic, Advanced];

const App = () => {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name={'APIExample'} component={Home} />
{DATA.map((value) =>
// @ts-ignore
value.data.map(({ name, component }) => (
<Stack.Screen name={name} component={component} />
))
)}
</Stack.Navigator>
</NavigationContainer>
);
};

// @ts-ignore
const Home = ({ navigation }) => {
return (
<View style={styles.container}>
<Text style={styles.text}>Result: {result}</Text>
</View>
<SafeAreaView style={styles.container}>
<SectionList
// @ts-ignore
sections={DATA}
keyExtractor={(item, index) => item.name + index}
renderItem={({ item }) => <Item item={item} navigation={navigation} />}
renderSectionHeader={({ section: { title } }) => (
<Text style={styles.header}>{title}</Text>
)}
/>
</SafeAreaView>
);
}
};

// @ts-ignore
const Item = ({ item, navigation }) => (
<View style={styles.item}>
<TouchableOpacity onPress={() => navigation.navigate(item.name)}>
<Text style={styles.title}>{item.name}</Text>
</TouchableOpacity>
</View>
);

const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
},
text: {
textAlign: 'center',
header: {
padding: 10,
fontSize: 24,
color: 'white',
backgroundColor: 'grey',
},
item: {
padding: 15,
},
title: {
fontSize: 24,
color: 'black',
},
});

export default App;
255 changes: 255 additions & 0 deletions example/src/examples/advanced/MultiChannel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
import React, { Component } from 'react';
import {
View,
PermissionsAndroid,
StyleSheet,
Button,
Platform,
} from 'react-native';

import RtcEngine, {
RtcChannel,
RtcLocalView,
RtcRemoteView,
ChannelProfile,
ClientRole,
ChannelMediaOptions,
} from 'react-native-agora';

const config = require('../../../agora.config.json');

interface State {
renderChannelId: string;
isJoined0: boolean;
isJoined1: boolean;
remoteUid0: number | undefined;
remoteUid1: number | undefined;
}

const channelId0 = 'channel0';
const channelId1 = 'channel1';

export default class MultiChannel extends Component<{}, State, any> {
_engine: RtcEngine | undefined;
_channel0: RtcChannel | undefined;
_channel1: RtcChannel | undefined;

constructor(props: {}) {
super(props);
this.state = {
renderChannelId: channelId0,
isJoined0: false,
isJoined1: false,
remoteUid0: undefined,
remoteUid1: undefined,
};
}

UNSAFE_componentWillMount() {
this._initEngine();
}

componentWillUnmount() {
this._engine?.destroy();
}

_initEngine = async () => {
this._engine = await RtcEngine.create(config.appId);

await this._engine.enableVideo();
await this._engine.startPreview();
await this._engine.setChannelProfile(ChannelProfile.LiveBroadcasting);
};

_joinChannel0 = async () => {
if (Platform.OS === 'android') {
await PermissionsAndroid.requestMultiple([
PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,
PermissionsAndroid.PERMISSIONS.CAMERA,
]);
}

this._channel0 = await RtcChannel.create(channelId0);
this._addListener(this._channel0, channelId0);

await this._channel0.setClientRole(ClientRole.Broadcaster);
await this._channel0.joinChannel(
null,
null,
0,
new ChannelMediaOptions(true, true)
);
};

_joinChannel1 = async () => {
if (Platform.OS === 'android') {
await PermissionsAndroid.requestMultiple([
PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,
PermissionsAndroid.PERMISSIONS.CAMERA,
]);
}

this._channel1 = await RtcChannel.create(channelId1);
this._addListener(this._channel1, channelId1);

await this._channel1.setClientRole(ClientRole.Broadcaster);
await this._channel1.joinChannel(
null,
null,
0,
new ChannelMediaOptions(true, true)
);
};

_addListener = (channel: RtcChannel, channelId: string) => {
channel.addListener('JoinChannelSuccess', (uid, elapsed) => {
console.info('JoinChannelSuccess', channelId, uid, elapsed);
if (channelId === channelId0) {
this.setState({ isJoined0: true });
} else if (channelId === channelId1) {
this.setState({ isJoined1: true });
}
});
channel.addListener('UserJoined', (uid, elapsed) => {
console.info('UserJoined', channelId, uid, elapsed);
if (channelId === channelId0) {
this.setState({ remoteUid0: uid });
} else if (channelId === channelId1) {
this.setState({ remoteUid1: uid });
}
});
channel.addListener('UserOffline', (uid, reason) => {
console.info('UserOffline', channelId, uid, reason);
if (channelId === channelId0) {
if (uid === this.state.remoteUid0) {
this.setState({ remoteUid0: undefined });
}
} else if (channelId === channelId1) {
if (uid === this.state.remoteUid1) {
this.setState({ remoteUid1: undefined });
}
}
});
channel.addListener('LeaveChannel', (stats) => {
console.info('LeaveChannel', channelId, stats);
if (channelId === channelId0) {
this.setState({ isJoined0: false, remoteUid0: undefined });
} else if (channelId === channelId1) {
this.setState({ isJoined1: false, remoteUid1: undefined });
}
});
};

_publishChannel0 = async () => {
await this._channel1?.unpublish();
await this._channel0?.publish();
};

_publishChannel1 = async () => {
await this._channel0?.unpublish();
await this._channel1?.publish();
};

_leaveChannel0 = async () => {
await this._channel0?.leaveChannel();
};

_leaveChannel1 = async () => {
await this._channel1?.leaveChannel();
};

render() {
const { isJoined0, isJoined1 } = this.state;
return (
<View style={styles.container}>
<View style={styles.bottom}>
<Button
onPress={isJoined0 ? this._leaveChannel0 : this._joinChannel0}
title={`${isJoined0 ? 'Leave' : 'Join'} ${channelId0}`}
/>
<Button
onPress={isJoined1 ? this._leaveChannel1 : this._joinChannel1}
title={`${isJoined1 ? 'Leave' : 'Join'} ${channelId1}`}
/>
</View>
{this._renderVideo()}
<View style={styles.float}>
<Button
onPress={this._publishChannel0}
title={`Pulish ${channelId0}`}
/>
<Button
onPress={() => {
this.setState({ renderChannelId: channelId0 });
}}
title={`Render ${channelId0}`}
/>
<Button
onPress={this._publishChannel1}
title={`Pulish ${channelId1}`}
/>
<Button
onPress={() => {
this.setState({ renderChannelId: channelId1 });
}}
title={`Render ${channelId1}`}
/>
</View>
</View>
);
}

_renderVideo = () => {
const { renderChannelId, remoteUid0, remoteUid1 } = this.state;
let remoteUid: number | undefined;
if (renderChannelId === channelId0) {
remoteUid = remoteUid0;
} else if (renderChannelId === channelId1) {
remoteUid = remoteUid1;
}
return (
<View style={styles.container}>
<RtcLocalView.SurfaceView
style={styles.local}
channelId={renderChannelId}
/>
{remoteUid !== undefined && (
<RtcRemoteView.SurfaceView
style={styles.remote}
channelId={renderChannelId}
uid={remoteUid}
/>
)}
</View>
);
};
}

const styles = StyleSheet.create({
container: {
flex: 1,
},
float: {
width: '30%',
position: 'absolute',
right: 0,
bottom: 0,
},
bottom: {
width: '100%',
},
input: {
borderColor: 'gray',
borderWidth: 1,
},
local: {
flex: 1,
},
remote: {
width: 200,
height: 200,
position: 'absolute',
left: 0,
top: 0,
},
});
Loading

0 comments on commit 652c346

Please sign in to comment.