LiveKit React Native SDK

repository·main·Indexed 43 days ago

https://github.com/livekit/client-sdk-react-native

A React Native client SDK for LiveKit (version 3.0.0) that enables real-time audio and video communication. It provides support for screensharing, background processing on Android and iOS, and End-to-End Encryption (E2EE) via the useRNE2EEManager hook. The SDK includes the LiveKitRoom component, AudioSession management, and hooks like useTracks for rendering video tracks.

Tokens
13K
Snippets
39
Records
51
Agent score
53%

What's inside LiveKit

  1. Use End-to-End Encryption (E2EE) with useRNE2EEManager

    main

    The example app demonstrates how to implement End-to-End Encryption (E2EE) using the useRNE2EEManager hook.

    To enable E2EE:

    1. Toggle the E2EE setting in the pre-join screen.
    2. Provide an encryption key.

    When enabled, all audio and video tracks within the room will be end-to-end encrypted.

  2. Run and test changes using the example app

    main

    You can use the included example app to verify your changes.

    • JavaScript changes: Reflected in the example app automatically without a rebuild.
    • Native code changes: Require a rebuild of the example app.

    Commands

    TaskCommand
    Start Metro packageryarn example start
    Run on Androidyarn example android
    Run on iOSyarn example ios

    Native Code Editing

    • iOS (Objective-C): Open example/ios/LivekitReactNativeExample.xcworkspace in Xcode. Source files are located at Pods > Development Pods > livekit-react-native.
    • Android (Kotlin): Open example/android in Android Studio. Source files are located at livekitreactnative under Android.
    yarn example start
    
    yarn example android
    
    yarn example ios
  3. Configure LiveKit on iOS (Native Setup)

    main

    Initialize the LiveKit native module in your AppDelegate file. This must be placed above any other React Native initialization.

    Swift Implementation

    In AppDelegate.swift:

    import livekit_react_native
    import livekit_react_native_webrtc
    
    @main
    class AppDelegate: UIResponder, UIApplicationDelegate {
      func application(
        _ application: UIApplication, 
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
      ) -> Bool {
        // Place this above any other RN related initialization
        LivekitReactNative.setup()
        // ...
      }
    }

    Objective-C Implementation

    In AppDelegate.m:

    #import "LivekitReactNative.h"
    #import "WebRTCModuleOptions.h"
    
    @implementation AppDelegate
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
      // Place this above any other RN related initialization
      [LivekitReactNative setup];
      // ...
    }
    @end

    Background Camera Access (iOS 18+): To use the camera in the background, you require the voip background mode and must enable multitasking camera access via WebRTCModuleOptions:

    // Objective-C
    WebRTCModuleOptions *options = [WebRTCModuleOptions sharedInstance];
    options.enableMultitaskingCameraAccess = YES;
    // Swift
    let options = WebRTCModuleOptions.sharedInstance()
    options.enableMultitaskingCameraAccess = true
    import livekit_react_native
    import livekit_react_native_webrtc
    
    @main
    class AppDelegate: UIResponder, UIApplicationDelegate {
      func application(
        _ application: UIApplication, 
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
      ) -> Bool {
        LivekitReactNative.setup()
        return true
      }
    }
  4. Initialize LiveKit with registerGlobals()

    main

    In your index.js file, you must call registerGlobals() to set up the required WebRTC libraries for use in JavaScript. This is a mandatory step for LiveKit to function.

    import { registerGlobals } from '@livekit/react-native';
    
    registerGlobals();
    import { registerGlobals } from '@livekit/react-native';
    
    registerGlobals();
  5. Configure Background Processing on iOS

    main

    To maintain a LiveKit connection in the background on iOS, use one of the following methods:

    1. Basic Backgrounding: Enable audio and voip in the UIBackgroundModes of your Xcode project (Target -> Signing & Capabilities -> Background Modes). This keeps the app alive as long as an audio track or microphone is active.
    2. Robust Backgrounding (Recommended): Use CallKit to maintain the connection. The library react-native-callkeep is suggested for integration.

    Important: If using CallKit to handle incoming calls, you must call RTCAudioSession.audioSessionDidActivate and RTCAudioSession.audioSessionDidDeactivate when the call provider activates or deactivates the audio session.

  6. Enable Screenshare on Android

    main

    To enable screensharing on Android, you must declare the mediaProjection foreground service permission in your AndroidManifest.xml. While the SDK handles the foreground service internally from version 2.4.0 onwards, the permission declaration is still required.

    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" />
  7. Enable Screenshare on iOS

    main

    iOS screensharing requires a Broadcast Extension.

    1. Integration: Follow the Jitsi Broadcast Extension integration guide. This involves copying specific files from a sample project into your iOS project and registering a Broadcast Extension in Xcode.
    2. Background Stability: It is highly recommended to use CallKeep to register calls with CallKit and enable the voip background mode. This prevents the app from being restricted in the background, which would otherwise interrupt screen recording.
    3. Implementation: You must include a ScreenCapturePickerView in your view tree and use NativeModules.ScreenCapturePickerViewManager.show to trigger the picker before enabling screen share via the participant API.

    Note: Camera and microphone tracks cannot be published on the iOS Simulator.

    const screenCaptureRef = React.useRef(null);
    const screenCapturePickerView = Platform.OS === 'ios' && (
      <ScreenCapturePickerView ref={screenCaptureRef} />
    );
    
    const startBroadcast = async () => {
      if (Platform.OS === 'ios') {
        const reactTag = findNodeHandle(screenCaptureRef.current);
        await NativeModules.ScreenCapturePickerViewManager.show(reactTag);
        room.localParticipant.setScreenShareEnabled(true);
      } else {
        room.localParticipant.setScreenShareEnabled(true);
      }
    };
    
    return (
      <View style={styles.container}>
        {/* Make sure the ScreenCapturePickerView exists in the view tree. */}
        {screenCapturePickerView}
      </View>
    );
  8. Install the LiveKit React Native SDK

    main

    To install the LiveKit React Native SDK, you must install the core SDK, the WebRTC dependency, and the livekit-client package.

    NPM

    npm install @livekit/react-native @livekit/react-native-webrtc livekit-client

    Yarn

    yarn add @livekit/react-native @livekit/react-native-webrtc livekit-client

    Note: This library depends on @livekit/react-native-webrtc, which requires additional platform-specific installation steps for iOS and Android.

  9. Use LiveKitRoom and hooks to build a video app

    main

    The LiveKitRoom component manages the Room object and provides context for LiveKit hooks. To build a functional app, follow these steps:

    1. Initialize Globals: Call registerGlobals() in index.js.
    2. Manage Audio Session: Use AudioSession.startAudioSession() and AudioSession.stopAudioSession() within a useEffect hook to manage the native audio lifecycle.
    3. Wrap with LiveKitRoom: Provide serverUrl, token, and connection options.
    4. Consume Tracks: Use the useTracks hook to retrieve tracks (e.g., Track.Source.Camera) and the VideoTrack component to render them.
    import * as React from 'react';
    import { View, FlatList, StyleSheet } from 'react-native';
    import { 
      AudioSession, 
      LiveKitRoom, 
      useTracks, 
      VideoTrack, 
      isTrackReference, 
      registerGlobals 
    } from '@livekit/react-native';
    import { Track } from 'livekit-client';
    
    const wsURL = "wss://example.com";
    const token = "your-token-here";
    
    export default function App() {
      React.useEffect(() => {
        let start = async () => {
          await AudioSession.startAudioSession();
        };
        start();
        return () => {
          AudioSession.stopAudioSession();
        };
      }, []);
    
      return (
        <LiveKitRoom
          serverUrl={wsURL}
          token={token}
          connect={true}
          options={{ adaptiveStream: { pixelDensity: 'screen' } }}
          audio={true}
          video={true}
        >
          <RoomView />
        </LiveKitRoom>
      );
    }
    
    const RoomView = () => {
      const tracks = useTracks([Track.Source.Camera]);
    
      const renderTrack = ({item}) => {
        if(isTrackReference(item)) {
          return (<VideoTrack trackRef={item} style={styles.participantView} />);
        } else {
          return (<View style={styles.participantView} />);
        }
      };
    
      return (
        <View style={styles.container}>
          <FlatList data={tracks} renderItem={renderTrack} />
        </View>
      );
    };
    
    const styles = StyleSheet.create({
      container: { flex: 1, alignItems: 'stretch', justifyContent: 'center' },
      participantView: { height: 300 },
    });
    import { registerGlobals, LiveKitRoom, useTracks, VideoTrack, isTrackReference, AudioSession } from '@livekit/react-native';
    import { Track } from 'livekit-client';
    
    // 1. registerGlobals() in index.js
    // 2. Use LiveKitRoom to manage connection
    // 3. Use useTracks() to get tracks
    // 4. Use VideoTrack to render