README.md

Getting Started

yarn install

Running on iOS Device

  • Open the project MyExample/ios/MyExample.xcworkspace in Xcode
  • Ensure that in pod Pods/react_native_awesome_module Build Phases -> Link Binary With Library contains the EdgeCenterVideoCallsSDK framework.
  • Select your device in Xcode and press “Build and run” ​

    Running on Android Device

  • Run Android emulator or connect Android device with Android Studio
  • Open the project MyExample in terminal
  • Run command react-native run-android ​ ​

    How to use SDK with react-native

    Android

    Import SDK to Android project

    Place SDK in your project.
    Change settings.gradle file (located in android directory of your main project) with following code for include projects:

include ':EdgeCenterVideoCallsSDK'
project(':EdgeCenterVideoCallsSDK').projectDir = new File(rootProject.projectDir, '/path/to/SDK/folder')

Add dependency to your build.gradle (located in android directory located in root of your project)

implementation 'com.twilio:audioswitch:1.1.5'
implementation "io.github.crow-misia.libmediasoup-android:libmediasoup-android:0.10.0"
implementation project(":EdgeCenterVideoCallsSDK")

Implementation native module

Create native module by official react-native docs
In that module you have to implement functions that you want to use from SDK in your JS application
First step to use SDK is ECSession.instance.init function
Init SDK function from our example application:

  init {
    runOnUiThread {
      ECSession.instance.init(application)
    }
  }

How you can see you need to pass application as parameter to init SDK function, for do that you may pass application to your module from your package:

class MyAppPackage(private val application: Application) : ReactPackage {
    //...
  override fun createNativeModules(
    reactContext: ReactApplicationContext
  ): MutableList<NativeModule> = listOf(ECVideoCallsService(reactContext, application)).toMutableList()
}

And pass application to your package from your MainApplication (located in android directory of your main project):

public class MainApplication extends Application implements ReactApplication {
    private final ReactNativeHost mReactNativeHost =
            new ReactNativeHost(this) {
                //...
                @Override
                protected List<ReactPackage> getPackages() {
                    List<ReactPackage> packages = new PackageList(this).getPackages();
                    packages.add(new MyAppPackage(getApplication()));
                    return packages;
                }
                //...
            };
    //...
}

For join to a room you have to set some required parameters to ECSession.instance.setConnectionParams and then call ECSession.instance.connect(reactContext)
Join user to room function from our example application:

  @ReactMethod
  fun openConnection(options: ReadableMap) {
    runOnUiThread {

      val userRole = when (options.getString("role") ?: "") {
        "common" -> UserRole.COMMON
        "moderator" -> UserRole.MODERATOR
        else -> UserRole.UNKNOWN
      }

      val userInfo = LocalUserInfo(
        displayName = options.getString("displayName") ?: "User${Utils.getRandomString(3)}",
        role = userRole,
        userId = options.getString("userId") ?: Utils.getRandomString(DEFAULT_LENGTH_RANDOM_STRING)
      )

      val roomParams = RoomParams(
        roomId = options.getString("roomId") ?: "",
        hostName = options.getString("clientHostName") ?: "",
        startWithCam = options.getBoolean("isVideoOn"),
        startWithMic = options.getBoolean("isAudioOn")
      )

      ECSession.instance.setConnectionParams(userInfo, roomParams)
      ECSession.instance.connect(reactContext)
    }
  }

Make sure that SDK functions ECSession.instance.init and ECSession.instance.connect running in UI Thread

You have to use view components from SDK in your react-native application LocalVideoTextureView - to show local video stream RemoteUserVideoView - to show remote video stream

Create view manager for LocalVideoTextureView by example:

class GCLocalViewManager(var mCallerContext: ReactApplicationContext) :
  SimpleViewManager<LocalVideoTextureView>() {

  override fun getName(): String {
    return "GCLocalView"
  }

  override fun createViewInstance(reactContext: ThemedReactContext): LocalVideoTextureView {
    return LocalVideoTextureView(reactContext.baseContext)
  }
}

Use RemoteUserVideoView by example:

class GCRemoteViewManager(var mCallerContext: ReactApplicationContext) :
  SimpleViewManager<RemoteUserVideoView>() {

  override fun getName(): String {
    return "GCRemoteView"
  }

  override fun onDropViewInstance(view: RemoteUserVideoView) {
    view.release()
    super.onDropViewInstance(view)
  }

  override fun createViewInstance(reactContext: ThemedReactContext): RemoteUserVideoView {
    val view = RemoteUserVideoView(reactContext.baseContext)

    ECSession.instance.roomState.remoteUsers.observeForever { remoteUsers ->
      remoteUsers?.list?.let { users ->
        if (users.isNotEmpty()) {
          LLog.d("ReactRemoteViewManager", "connect remote user: ${users[0].id}")
          view.connect(users[0].id)
        }
      }
    }
    return view
  }
}

