OpenTok SDK applied and method channels written to native

merge-requests/437/head
Zohaib Iqbal Kambrani 3 years ago
parent 57a3c2a04c
commit d0986fcaf6

@ -107,7 +107,10 @@ dependencies {
implementation 'com.github.kittinunf.fuel:fuel:2.3.0' //for JVM
implementation 'com.github.kittinunf.fuel:fuel-android:2.3.0'
implementation 'com.google.android.gms:play-services-location:17.1.0'//for Android
implementation 'com.google.android.gms:play-services-basement:17.5.0'
implementation 'com.google.android.gms:play-services-basement:17.5.0'
implementation "com.opentok.android:opentok-android-sdk:2.19.1"
}

@ -4,15 +4,16 @@ import android.util.Log
import androidx.annotation.NonNull;
import com.ejada.hmg.utils.*
import io.flutter.embedding.android.FlutterFragmentActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugins.GeneratedPluginRegistrant
class MainActivity: FlutterFragmentActivity() {
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);
// Create Flutter Platform Bridge
PlatformBridge(flutterEngine.dartExecutor.binaryMessenger, this).create()
GeneratedPluginRegistrant.registerWith(flutterEngine);
// Create Flutter Platform Bridge
PlatformBridge(flutterEngine, this).create()
OpenTokPlatformBridge(flutterEngine, this).create()
val time = timeToMillis("04:00:00", "HH:mm:ss")
@ -24,7 +25,7 @@ class MainActivity: FlutterFragmentActivity() {
// val d5 = Logs.GeofenceEvent.list(this)
// val d6 = Logs.GeofenceEvent.raw(this)
}
}
override fun onResume() {
super.onResume()

@ -0,0 +1,170 @@
package com.example.basic_video_chat_flutter
import android.content.Context
import android.os.Handler
import android.os.Looper
import android.util.AttributeSet
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.LinearLayout
import com.opentok.android.*
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.StandardMessageCodec
import io.flutter.plugin.platform.PlatformView
import io.flutter.plugin.platform.PlatformViewFactory
enum class SdkState {
LOGGED_OUT,
LOGGED_IN,
WAIT,
ERROR
}
class OpenTok(private var context: Context, private var flutterEngine: FlutterEngine){
private lateinit var opentokVideoPlatformView: OpentokVideoPlatformView
init {
opentokVideoPlatformView = OpentokVideoFactory.getViewInstance(context)
flutterEngine
.platformViewsController
.registry
// opentok-video-container is a custom platform-view-type
.registerViewFactory("opentok-video-container", OpentokVideoFactory())
}
private var session: Session? = null
private var publisher: Publisher? = null
private var subscriber: Subscriber? = null
private val sessionListener: Session.SessionListener = object: Session.SessionListener {
override fun onConnected(session: Session) {
// Connected to session
Log.d("MainActivity", "Connected to session ${session.sessionId}")
publisher = Publisher.Builder(context).build().apply {
setPublisherListener(publisherListener)
renderer?.setStyle(BaseVideoRenderer.STYLE_VIDEO_SCALE, BaseVideoRenderer.STYLE_VIDEO_FILL)
view.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
opentokVideoPlatformView.publisherContainer.addView(view)
}
notifyFlutter(SdkState.LOGGED_IN)
session.publish(publisher)
}
override fun onDisconnected(session: Session) {
notifyFlutter(SdkState.LOGGED_OUT)
}
override fun onStreamReceived(session: Session, stream: Stream) {
Log.d(
"MainActivity",
"onStreamReceived: New Stream Received " + stream.streamId + " in session: " + session.sessionId
)
if (subscriber == null) {
subscriber = Subscriber.Builder(context, stream).build().apply {
renderer?.setStyle(BaseVideoRenderer.STYLE_VIDEO_SCALE, BaseVideoRenderer.STYLE_VIDEO_FILL)
setSubscriberListener(subscriberListener)
session.subscribe(this)
opentokVideoPlatformView.subscriberContainer.addView(view)
}
}
}
override fun onStreamDropped(session: Session, stream: Stream) {
Log.d(
"MainActivity",
"onStreamDropped: Stream Dropped: " + stream.streamId + " in session: " + session.sessionId
)
if (subscriber != null) {
subscriber = null
opentokVideoPlatformView.subscriberContainer.removeAllViews()
}
}
override fun onError(session: Session, opentokError: OpentokError) {
Log.d("MainActivity", "Session error: " + opentokError.message)
notifyFlutter(SdkState.ERROR)
}
}
private val publisherListener: PublisherKit.PublisherListener = object : PublisherKit.PublisherListener {
override fun onStreamCreated(publisherKit: PublisherKit, stream: Stream) {
Log.d("MainActivity", "onStreamCreated: Publisher Stream Created. Own stream " + stream.streamId)
}
override fun onStreamDestroyed(publisherKit: PublisherKit, stream: Stream) {
Log.d("MainActivity", "onStreamDestroyed: Publisher Stream Destroyed. Own stream " + stream.streamId)
}
override fun onError(publisherKit: PublisherKit, opentokError: OpentokError) {
Log.d("MainActivity", "PublisherKit onError: " + opentokError.message)
notifyFlutter(SdkState.ERROR)
}
}
var subscriberListener: SubscriberKit.SubscriberListener = object : SubscriberKit.SubscriberListener {
override fun onConnected(subscriberKit: SubscriberKit) {
Log.d("MainActivity", "onConnected: Subscriber connected. Stream: " + subscriberKit.stream.streamId)
}
override fun onDisconnected(subscriberKit: SubscriberKit) {
Log.d("MainActivity", "onDisconnected: Subscriber disconnected. Stream: " + subscriberKit.stream.streamId)
notifyFlutter(SdkState.LOGGED_OUT)
}
override fun onError(subscriberKit: SubscriberKit, opentokError: OpentokError) {
Log.d("MainActivity", "SubscriberKit onError: " + opentokError.message)
notifyFlutter(SdkState.ERROR)
}
}
fun initSession(call: MethodCall, result: MethodChannel.Result) {
val apiKey = requireNotNull(call.argument<String>("apiKey"))
val sessionId = requireNotNull(call.argument<String>("sessionId"))
val token = requireNotNull(call.argument<String>("token"))
notifyFlutter(SdkState.WAIT)
session = Session.Builder(context, apiKey, sessionId).build()
session?.setSessionListener(sessionListener)
session?.connect(token)
result.success("")
}
fun swapCamera(call: MethodCall, result: MethodChannel.Result) {
publisher?.cycleCamera()
result.success("")
}
fun toggleAudio(call: MethodCall, result: MethodChannel.Result) {
val publishAudio = requireNotNull(call.argument<Boolean>("publishAudio"))
publisher?.publishAudio = publishAudio
result.success("")
}
fun toggleVideo(call: MethodCall, result: MethodChannel.Result) {
val publishVideo = requireNotNull(call.argument<Boolean>("publishVideo"))
publisher?.publishVideo = publishVideo
result.success("")
}
private fun notifyFlutter(state: SdkState) {
Handler(Looper.getMainLooper()).post {
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "OpenTok-Platform-Bridge")
.invokeMethod("updateState", state.toString())
}
}
}

