3
3
# Twilio Video (WebRTC) for React Native
4
4
5
5
Platforms:
6
+
6
7
- iOS
7
8
- Android
8
9
@@ -27,6 +28,47 @@ yarn add https://github.com/blackuy/react-native-twilio-video-webrtc
27
28
npm install https://github.com/blackuy/react-native-twilio-video-webrtc --save
28
29
```
29
30
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
+
30
72
### iOS
31
73
32
74
#### Option A: Install with CocoaPods (recommended)
@@ -135,7 +177,7 @@ android {
135
177
}
136
178
```
137
179
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:
139
181
140
182
``` java
141
183
import com.twiliorn.library.TwilioPackage ;
@@ -165,7 +207,7 @@ For most applications, you'll want to add camera and audio permissions to your `
165
207
<uses-feature android : name =" android.hardware.microphone" android : required =" false" />
166
208
```
167
209
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 `
169
211
class in ` react-native ` in order to request the ` CAMERA ` and ` RECORD_AUDIO ` permissions.
170
212
171
213
### Additional Tips
@@ -190,6 +232,7 @@ this library are not stripped. To do that, add these two lines to `proguard-rule
190
232
```
191
233
192
234
## Docs
235
+
193
236
You can see the documentation [ here] ( ./docs ) .
194
237
195
238
## Usage
@@ -200,8 +243,8 @@ We have three important components to understand:
200
243
import {
201
244
TwilioVideo ,
202
245
TwilioVideoLocalView ,
203
- TwilioVideoParticipantView
204
- } from ' react-native-twilio-video-webrtc'
246
+ TwilioVideoParticipantView ,
247
+ } from " react-native-twilio-video-webrtc" ;
205
248
```
206
249
207
250
- ` TwilioVideo ` / is responsible for connecting to rooms, events delivery and camera/audio.
@@ -210,62 +253,62 @@ import {
210
253
211
254
Here you can see a complete example of a simple application that uses almost all the apis:
212
255
213
- ```` javascript
214
- import React , { Component , useRef } from ' react' ;
256
+ ``` javascript
257
+ import React , { Component , useRef } from " react" ;
215
258
import {
216
259
TwilioVideoLocalView ,
217
260
TwilioVideoParticipantView ,
218
- TwilioVideo
219
- } from ' react-native-twilio-video-webrtc' ;
261
+ TwilioVideo ,
262
+ } from " react-native-twilio-video-webrtc" ;
220
263
221
264
const Example = (props ) => {
222
265
const [isAudioEnabled , setIsAudioEnabled ] = useState (true );
223
266
const [isVideoEnabled , setIsVideoEnabled ] = useState (true );
224
- const [status , setStatus ] = useState (' disconnected' );
267
+ const [status , setStatus ] = useState (" disconnected" );
225
268
const [participants , setParticipants ] = useState (new Map ());
226
269
const [videoTracks , setVideoTracks ] = useState (new Map ());
227
- const [token , setToken ] = useState (' ' );
270
+ const [token , setToken ] = useState (" " );
228
271
const twilioRef = useRef (null );
229
272
230
273
const _onConnectButtonPress = () => {
231
274
twilioRef .current .connect ({ accessToken: token });
232
- setStatus (' connecting' );
233
- }
234
-
275
+ setStatus (" connecting" );
276
+ };
277
+
235
278
const _onEndButtonPress = () => {
236
279
twilioRef .current .disconnect ();
237
280
};
238
281
239
282
const _onMuteButtonPress = () => {
240
283
twilioRef .current
241
284
.setLocalAudioEnabled (! isAudioEnabled)
242
- .then (isEnabled => setIsAudioEnabled (isEnabled));
285
+ .then (( isEnabled ) => setIsAudioEnabled (isEnabled));
243
286
};
244
287
245
288
const _onFlipButtonPress = () => {
246
289
twilioRef .current .flipCamera ();
247
290
};
248
291
249
- const _onRoomDidConnect = ({roomName, error}) => {
250
- console .log (' onRoomDidConnect: ' , roomName);
292
+ const _onRoomDidConnect = ({ roomName, error }) => {
293
+ console .log (" onRoomDidConnect: " , roomName);
251
294
252
- setStatus (' connected' );
295
+ setStatus (" connected" );
253
296
};
254
297
255
298
const _onRoomDidDisconnect = ({ roomName, error }) => {
256
- console .log (' [Disconnect]ERROR: ' , error);
299
+ console .log (" [Disconnect]ERROR: " , error);
257
300
258
- setStatus (' disconnected' );
301
+ setStatus (" disconnected" );
259
302
};
260
303
261
- const _onRoomDidFailToConnect = error => {
262
- console .log (' [FailToConnect]ERROR: ' , error);
304
+ const _onRoomDidFailToConnect = ( error ) => {
305
+ console .log (" [FailToConnect]ERROR: " , error);
263
306
264
- setStatus (' disconnected' );
307
+ setStatus (" disconnected" );
265
308
};
266
309
267
310
const _onParticipantAddedVideoTrack = ({ participant, track }) => {
268
- console .log (' onParticipantAddedVideoTrack: ' , participant, track);
311
+ console .log (" onParticipantAddedVideoTrack: " , participant, track);
269
312
270
313
setVideoTracks (
271
314
new Map ([
@@ -274,12 +317,12 @@ const Example = (props) => {
274
317
track .trackSid ,
275
318
{ participantSid: participant .sid , videoTrackSid: track .trackSid },
276
319
],
277
- ]),
320
+ ])
278
321
);
279
322
};
280
323
281
324
const _onParticipantRemovedVideoTrack = ({ participant, track }) => {
282
- console .log (' onParticipantRemovedVideoTrack: ' , participant, track);
325
+ console .log (" onParticipantRemovedVideoTrack: " , participant, track);
283
326
284
327
const videoTracksLocal = videoTracks;
285
328
videoTracksLocal .delete (track .trackSid );
@@ -289,84 +332,78 @@ const Example = (props) => {
289
332
290
333
return (
291
334
< View style= {styles .container }>
292
- {
293
- status === ' disconnected' &&
335
+ {status === " disconnected" && (
294
336
< View>
295
- < Text style= {styles .welcome }>
296
- React Native Twilio Video
297
- < / Text >
337
+ < Text style= {styles .welcome }> React Native Twilio Video< / Text >
298
338
< TextInput
299
339
style= {styles .input }
300
- autoCapitalize= ' none'
340
+ autoCapitalize= " none"
301
341
value= {token}
302
- onChangeText= {(text ) => setToken (text)}>
303
- < / TextInput>
342
+ onChangeText= {(text ) => setToken (text)}
343
+ > </ TextInput>
304
344
< Button
305
345
title= " Connect"
306
346
style= {styles .button }
307
- onPress= {_onConnectButtonPress}>
308
- < / Button>
347
+ onPress= {_onConnectButtonPress}
348
+ > </ Button>
309
349
< / View>
310
- }
350
+ ) }
311
351
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" && (
317
355
< 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
+ })}
329
365
< / View>
330
- }
331
- < View
332
- style= {styles .optionsContainer }>
366
+ )}
367
+ < View style= {styles .optionsContainer }>
333
368
< TouchableOpacity
334
369
style= {styles .optionButton }
335
- onPress= {_onEndButtonPress}>
336
- < Text style= {{fontSize: 12 }}> End< / Text >
370
+ onPress= {_onEndButtonPress}
371
+ >
372
+ < Text style= {{ fontSize: 12 }}> End< / Text >
337
373
< / TouchableOpacity>
338
374
< TouchableOpacity
339
375
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 >
342
381
< / TouchableOpacity>
343
382
< TouchableOpacity
344
383
style= {styles .optionButton }
345
- onPress= {_onFlipButtonPress}>
346
- < Text style= {{fontSize: 12 }}> Flip< / Text >
384
+ onPress= {_onFlipButtonPress}
385
+ >
386
+ < Text style= {{ fontSize: 12 }}> Flip< / Text >
347
387
< / TouchableOpacity>
348
- < TwilioVideoLocalView
349
- enabled= {true }
350
- style= {styles .localVideo }
351
- / >
388
+ < TwilioVideoLocalView enabled= {true } style= {styles .localVideo } / >
352
389
< / View>
353
390
< / View>
354
- }
391
+ ) }
355
392
356
393
< 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}
363
400
/ >
364
401
< / View>
365
402
);
366
- }
403
+ };
367
404
368
- AppRegistry .registerComponent (' Example' , () => Example);
369
- ````
405
+ AppRegistry .registerComponent (" Example" , () => Example);
406
+ ```
370
407
371
408
## Run the Example Application
372
409
@@ -379,18 +416,18 @@ To run the example application:
379
416
380
417
## Migrating from 1.x to 2.x
381
418
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:
383
420
384
421
```
385
422
s.dependency 'TwilioVideo', '~> 2.2.0'
386
423
```
387
424
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 ` ).
392
429
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 ` .
394
431
395
432
## Contact
396
433
0 commit comments