You have to call function connect for RemoteUserVideoView and pass userId into
You can get userId from ECSession.instance.roomState.remoteUsers by example above

Add permissions in AndroidManifest.xml

    <manifestPermissions>
      <!-- Needed to communicate with already-paired Bluetooth devices. (Legacy up to Android 11) -->
      <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
      <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
      <!-- Needed to communicate with already-paired Bluetooth devices. (Android 12 upwards)-->
      <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
      <uses-permission android:name="android.permission.READ_PHONE_STATE" />
      <uses-permission android:name="android.permission.INTERNET" />
      <uses-permission android:name="android.permission.CALL_PHONE" />
      <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    </manifestPermissions>

IOS

Implementation native module

Create native module by official react-native docs
In that module you have to implement functions that you want to use from SDK in your JS application
For join to a room you have to set some required parameters to ECSession.shared.connectionParams and then call ECSession.shared.startConnection()
Join user to room function from our example application:

    private var client = ECSession.shared
    private var joinOptions: ConnectionOptions!

    private var isConnectedOpponent = false

    @objc
    func openConnection(_ options: NSDictionary) {
        ECRoomLogger.activateLogger()

        client.cameraParams = ECCameraParams(cameraPosition: .front)

        var userRole: ECUserRole
        if let role = options["role"]  {
            switch role as! String {
            case "common": userRole = .common
            case "moderator": userRole = .moderator
            default: userRole = .unknown
          }
        } else {
            userRole = .unknown
        }

        let localUserParams = ECLocalUserParams(
            name: options["displayName"] as! String,
            role: userRole)

        let roomParams = ECRoomParams(
            id: options["roomId"] as! String,
            host: options["clientHostName"] as? String)

        client.connectionParams = (localUserParams, roomParams)

        joinOptions = ConnectionOptions(
            isVideoOn: options["isVideoOn"] as! Bool,
            isAudioOn: options["isAudioOn"] as! Bool,
            blurSigma: options["blurSigma"] as! Double
        )

        try? client.startConnection()
        client.audioSessionActivate()
        client.roomListener = self
    }

Implement roomListener if you want to have some callbacks:

extension ECVideoCallsService: ECRoomListener {
    //...
    func roomClientHandle(_ client: ECRoomClient, mediaEvent: ECMediaEvent) {
        switch mediaEvent {

        case .produceLocalVideo(track: let track):
            print("RoomListener: produceLocalVideoTrack:", track)
            DispatchQueue.main.async {
                track.add(GCViewsEnum.local)
            }
        case .produceLocalAudio(track: let track):
            print("produceLocalAudio: ", track)
        case .didCloseLocalVideo(track: let track):
            print("didCloseLocalVideo: ", track ?? "nil")
            DispatchQueue.main.async {
                track?.remove(GCViewsEnum.local)
            }
    //...

You can use view components RTCEAGLVideoView from WebRTC in your react-native application

Create views enum by example:

import WebRTC

enum GCViewsEnum {
     public static let local: RTCEAGLVideoView = RTCEAGLVideoView()
     public static let remote: RTCEAGLVideoView = RTCEAGLVideoView()
}

And then create local view component GCLocalViewManager by example:

import Foundation

@objc(GCLocalViewManager)
class GCLocalViewManager: RCTViewManager {

  override func view() -> UIView! {
    return GCViewsEnum.local
  }

  @objc override static func requiresMainQueueSetup() -> Bool {
    return true
  }
}

And remote view component:

import Foundation

@objc(GCRemoteViewManager)
class GCRemoteViewManager: RCTViewManager {

  override func view() -> UIView! {
    return GCViewsEnum.remote
  }

  @objc override static func requiresMainQueueSetup() -> Bool {
    return true
  }
}

Using native module functions in your js

Example usage openConnection function from native module to join to room:

    import { NativeModules } from 'react-native';
    // ...
    NativeModules.ECVideoCallsService.openConnection({
            roomId: 'serv1234',
            displayName: 'Client from react native',
            isAudioOn: true,
            isVideoOn: true,
            isModerator: false,
          });

Create two components for views:
Local view component example:

interface ViewProps extends PropsWithChildren<any> {
  style: StyleProp<ViewStyle>;
}
const GCLocalView = requireNativeComponent<ViewProps>('GCLocalView');
export default GCLocalView;

​ Remote view component example:

interface ViewProps extends PropsWithChildren<any> {
  style: StyleProp<ViewStyle>;
}
const GCRemoteView = requireNativeComponent<ViewProps>('GCRemoteView');
export default GCRemoteView;

​ Now you can use them in your call screen:

 return (
    <View style={styles.root}>
      <View style={styles.container}>
        <View>
          {videoOn && (
            <View>
              <GCLocalView style={[styles.mirror, styles.preview]} />
            </View>
          )}
        //...
        </View>
      </View>
      <GCRemoteView style={[styles.remote, getTransform()]} />
    </View>
  );
Конвейеры
0 успешных
0 с ошибкой