@ -0,0 +1,63 @@
package com.example.basic_video_chat_flutter
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.widget.FrameLayout
import android.widget.LinearLayout
import io.flutter.plugin.common.StandardMessageCodec
import io.flutter.plugin.platform.PlatformView
import io.flutter.plugin.platform.PlatformViewFactory
class OpentokVideoFactory : PlatformViewFactory(StandardMessageCodec.INSTANCE) {
companion object {
private lateinit var view: OpentokVideoPlatformView
fun getViewInstance(context: Context): OpentokVideoPlatformView {
if(!this::view.isInitialized) {
view = OpentokVideoPlatformView(context)
}
return view
}
}
override fun create(context: Context, viewId: Int, args: Any?): PlatformView {
return getViewInstance(context)
}
}
class OpentokVideoPlatformView(context: Context) : PlatformView {
private val videoContainer: OpenTokVideoContainer = OpenTokVideoContainer(context)
val subscriberContainer get() = videoContainer.subscriberContainer
val publisherContainer get() = videoContainer.publisherContainer
override fun getView(): View {
return videoContainer
}
override fun dispose() {}
}
class OpenTokVideoContainer @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyle: Int = 0,
defStyleRes: Int = 0
) : LinearLayout(context, attrs, defStyle, defStyleRes) {
var subscriberContainer: FrameLayout
private set
var publisherContainer: FrameLayout
private set
init {
val view = LayoutInflater.from(context).inflate(R.layout.view_video, this, true)
subscriberContainer = view.findViewById(R.id.subscriber_container)
publisherContainer = view.findViewById(R.id.publisher_container)
}
}

