33# Twilio Video (WebRTC) for React Native
44
55Platforms:
6+
67- iOS
78- Android
89
@@ -27,6 +28,47 @@ yarn add https://github.com/blackuy/react-native-twilio-video-webrtc
2728npm install https://github.com/blackuy/react-native-twilio-video-webrtc --save
2829```
2930
31+ ### Usage with Expo
32+
33+ To use this library with [ ` Expo ` ] ( https://expo.dev ) we recommend using our config plugin that you can configure like the following example:
34+
35+ ``` json
36+ {
37+ "name" : " my app" ,
38+ "plugins" : [
39+ [
40+ " react-native-twilio-video-webrtc" ,
41+ {
42+ "cameraPermission" : " Allow $(PRODUCT_NAME) to access your camera" ,
43+ "microphonePermission" : " Allow $(PRODUCT_NAME) to access your microphone"
44+ }
45+ ]
46+ ]
47+ }
48+ ```
49+
50+ Also you will need to install ` expo-build-properties ` package:
51+
52+ #### NPM
53+
54+ ``` bash
55+ npm i expo-build-properties
56+ ```
57+
58+ #### Yarn
59+
60+ ``` bash
61+ yarn add expo-build-properties
62+ ```
63+
64+ #### Expo Config Plugin Props
65+
66+ The plugin support the following properties:
67+
68+ - ` cameraPermission ` : Specifies the text to show when requesting the camera permission to the user.
69+
70+ - ` microphonePermission ` : Specifies the text to show when requesting the microphone permission to the user.
71+
3072### iOS
3173
3274#### Option A: Install with CocoaPods (recommended)
@@ -135,7 +177,7 @@ android {
135177}
136178```
137179
138- Now you're ready to load the package in ` MainApplication.java ` . In the imports section, add this:
180+ Now you're ready to load the package in ` MainApplication.java ` . In the imports section, add this:
139181
140182``` java
141183import com.twiliorn.library.TwilioPackage ;
@@ -165,7 +207,7 @@ For most applications, you'll want to add camera and audio permissions to your `
165207 <uses-feature android : name =" android.hardware.microphone" android : required =" false" />
166208```
167209
168- Newer versions of Android have a different permissions model. You will need to use the ` PermissionsAndroid `
210+ Newer versions of Android have a different permissions model. You will need to use the ` PermissionsAndroid `
169211class in ` react-native ` in order to request the ` CAMERA ` and ` RECORD_AUDIO ` permissions.
170212
171213### Additional Tips
@@ -190,6 +232,7 @@ this library are not stripped. To do that, add these two lines to `proguard-rule
190232```
191233
192234## Docs
235+
193236You can see the documentation [ here] ( ./docs ) .
194237
195238## Usage
@@ -200,8 +243,8 @@ We have three important components to understand:
200243import {
201244 TwilioVideo ,
202245 TwilioVideoLocalView ,
203- TwilioVideoParticipantView
204- } from ' react-native-twilio-video-webrtc'
246+ TwilioVideoParticipantView ,
247+ } from " react-native-twilio-video-webrtc" ;
205248```
206249
207250- ` TwilioVideo ` / is responsible for connecting to rooms, events delivery and camera/audio.
@@ -210,62 +253,62 @@ import {
210253
211254Here you can see a complete example of a simple application that uses almost all the apis:
212255
213- ```` javascript
214- import React , { Component , useRef } from ' react' ;
256+ ``` javascript
257+ import React , { Component , useRef } from " react" ;
215258import {
216259 TwilioVideoLocalView ,
217260 TwilioVideoParticipantView ,
218- TwilioVideo
219- } from ' react-native-twilio-video-webrtc' ;
261+ TwilioVideo ,
262+ } from " react-native-twilio-video-webrtc" ;
220263
221264const Example = (props ) => {
222265 const [isAudioEnabled , setIsAudioEnabled ] = useState (true );
223266 const [isVideoEnabled , setIsVideoEnabled ] = useState (true );
224- const [status , setStatus ] = useState (' disconnected' );
267+ const [status , setStatus ] = useState (" disconnected" );
225268 const [participants , setParticipants ] = useState (new Map ());
226269 const [videoTracks , setVideoTracks ] = useState (new Map ());
227- const [token , setToken ] = useState (' ' );
270+ const [token , setToken ] = useState (" " );
228271 const twilioRef = useRef (null );
229272
230273 const _onConnectButtonPress = () => {
231274 twilioRef .current .connect ({ accessToken: token });
232- setStatus (' connecting' );
233- }
234-
275+ setStatus (" connecting" );
276+ };
277+
235278 const _onEndButtonPress = () => {
236279 twilioRef .current .disconnect ();
237280 };
238281
239282 const _onMuteButtonPress = () => {
240283 twilioRef .current
241284 .setLocalAudioEnabled (! isAudioEnabled)
242- .then (isEnabled => setIsAudioEnabled (isEnabled));
285+ .then (( isEnabled ) => setIsAudioEnabled (isEnabled));
243286 };
244287
245288 const _onFlipButtonPress = () => {
246289 twilioRef .current .flipCamera ();
247290 };
248291
249- const _onRoomDidConnect = ({roomName, error}) => {
250- console .log (' onRoomDidConnect: ' , roomName);
292+ const _onRoomDidConnect = ({ roomName, error }) => {
293+ console .log (" onRoomDidConnect: " , roomName);
251294
252- setStatus (' connected' );
295+ setStatus (" connected" );
253296 };
254297
255298 const _onRoomDidDisconnect = ({ roomName, error }) => {
256- console .log (' [Disconnect]ERROR: ' , error);
299+ console .log (" [Disconnect]ERROR: " , error);
257300
258- setStatus (' disconnected' );
301+ setStatus (" disconnected" );
259302 };
260303
261- const _onRoomDidFailToConnect = error => {
262- console .log (' [FailToConnect]ERROR: ' , error);
304+ const _onRoomDidFailToConnect = ( error ) => {
305+ console .log (" [FailToConnect]ERROR: " , error);
263306
264- setStatus (' disconnected' );
307+ setStatus (" disconnected" );
265308 };
266309
267310 const _onParticipantAddedVideoTrack = ({ participant, track }) => {
268- console .log (' onParticipantAddedVideoTrack: ' , participant, track);
311+ console .log (" onParticipantAddedVideoTrack: " , participant, track);
269312
270313 setVideoTracks (
271314 new Map ([
@@ -274,12 +317,12 @@ const Example = (props) => {
274317 track .trackSid ,
275318 { participantSid: participant .sid , videoTrackSid: track .trackSid },
276319 ],
277- ]),
320+ ])
278321 );
279322 };
280323
281324 const _onParticipantRemovedVideoTrack = ({ participant, track }) => {
282- console .log (' onParticipantRemovedVideoTrack: ' , participant, track);
325+ console .log (" onParticipantRemovedVideoTrack: " , participant, track);
283326
284327 const videoTracksLocal = videoTracks;
285328 videoTracksLocal .delete (track .trackSid );
@@ -289,84 +332,78 @@ const Example = (props) => {
289332
290333 return (
291334 < View style= {styles .container }>
292- {
293- status === ' disconnected' &&
335+ {status === " disconnected" && (
294336 < View>
295- < Text style= {styles .welcome }>
296- React Native Twilio Video
297- < / Text >
337+ < Text style= {styles .welcome }> React Native Twilio Video< / Text >
298338 < TextInput
299339 style= {styles .input }
300- autoCapitalize= ' none'
340+ autoCapitalize= " none"
301341 value= {token}
302- onChangeText= {(text ) => setToken (text)}>
303- < / TextInput>
342+ onChangeText= {(text ) => setToken (text)}
343+ > </ TextInput>
304344 < Button
305345 title= " Connect"
306346 style= {styles .button }
307- onPress= {_onConnectButtonPress}>
308- < / Button>
347+ onPress= {_onConnectButtonPress}
348+ > </ Button>
309349 < / View>
310- }
350+ ) }
311351
312- {
313- (status === ' connected' || status === ' connecting' ) &&
314- < View style= {styles .callContainer }>
315- {
316- status === ' connected' &&
352+ {(status === " connected" || status === " connecting" ) && (
353+ < View style= {styles .callContainer }>
354+ {status === " connected" && (
317355 < View style= {styles .remoteGrid }>
318- {
319- Array .from (videoTracks, ([trackSid , trackIdentifier ]) => {
320- return (
321- < TwilioVideoParticipantView
322- style= {styles .remoteVideo }
323- key= {trackSid}
324- trackIdentifier= {trackIdentifier}
325- / >
326- )
327- })
328- }
356+ {Array .from (videoTracks, ([trackSid , trackIdentifier ]) => {
357+ return (
358+ < TwilioVideoParticipantView
359+ style= {styles .remoteVideo }
360+ key= {trackSid}
361+ trackIdentifier= {trackIdentifier}
362+ / >
363+ );
364+ })}
329365 < / View>
330- }
331- < View
332- style= {styles .optionsContainer }>
366+ )}
367+ < View style= {styles .optionsContainer }>
333368 < TouchableOpacity
334369 style= {styles .optionButton }
335- onPress= {_onEndButtonPress}>
336- < Text style= {{fontSize: 12 }}> End< / Text >
370+ onPress= {_onEndButtonPress}
371+ >
372+ < Text style= {{ fontSize: 12 }}> End< / Text >
337373 < / TouchableOpacity>
338374 < TouchableOpacity
339375 style= {styles .optionButton }
340- onPress= {_onMuteButtonPress}>
341- < Text style= {{fontSize: 12 }}> { isAudioEnabled ? " Mute" : " Unmute" }< / Text >
376+ onPress= {_onMuteButtonPress}
377+ >
378+ < Text style= {{ fontSize: 12 }}>
379+ {isAudioEnabled ? " Mute" : " Unmute" }
380+ < / Text >
342381 < / TouchableOpacity>
343382 < TouchableOpacity
344383 style= {styles .optionButton }
345- onPress= {_onFlipButtonPress}>
346- < Text style= {{fontSize: 12 }}> Flip< / Text >
384+ onPress= {_onFlipButtonPress}
385+ >
386+ < Text style= {{ fontSize: 12 }}> Flip< / Text >
347387 < / TouchableOpacity>
348- < TwilioVideoLocalView
349- enabled= {true }
350- style= {styles .localVideo }
351- / >
388+ < TwilioVideoLocalView enabled= {true } style= {styles .localVideo } / >
352389 < / View>
353390 < / View>
354- }
391+ ) }
355392
356393 < TwilioVideo
357- ref= { twilioRef }
358- onRoomDidConnect= { _onRoomDidConnect }
359- onRoomDidDisconnect= { _onRoomDidDisconnect }
360- onRoomDidFailToConnect= { _onRoomDidFailToConnect }
361- onParticipantAddedVideoTrack= { _onParticipantAddedVideoTrack }
362- onParticipantRemovedVideoTrack= { _onParticipantRemovedVideoTrack }
394+ ref= {twilioRef}
395+ onRoomDidConnect= {_onRoomDidConnect}
396+ onRoomDidDisconnect= {_onRoomDidDisconnect}
397+ onRoomDidFailToConnect= { _onRoomDidFailToConnect}
398+ onParticipantAddedVideoTrack= {_onParticipantAddedVideoTrack}
399+ onParticipantRemovedVideoTrack= { _onParticipantRemovedVideoTrack}
363400 / >
364401 < / View>
365402 );
366- }
403+ };
367404
368- AppRegistry .registerComponent (' Example' , () => Example);
369- ````
405+ AppRegistry .registerComponent (" Example" , () => Example);
406+ ```
370407
371408## Run the Example Application
372409
@@ -379,18 +416,18 @@ To run the example application:
379416
380417## Migrating from 1.x to 2.x
381418
382- * Make sure your pod dependencies are updated. If you manually specified a pod version, you'll want to update it as follows:
419+ - Make sure your pod dependencies are updated. If you manually specified a pod version, you'll want to update it as follows:
383420
384421```
385422 s.dependency 'TwilioVideo', '~> 2.2.0'
386423```
387424
388- * Both participants and tracks are uniquely identified by their ` sid ` /` trackSid ` field.
389- The ` trackId ` field no longer exists and should be replaced by ` trackSid ` . Commensurate with this change,
390- participant views now expect ` participantSid ` and ` videoTrackSid ` keys in the ` trackIdentity ` prop (instead of
391- ` identity ` and ` trackId ` ).
425+ - Both participants and tracks are uniquely identified by their ` sid ` /` trackSid ` field.
426+ The ` trackId ` field no longer exists and should be replaced by ` trackSid ` . Commensurate with this change,
427+ participant views now expect ` participantSid ` and ` videoTrackSid ` keys in the ` trackIdentity ` prop (instead of
428+ ` identity ` and ` trackId ` ).
392429
393- * Make sure you're listening to participant events via ` onParticipant{Added/Removed}VideoTrack ` rather than ` onParticipant{Enabled/Disabled}Track ` .
430+ - Make sure you're listening to participant events via ` onParticipant{Added/Removed}VideoTrack ` rather than ` onParticipant{Enabled/Disabled}Track ` .
394431
395432## Contact
396433
0 commit comments