@ -0,0 +1,50 @@
package com.ejada.hmg.utils
import android.content.Context
import android.net.wifi.WifiManager
import android.util.Log
import com.ejada.hmg.MainActivity
import com.ejada.hmg.hmgwifi.HMG_Guest
import com.ejada.hmg.hmgwifi.HMG_Internet
import com.ejada.hmg.geofence.GeoZoneModel
import com.ejada.hmg.geofence.HMG_Geofence
import com.example.basic_video_chat_flutter.OpenTok
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
class OpenTokPlatformBridge(private var flutterEngine: FlutterEngine, private var mainActivity: MainActivity) {
private lateinit var channel: MethodChannel
private lateinit var openTok: OpenTok
companion object {
private const val CHANNEL = "OpenTok-Platform-Bridge"
}
fun create(){
openTok = OpenTok(mainActivity, flutterEngine)
channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
channel.setMethodCallHandler { call: MethodCall, result: MethodChannel.Result ->
when (call.method) {
"initSession" -> {
openTok.initSession(call, result)
}
"swapCamera" -> {
openTok.swapCamera(call, result)
}
"toggleAudio" -> {
openTok.toggleAudio(call, result)
}
"toggleVideo" -> {
openTok.toggleVideo(call, result)
}
else -> {
result.notImplemented()
}
}
}
}
}

@ -8,13 +8,12 @@ import com.ejada.hmg.hmgwifi.HMG_Guest
import com.ejada.hmg.hmgwifi.HMG_Internet
import com.ejada.hmg.geofence.GeoZoneModel
import com.ejada.hmg.geofence.HMG_Geofence
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
class PlatformBridge(binaryMessenger: BinaryMessenger, flutterMainActivity: MainActivity) {
private var binaryMessenger = binaryMessenger
private var mainActivity = flutterMainActivity
class PlatformBridge(private var flutterEngine: FlutterEngine, private var mainActivity: MainActivity) {
private lateinit var channel: MethodChannel
@ -28,7 +27,7 @@ class PlatformBridge(binaryMessenger: BinaryMessenger, flutterMainActivity: Main
}
fun create(){
channel = MethodChannel(binaryMessenger, CHANNEL)
channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
HMGUtils.setPlatformChannel(channel)
channel.setMethodCallHandler { methodCall: MethodCall, result: MethodChannel.Result ->

@ -23,7 +23,12 @@ allprojects {
google()
// jcenter()
mavenCentral()
maven { url 'https://developer.huawei.com/repo/' }
maven {
url 'https://developer.huawei.com/repo/'
}
maven{
url "https://artifactory.ess-dev.com/artifactory/gradle-dev-local"
}
}
}

@ -1 +1 @@
e52eba3667a38bec777870899c15ae7d
3f3d14a0ae775b56806906c2cb14a1f0

@ -42,6 +42,7 @@ target 'Runner' do
# Native Pods
pod 'NVActivityIndicatorView'
pod 'OpenTok'
# Flutter Pod

@ -370,6 +370,10 @@ PODS:
- Flutter
- flutter_tts (0.0.1):
- Flutter
- flutter_webrtc (0.2.2):
- Flutter
- GoogleWebRTC (= 1.1.31999)
- Libyuv (= 1703)
- FMDB (2.7.5):
- FMDB/standard (= 2.7.5)
- FMDB/standard (2.7.5)
@ -410,6 +414,7 @@ PODS:
- GoogleUtilities/Logger
- GoogleUtilities/UserDefaults (6.7.2):
- GoogleUtilities/Logger
- GoogleWebRTC (1.1.31999)
- "gRPC-C++ (1.28.2)":
- "gRPC-C++/Implementation (= 1.28.2)"
- "gRPC-C++/Interface (= 1.28.2)"
@ -438,6 +443,8 @@ PODS:
- Flutter
- "huawei_location (5.0.0+301)":
- Flutter
- "huawei_map (5.0.3+303)":
- Flutter
- image_cropper (0.0.3):
- Flutter
- TOCropViewController (~> 2.5.4)
@ -446,6 +453,7 @@ PODS:
- just_audio (0.0.1):
- Flutter
- leveldb-library (1.22)
- Libyuv (1703)
- local_auth (0.0.1):
- Flutter
- location (0.0.1):
@ -469,6 +477,7 @@ PODS:
- NVActivityIndicatorView (5.1.1):
- NVActivityIndicatorView/Base (= 5.1.1)
- NVActivityIndicatorView/Base (5.1.1)
- OpenTok (2.20.0)
- path_provider (0.0.1):
- Flutter
- path_provider_linux (0.0.1):
@ -562,10 +571,12 @@ DEPENDENCIES:
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
- flutter_plugin_android_lifecycle (from `.symlinks/plugins/flutter_plugin_android_lifecycle/ios`)
- flutter_tts (from `.symlinks/plugins/flutter_tts/ios`)
- flutter_webrtc (from `.symlinks/plugins/flutter_webrtc/ios`)
- geolocator (from `.symlinks/plugins/geolocator/ios`)
- google_maps_flutter (from `.symlinks/plugins/google_maps_flutter/ios`)
- hexcolor (from `.symlinks/plugins/hexcolor/ios`)
- huawei_location (from `.symlinks/plugins/huawei_location/ios`)
- huawei_map (from `.symlinks/plugins/huawei_map/ios`)
- image_cropper (from `.symlinks/plugins/image_cropper/ios`)
- image_picker (from `.symlinks/plugins/image_picker/ios`)
- just_audio (from `.symlinks/plugins/just_audio/ios`)
@ -577,6 +588,7 @@ DEPENDENCIES:
- native_device_orientation (from `.symlinks/plugins/native_device_orientation/ios`)
- nfc_in_flutter (from `.symlinks/plugins/nfc_in_flutter/ios`)
- NVActivityIndicatorView
- OpenTok
- path_provider (from `.symlinks/plugins/path_provider/ios`)
- path_provider_linux (from `.symlinks/plugins/path_provider_linux/ios`)
- path_provider_macos (from `.symlinks/plugins/path_provider_macos/ios`)
@ -624,12 +636,15 @@ SPEC REPOS:
- GoogleDataTransport
- GoogleMaps
- GoogleUtilities
- GoogleWebRTC
- "gRPC-C++"
- gRPC-Core
- leveldb-library
- Libyuv
- MTBBarcodeScanner
- nanopb
- NVActivityIndicatorView
- OpenTok
- PromisesObjC
- Protobuf
- Reachability
@ -688,6 +703,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/flutter_plugin_android_lifecycle/ios"
flutter_tts:
:path: ".symlinks/plugins/flutter_tts/ios"
flutter_webrtc:
:path: ".symlinks/plugins/flutter_webrtc/ios"
geolocator:
:path: ".symlinks/plugins/geolocator/ios"
google_maps_flutter:
@ -696,6 +713,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/hexcolor/ios"
huawei_location:
:path: ".symlinks/plugins/huawei_location/ios"
huawei_map:
:path: ".symlinks/plugins/huawei_map/ios"
image_cropper:
:path: ".symlinks/plugins/image_cropper/ios"
image_picker:
@ -808,6 +827,7 @@ SPEC CHECKSUMS:
flutter_local_notifications: 9e4738ce2471c5af910d961a6b7eadcf57c50186
flutter_plugin_android_lifecycle: dc0b544e129eebb77a6bfb1239d4d1c673a60a35
flutter_tts: 0f492aab6accf87059b72354fcb4ba934304771d
flutter_webrtc: 39898454258b54ba51996850d5da8d5d53bf1524
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
geolocator: f5e3de65e241caba7ce3e8a618803387bda73384
google_maps_flutter: c7f9c73576de1fbe152a227bfd6e6c4ae8088619
@ -815,14 +835,17 @@ SPEC CHECKSUMS:
GoogleDataTransport: f56af7caa4ed338dc8e138a5d7c5973e66440833
GoogleMaps: 4b5346bddfe6911bb89155d43c903020170523ac
GoogleUtilities: 7f2f5a07f888cdb145101d6042bc4422f57e70b3
GoogleWebRTC: b39a78c4f5cc6b0323415b9233db03a2faa7b0f0
"gRPC-C++": 13d8ccef97d5c3c441b7e3c529ef28ebee86fad2
gRPC-Core: 4afa11bfbedf7cdecd04de535a9e046893404ed5
hexcolor: fdfb9c4258ad96e949c2dbcdf790a62194b8aa89
huawei_location: a1c3d2a029138b3d0b9a72ce910ffae3ff23c1aa
huawei_map: 34fbad9c274ea78a4151487c9ebe27f1887777e7
image_cropper: c8f9b4157933c7bb965a66d1c5e6c8fd408c6eb4
image_picker: 9c3312491f862b28d21ecd8fdf0ee14e601b3f09
just_audio: baa7252489dbcf47a4c7cc9ca663e9661c99aafa
leveldb-library: 55d93ee664b4007aac644a782d11da33fba316f7
Libyuv: 5f79ced0ee66e60a612ca97de1e6ccacd187a437
local_auth: 25938960984c3a7f6e3253e3f8d962fdd16852bd
location: 3a2eed4dd2fab25e7b7baf2a9efefe82b512d740
manage_calendar_events: 0338d505ea26cdfd20cd883279bc28afa11eca34
@ -833,6 +856,7 @@ SPEC CHECKSUMS:
native_device_orientation: e24d00be281de72996640885d80e706142707660
nfc_in_flutter: c656fbfb1ec5b9d021da87b0c87629d62fd5264d
NVActivityIndicatorView: 1f6c5687f1171810aa27a3296814dc2d7dec3667
OpenTok: 414c2c1dc6486f1897015e4d1703558d5eed48c3
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
path_provider_linux: 4d630dc393e1f20364f3e3b4a2ff41d9674a84e4
path_provider_macos: f760a3c5b04357c380e2fddb6f9db6f3015897e0
@ -869,6 +893,6 @@ SPEC CHECKSUMS:
webview_flutter: d2b4d6c66968ad042ad94cbb791f5b72b4678a96
wifi: d7d77c94109e36c4175d845f0a5964eadba71060
PODFILE CHECKSUM: 900f7dc480de5b961c031ed418407e0e40ed455c
PODFILE CHECKSUM: df22e8ed6009dd48559053927dc365d6dad6c11f
COCOAPODS: 1.10.1

@ -8,6 +8,8 @@
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
306FE6C8271D790C002D6EFC /* OpenTokPlatformBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 306FE6C7271D790C002D6EFC /* OpenTokPlatformBridge.swift */; };
306FE6CB271D8B73002D6EFC /* OpenTok.swift in Sources */ = {isa = PBXBuildFile; fileRef = 306FE6CA271D8B73002D6EFC /* OpenTok.swift */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
813F9CBA7DD5ED63B28B8BB6 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 767C165F7ABF3BF1F829B9BF /* Pods_Runner.framework */; };
@ -50,6 +52,8 @@
/* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
306FE6C7271D790C002D6EFC /* OpenTokPlatformBridge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenTokPlatformBridge.swift; sourceTree = "<group>"; };
306FE6CA271D8B73002D6EFC /* OpenTok.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenTok.swift; sourceTree = "<group>"; };
308FEC658188F7D588BE7580 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
@ -99,6 +103,14 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
306FE6C9271D8B54002D6EFC /* OpenTok */ = {
isa = PBXGroup;
children = (
306FE6CA271D8B73002D6EFC /* OpenTok.swift */,
);
path = OpenTok;
sourceTree = "<group>";
};
555EAAA626EFB641859EF0BE /* Frameworks */ = {
isa = PBXGroup;
children = (
@ -153,6 +165,7 @@
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
306FE6C9271D8B54002D6EFC /* OpenTok */,
E91B539E256AAC1400E96549 /* GuestPOC_Certificate.cer */,
E91B539D256AAC1400E96549 /* GuestPOC_Certificate.p12 */,
E91B5390256AAA6500E96549 /* Controllers */,
@ -182,6 +195,7 @@
E923EFD125863FDF00E3E751 /* GeoZoneModel.swift */,
E923EFD3258645C100E3E751 /* HMG_Geofence.swift */,
E923EFD52587443800E3E751 /* HMGPlatformBridge.swift */,
306FE6C7271D790C002D6EFC /* OpenTokPlatformBridge.swift */,
E9F7623A25922BCE00FB5CCF /* FlutterConstants.swift */,
);
path = Helper;
@ -375,6 +389,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
306FE6C8271D790C002D6EFC /* OpenTokPlatformBridge.swift in Sources */,
E923EFD225863FDF00E3E751 /* GeoZoneModel.swift in Sources */,
E91B539A256AAA6500E96549 /* MainFlutterVC.swift in Sources */,
E91B539C256AAA6500E96549 /* HMG_GUEST_bkp.swift in Sources */,
@ -382,6 +397,7 @@
E923EFD4258645C100E3E751 /* HMG_Geofence.swift in Sources */,
E923EFD62587443800E3E751 /* HMGPlatformBridge.swift in Sources */,
E9F7623B25922BCE00FB5CCF /* FlutterConstants.swift in Sources */,
306FE6CB271D8B73002D6EFC /* OpenTok.swift in Sources */,
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
E9E27168256E3A4000F49B69 /* LocalizedFromFlutter.swift in Sources */,
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,

@ -14,7 +14,7 @@ var userNotificationCenterDelegate:UNUserNotificationCenterDelegate? = nil
GMSServices.provideAPIKey("AIzaSyCmevVlr2Bh-c8W1VUzo8gt8JRY7n5PANw")
GeneratedPluginRegistrant.register(with: self)
initializePlatformChannel()
initializePlatformChannels()
if let _ = launchOptions?[.location] {
HMG_Geofence.initGeofencing()
@ -25,14 +25,16 @@ var userNotificationCenterDelegate:UNUserNotificationCenterDelegate? = nil
}
func initializePlatformChannel(){
func initializePlatformChannels(){
if let mainViewController = window.rootViewController as? MainFlutterVC{ // platform initialization suppose to be in foreground
flutterViewController = mainViewController
HMGPlatformBridge.initialize(flutterViewController: flutterViewController)
OpenTokPlatformBridge.initialize(flutterViewController: flutterViewController, registrar: self.registrar(forPlugin: "open-tok"))
}else if let mainViewController = initialViewController(){ // platform initialization suppose to be in background
flutterViewController = mainViewController
HMGPlatformBridge.initialize(flutterViewController: flutterViewController)
OpenTokPlatformBridge.initialize(flutterViewController: flutterViewController, registrar: self.registrar(forPlugin: "open-tok"))
}
}

@ -10,7 +10,7 @@ import NetworkExtension
import SystemConfiguration.CaptiveNetwork
var flutterMethodChannel:FlutterMethodChannel? = nil
var mainViewController:MainFlutterVC!
fileprivate var mainViewController:MainFlutterVC!
class HMGPlatformBridge{
private let channelName = "HMG-Platform-Bridge"

@ -0,0 +1,59 @@
//
// HMGPlatformBridge.swift
// Runner
//
// Created by ZiKambrani on 14/12/2020.
//
import UIKit
import NetworkExtension
import SystemConfiguration.CaptiveNetwork
import OpenTok
fileprivate var openTok:OpenTok?
class OpenTokPlatformBridge : NSObject{
private var methodChannel:FlutterMethodChannel? = nil
private var mainViewController:MainFlutterVC!
private static var shared_:OpenTokPlatformBridge?
class func initialize(flutterViewController:MainFlutterVC, registrar:FlutterPluginRegistrar?){
shared_ = OpenTokPlatformBridge()
shared_?.mainViewController = flutterViewController
shared_?.openChannel()
openTok = OpenTok(mainViewController: flutterViewController, registrar: registrar)
}
func shared() -> OpenTokPlatformBridge{
assert((OpenTokPlatformBridge.shared_ != nil), "OpenTokPlatformBridge is not initialized, call initialize(mainViewController:MainFlutterVC) function first.")
return OpenTokPlatformBridge.shared_!
}
private func openChannel(){
methodChannel = FlutterMethodChannel(name: "OpenTok-Platform-Bridge", binaryMessenger: mainViewController.binaryMessenger)
methodChannel?.setMethodCallHandler { (call, result) in
print("Called function \(call.method)")
switch(call.method) {
case "initSession":
openTok?.initSession(call: call, result: result)
case "swapCamera":
openTok?.swapCamera(call: call, result: result)
case "toggleAudio":
openTok?.toggleAudio(call: call, result: result)
case "toggleVideo":
openTok?.toggleVideo(call: call, result: result)
default:
result(FlutterMethodNotImplemented)
}
print("")
}
}
}

@ -0,0 +1,273 @@
//
// OpenTok.swift
// Runner
//
// Created by Zohaib Iqbal Kambrani on 18/10/2021.
//
import Foundation
import OpenTok
enum SdkState: String {
case loggedOut = "LOGGED_OUT"
case loggedIn = "LOGGED_IN"
case wait = "WAIT"
case error = "ERROR"
}
class OpenTok : NSObject{
private var mainViewController:MainFlutterVC!
private var registrar:FlutterPluginRegistrar?
init(mainViewController:MainFlutterVC, registrar:FlutterPluginRegistrar?){
self.mainViewController = mainViewController
self.registrar = registrar
let factory = OpentokVideoFactory(messenger: registrar!.messenger())
registrar?.register(factory, withId: "opentok-video-container")
}
var otSession: OTSession?
var vonageChannel: FlutterMethodChannel?
var subscriber: OTSubscriber?
lazy var publisher: OTPublisher = {
let settings = OTPublisherSettings()
settings.name = UIDevice.current.name
return OTPublisher(delegate: self, settings: settings)!
}()
func initSession(call:FlutterMethodCall, result: @escaping FlutterResult){
if let arguments = call.arguments as? [String: String],
let apiKey = arguments["apiKey"],
let sessionId = arguments["sessionId"],
let token = arguments["token"]{
var error: OTError?
defer {
// todo
}
notifyFlutter(state: SdkState.wait)
otSession = OTSession(apiKey: apiKey, sessionId: sessionId, delegate: self)!
otSession?.connect(withToken: token, error: &error)
result("")
}else{
}
}
func swapCamera(call:FlutterMethodCall, result: @escaping FlutterResult) {
if publisher.cameraPosition == .front {
publisher.cameraPosition = .back
} else {
publisher.cameraPosition = .front
}
result("")
}
func toggleAudio(call:FlutterMethodCall, result: @escaping FlutterResult) {
if let arguments = call.arguments as? [String: Bool],
let publishAudio = arguments["publishAudio"] {
publisher.publishAudio = !publisher.publishAudio
}
result("")
}
func toggleVideo(call:FlutterMethodCall, result: @escaping FlutterResult) {
if let arguments = call.arguments as? [String: Bool],
let publishVideo = arguments["publishVideo"] {
publisher.publishVideo = !publisher.publishVideo
}
result("")
}
func notifyFlutter(state: SdkState) {
vonageChannel?.invokeMethod("updateState", arguments: state.rawValue)
}
}
extension OpenTok: OTSessionDelegate {
func sessionDidConnect(_ sessionDelegate: OTSession) {
print("The client connected to the session.")
notifyFlutter(state: SdkState.loggedIn)
var error: OTError?
defer {
// todo
}
self.otSession?.publish(self.publisher, error: &error)
if let pubView = self.publisher.view {
pubView.frame = CGRect(x: 0, y: 0, width: 200, height: 300)
if OpentokVideoFactory.view == nil {
OpentokVideoFactory.viewToAddPub = pubView
} else {
OpentokVideoFactory.view?.addPublisherView(pubView)
}
}
}
func sessionDidDisconnect(_ session: OTSession) {
print("The client disconnected from the session.")
notifyFlutter(state: SdkState.loggedOut)
}
func session(_ session: OTSession, didFailWithError error: OTError) {
print("The client failed to connect to the session: \(error).")
}
func session(_ session: OTSession, streamCreated stream: OTStream) {
print("A stream was created in the session.")
var error: OTError?
defer {
// todo
}
subscriber = OTSubscriber(stream: stream, delegate: self)
session.subscribe(subscriber!, error: &error)
}
func session(_ session: OTSession, streamDestroyed stream: OTStream) {
print("A stream was destroyed in the session.")
}
}
extension OpenTok: OTPublisherDelegate {
func publisher(_ publisher: OTPublisherKit, streamCreated stream: OTStream) {
}
func publisher(_ publisher: OTPublisherKit, streamDestroyed stream: OTStream) {
}
func publisher(_ publisher: OTPublisherKit, didFailWithError error: OTError) {
print("Publisher failed: \(error.localizedDescription)")
}
}
extension OpenTok: OTSubscriberDelegate {
func subscriberDidConnect(toStream subscriberKit: OTSubscriberKit) {
print("Subscriber connected")
if let subView = self.subscriber?.view {
subView.frame = CGRect(x: 0, y: 0, width: 200, height: 300)
if OpentokVideoFactory.view == nil {
OpentokVideoFactory.viewToAddSub = subView
} else {
OpentokVideoFactory.view?.addSubscriberView(subView)
}
}
}
func subscriber(_ subscriber: OTSubscriberKit, didFailWithError error: OTError) {
print("Subscriber failed: \(error.localizedDescription)")
}
}
class OpentokVideoFactory: NSObject, FlutterPlatformViewFactory {
static var view: OpentokVideoPlatformView?
static var viewToAddSub: UIView?
static var viewToAddPub: UIView?
static func getViewInstance(
frame: CGRect,
viewId: Int64,
args: Any?,
messenger: FlutterBinaryMessenger?
) -> OpentokVideoPlatformView{
if(view == nil) {
view = OpentokVideoPlatformView()
if viewToAddSub != nil {
view?.addSubscriberView(viewToAddSub!)
}
if viewToAddPub != nil {
view?.addPublisherView(viewToAddPub!)
}
}
return view!
}
private var messenger: FlutterBinaryMessenger
init(messenger: FlutterBinaryMessenger) {
self.messenger = messenger
super.init()
}
func create(
withFrame frame: CGRect,
viewIdentifier viewId: Int64,
arguments args: Any?
) -> FlutterPlatformView {
return OpentokVideoFactory.getViewInstance(
frame: frame,
viewId: viewId,
args: args,
messenger: messenger)
}
}
class OpentokVideoPlatformView: NSObject, FlutterPlatformView {
private let videoContainer: OpenTokVideoContainer
override init() {
videoContainer = OpenTokVideoContainer()
super.init()
}
public func addSubscriberView(_ view: UIView) {
videoContainer.addSubscriberView(view)
}
public func addPublisherView(_ view: UIView) {
videoContainer.addPublisherView(view)
}
func view() -> UIView {
return videoContainer
}
}
final class OpenTokVideoContainer: UIView {
private let subscriberContainer = UIView()
private let publisherContainer = UIView()
init() {
super.init(frame: .zero)
addSubview(subscriberContainer)
addSubview(publisherContainer)
}
public func addSubscriberView(_ view: UIView) {
subscriberContainer.addSubview(view)
}
public func addPublisherView(_ view: UIView) {
publisherContainer.addSubview(view)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
let width = frame.width
let height = frame.height
let videoWidth = width / 2
subscriberContainer.frame = CGRect(x: 0, y: 0, width: videoWidth, height: height)
publisherContainer.frame = CGRect(x: videoWidth, y: 0, width: videoWidth, height: height)
}
}
Loading…
Cancel
Save