diff --git a/android/app/build.gradle b/android/app/build.gradle index 89407e6f..293285c9 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -122,7 +122,7 @@ dependencies { implementation 'com.google.android.gms:play-services-basement:17.5.0' -// implementation "com.opentok.android:opentok-android-sdk:2.19.1" + implementation "com.opentok.android:opentok-android-sdk:2.19.1" implementation 'com.facebook.stetho:stetho:1.5.1' implementation 'com.facebook.stetho:stetho-urlconnection:1.5.1' diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/MainActivity.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/MainActivity.kt index 0e5e1117..65998387 100644 --- a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/MainActivity.kt +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/MainActivity.kt @@ -14,11 +14,10 @@ class MainActivity: FlutterFragmentActivity() { override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { GeneratedPluginRegistrant.registerWith(flutterEngine); // Create Flutter Platform Bridge - this.window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or - WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) + this.window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) PlatformBridge(flutterEngine, this).create() -// OpenTokPlatformBridge(flutterEngine, this).create() + OpenTokPlatformBridge(flutterEngine, this).create() val time = timeToMillis("04:00:00", "HH:mm:ss") diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/opentok/LocalVideo.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/opentok/LocalVideo.kt index 960665d5..cfebfe65 100644 --- a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/opentok/LocalVideo.kt +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/opentok/LocalVideo.kt @@ -1,58 +1,58 @@ -//package com.ejada.hmg.opentok -// -//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 com.ejada.hmg.R -//import io.flutter.plugin.common.StandardMessageCodec -//import io.flutter.plugin.platform.PlatformView -//import io.flutter.plugin.platform.PlatformViewFactory -// -//class LocalVideoFactory : PlatformViewFactory(StandardMessageCodec.INSTANCE) { -// -// companion object { -// private lateinit var view: LocalVideoPlatformView -// -// fun getViewInstance(context: Context): LocalVideoPlatformView { -// if(!this::view.isInitialized) { -// view = LocalVideoPlatformView(context) -// } -// -// return view -// } -// } -// -// override fun create(context: Context, viewId: Int, args: Any?): PlatformView { -// return getViewInstance(context) -// } -//} -// -//class LocalVideoPlatformView(context: Context) : PlatformView { -// private val videoContainer: LocalVideoContainer = LocalVideoContainer(context) -// -// val container get() = videoContainer.publisherContainer -// -// override fun getView(): View { -// return videoContainer -// } -// -// override fun dispose() {} -//} -// -//class LocalVideoContainer @JvmOverloads constructor( -// context: Context, -// attrs: AttributeSet? = null, -// defStyle: Int = 0, -// defStyleRes: Int = 0 -//) : LinearLayout(context, attrs, defStyle, defStyleRes) { -// -// var publisherContainer: FrameLayout private set -// -// init { -// val view = LayoutInflater.from(context).inflate(R.layout.local_video, this, true) -// publisherContainer = view.findViewById(R.id.publisher_container) -// } -//} \ No newline at end of file +package com.ejada.hmg.opentok + +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 com.ejada.hmg.R +import io.flutter.plugin.common.StandardMessageCodec +import io.flutter.plugin.platform.PlatformView +import io.flutter.plugin.platform.PlatformViewFactory + +class LocalVideoFactory : PlatformViewFactory(StandardMessageCodec.INSTANCE) { + + companion object { + private lateinit var view: LocalVideoPlatformView + + fun getViewInstance(context: Context): LocalVideoPlatformView { + if(!this::view.isInitialized) { + view = LocalVideoPlatformView(context) + } + + return view + } + } + + override fun create(context: Context, viewId: Int, args: Any?): PlatformView { + return getViewInstance(context) + } +} + +class LocalVideoPlatformView(context: Context) : PlatformView { + private val videoContainer: LocalVideoContainer = LocalVideoContainer(context) + + val container get() = videoContainer.publisherContainer + + override fun getView(): View { + return videoContainer + } + + override fun dispose() {} +} + +class LocalVideoContainer @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyle: Int = 0, + defStyleRes: Int = 0 +) : LinearLayout(context, attrs, defStyle, defStyleRes) { + + var publisherContainer: FrameLayout private set + + init { + val view = LayoutInflater.from(context).inflate(R.layout.local_video, this, true) + publisherContainer = view.findViewById(R.id.publisher_container) + } +} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/opentok/OpenTok.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/opentok/OpenTok.kt index 6d8e668a..5142702a 100644 --- a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/opentok/OpenTok.kt +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/opentok/OpenTok.kt @@ -1,170 +1,181 @@ -//package com.ejada.hmg.opentok -// -//import android.content.Context -//import android.os.Handler -//import android.os.Looper -//import android.util.Log -//import android.view.ViewGroup -//import com.facebook.stetho.urlconnection.StethoURLConnectionManager -//import com.opentok.android.* -//import io.flutter.embedding.engine.FlutterEngine -//import io.flutter.embedding.engine.plugins.util.GeneratedPluginRegister -//import io.flutter.plugin.common.MethodCall -//import io.flutter.plugin.common.MethodChannel -// -// -//enum class OpenTokSDKState { -// LOGGED_OUT, -// LOGGED_IN, -// WAIT, -// ERROR -//} -// -//class OpenTok(private var context: Context, private var flutterEngine: FlutterEngine){ -// private lateinit var remoteVideoPlatformView: RemoteVideoPlatformView -// private lateinit var localVideoPlatformView: LocalVideoPlatformView -// -// init { -// remoteVideoPlatformView = RemoteVideoFactory.getViewInstance(context) -// flutterEngine -// .platformViewsController -// .registry -// .registerViewFactory("remote-video-container", RemoteVideoFactory()) -// -// localVideoPlatformView = LocalVideoFactory.getViewInstance(context) -// flutterEngine -// .platformViewsController -// .registry -// .registerViewFactory("local-video-container", LocalVideoFactory()) -// } -// -// 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) -// localVideoPlatformView.container.addView(view) -// } -// -// notifyFlutter(OpenTokSDKState.LOGGED_IN) -// session.publish(publisher) -// } -// -// override fun onDisconnected(session: Session) { -// notifyFlutter(OpenTokSDKState.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) -// -// remoteVideoPlatformView.container.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 -// -// remoteVideoPlatformView.container.removeAllViews() -// } -// } -// -// override fun onError(session: Session, opentokError: OpentokError) { -// Log.d("MainActivity", "Session error: " + opentokError.message) -// notifyFlutter(OpenTokSDKState.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(OpenTokSDKState.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(OpenTokSDKState.LOGGED_OUT) -// } -// -// override fun onError(subscriberKit: SubscriberKit, opentokError: OpentokError) { -// Log.d("MainActivity", "SubscriberKit onError: " + opentokError.message) -// notifyFlutter(OpenTokSDKState.ERROR) -// } -// } -// -// fun initSession(call: MethodCall, result: MethodChannel.Result) { -// -// val apiKey = requireNotNull(call.argument("apiKey")) -// val sessionId = requireNotNull(call.argument("sessionId")) -// val token = requireNotNull(call.argument("token")) -// -// notifyFlutter(OpenTokSDKState.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("publishAudio")) -// publisher?.publishAudio = publishAudio -// result.success("") -// } -// -// fun toggleVideo(call: MethodCall, result: MethodChannel.Result) { -// val publishVideo = requireNotNull(call.argument("publishVideo")) -// publisher?.publishVideo = publishVideo -// result.success("") -// } -// -// private fun notifyFlutter(state: OpenTokSDKState) { -// Handler(Looper.getMainLooper()).post { -// MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "OpenTok-Platform-Bridge") -// .invokeMethod("updateState", state.toString()) -// } -// } -//} +package com.ejada.hmg.opentok + +import android.content.Context +import android.os.Handler +import android.os.Looper +import android.util.Log +import android.view.ViewGroup +import com.facebook.stetho.urlconnection.StethoURLConnectionManager +import com.opentok.android.* +import io.flutter.embedding.engine.FlutterEngine +import io.flutter.embedding.engine.plugins.util.GeneratedPluginRegister +import io.flutter.plugin.common.MethodCall +import io.flutter.plugin.common.MethodChannel + + +enum class OpenTokSDKState { + LOGGED_OUT, + LOGGED_IN, + WAIT, + ERROR +} + +class OpenTok(private var context: Context, private var flutterEngine: FlutterEngine){ + private lateinit var remoteVideoPlatformView: RemoteVideoPlatformView + private lateinit var localVideoPlatformView: LocalVideoPlatformView + + init { + remoteVideoPlatformView = RemoteVideoFactory.getViewInstance(context) + flutterEngine + .platformViewsController + .registry + .registerViewFactory("remote-video-container", RemoteVideoFactory()) + + localVideoPlatformView = LocalVideoFactory.getViewInstance(context) + flutterEngine + .platformViewsController + .registry + .registerViewFactory("local-video-container", LocalVideoFactory()) + } + + 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) + localVideoPlatformView.container.addView(view) + } + + notifyFlutter(OpenTokSDKState.LOGGED_IN) + session.publish(publisher) + } + + override fun onDisconnected(session: Session) { + notifyFlutter(OpenTokSDKState.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) + + remoteVideoPlatformView.container.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 + + remoteVideoPlatformView.container.removeAllViews() + } + } + + override fun onError(session: Session, opentokError: OpentokError) { + Log.d("MainActivity", "Session error: " + opentokError.message) + notifyFlutter(OpenTokSDKState.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(OpenTokSDKState.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(OpenTokSDKState.LOGGED_OUT) + } + + override fun onError(subscriberKit: SubscriberKit, opentokError: OpentokError) { + Log.d("MainActivity", "SubscriberKit onError: " + opentokError.message) + notifyFlutter(OpenTokSDKState.ERROR) + } + } + + fun initSession(call: MethodCall, result: MethodChannel.Result) { + + val apiKey = requireNotNull(call.argument("apiKey")) + val sessionId = requireNotNull(call.argument("sessionId")) + val token = requireNotNull(call.argument("token")) + + notifyFlutter(OpenTokSDKState.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(true) + } + + fun toggleAudio(call: MethodCall, result: MethodChannel.Result) { + if (publisher != null) { + publisher?.publishAudio = !(publisher!!.publishAudio) + result.success(true) + }else{ + result.success(false) + } + } + + fun toggleVideo(call: MethodCall, result: MethodChannel.Result) { + if (publisher != null) { + publisher?.publishVideo = !(publisher!!.publishVideo) + result.success(true) + }else{ + result.success(false) + } + } + + fun hangupCall(call: MethodCall, result: MethodChannel.Result) { + session?.disconnect() + result.success(true) + } + + private fun notifyFlutter(state: OpenTokSDKState) { + Handler(Looper.getMainLooper()).post { + MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "OpenTok-Platform-Bridge") + .invokeMethod("updateState", state.toString()) + } + } +} diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/opentok/RemoteVideo.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/opentok/RemoteVideo.kt index 8c822839..9116a1e8 100644 --- a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/opentok/RemoteVideo.kt +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/opentok/RemoteVideo.kt @@ -1,58 +1,58 @@ -//package com.ejada.hmg.opentok -// -//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 com.ejada.hmg.R -//import io.flutter.plugin.common.StandardMessageCodec -//import io.flutter.plugin.platform.PlatformView -//import io.flutter.plugin.platform.PlatformViewFactory -// -//class RemoteVideoFactory : PlatformViewFactory(StandardMessageCodec.INSTANCE) { -// -// companion object { -// private lateinit var view: RemoteVideoPlatformView -// -// fun getViewInstance(context: Context): RemoteVideoPlatformView { -// if(!this::view.isInitialized) { -// view = RemoteVideoPlatformView(context) -// } -// -// return view -// } -// } -// -// override fun create(context: Context, viewId: Int, args: Any?): PlatformView { -// return getViewInstance(context) -// } -//} -// -//class RemoteVideoPlatformView(context: Context) : PlatformView { -// private val videoContainer: RemoteVideoContainer = RemoteVideoContainer(context) -// -// val container get() = videoContainer.subscriberContainer -// -// override fun getView(): View { -// return videoContainer -// } -// -// override fun dispose() {} -//} -// -//class RemoteVideoContainer @JvmOverloads constructor( -// context: Context, -// attrs: AttributeSet? = null, -// defStyle: Int = 0, -// defStyleRes: Int = 0 -//) : LinearLayout(context, attrs, defStyle, defStyleRes) { -// -// var subscriberContainer: FrameLayout private set -// -// init { -// val view = LayoutInflater.from(context).inflate(R.layout.remote_video, this, true) -// subscriberContainer = view.findViewById(R.id.subscriber_container) -// } -//} \ No newline at end of file +package com.ejada.hmg.opentok + +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 com.ejada.hmg.R +import io.flutter.plugin.common.StandardMessageCodec +import io.flutter.plugin.platform.PlatformView +import io.flutter.plugin.platform.PlatformViewFactory + +class RemoteVideoFactory : PlatformViewFactory(StandardMessageCodec.INSTANCE) { + + companion object { + private lateinit var view: RemoteVideoPlatformView + + fun getViewInstance(context: Context): RemoteVideoPlatformView { + if(!this::view.isInitialized) { + view = RemoteVideoPlatformView(context) + } + + return view + } + } + + override fun create(context: Context, viewId: Int, args: Any?): PlatformView { + return getViewInstance(context) + } +} + +class RemoteVideoPlatformView(context: Context) : PlatformView { + private val videoContainer: RemoteVideoContainer = RemoteVideoContainer(context) + + val container get() = videoContainer.subscriberContainer + + override fun getView(): View { + return videoContainer + } + + override fun dispose() {} +} + +class RemoteVideoContainer @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyle: Int = 0, + defStyleRes: Int = 0 +) : LinearLayout(context, attrs, defStyle, defStyleRes) { + + var subscriberContainer: FrameLayout private set + + init { + val view = LayoutInflater.from(context).inflate(R.layout.remote_video, this, true) + subscriberContainer = view.findViewById(R.id.subscriber_container) + } +} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/OpenTokPlatformBridge.kt b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/OpenTokPlatformBridge.kt index 33d9ff0a..ebb04456 100644 --- a/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/OpenTokPlatformBridge.kt +++ b/android/app/src/main/kotlin/com/cloud/diplomaticquarterapp/utils/OpenTokPlatformBridge.kt @@ -1,42 +1,45 @@ -//package com.ejada.hmg.utils -// -//import com.ejada.hmg.MainActivity -//import com.ejada.hmg.opentok.OpenTok -//import io.flutter.embedding.engine.FlutterEngine -//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() -// } -// } -// } -// } -// -//} +package com.ejada.hmg.utils + +import com.ejada.hmg.MainActivity +import com.ejada.hmg.opentok.OpenTok +import io.flutter.embedding.engine.FlutterEngine +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) + } + "hangupCall" -> { + openTok.hangupCall(call, result) + } + else -> { + result.notImplemented() + } + } + } + } + +} diff --git a/ios/Podfile b/ios/Podfile index 10f3c9b4..da082adc 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -30,6 +30,8 @@ flutter_ios_podfile_setup target 'Runner' do use_frameworks! use_modular_headers! + + pod 'OpenTok', '~> 2.22.0' flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) end diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 564d98c2..3c59323c 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -62,10 +62,10 @@ PODS: - Firebase/Analytics (= 8.9.0) - firebase_core - Flutter - - firebase_core (1.10.5): + - firebase_core (1.10.6): - Firebase/CoreOnly (= 8.9.0) - Flutter - - firebase_messaging (11.2.3): + - firebase_messaging (11.2.4): - Firebase/Messaging (= 8.9.0) - firebase_core - Flutter @@ -220,6 +220,8 @@ PODS: - nanopb/encode (2.30908.0) - native_device_orientation (0.0.1): - Flutter + - OpenTok (2.22.0): + - VonageWebRTC (= 84.0.20) - OrderedSet (5.0.0) - package_info_plus (0.4.5): - Flutter @@ -256,6 +258,7 @@ PODS: - Flutter - video_player (0.0.1): - Flutter + - VonageWebRTC (84.0.20) - wakelock (0.0.1): - Flutter - WebRTC-SDK (92.4515.11) @@ -297,6 +300,7 @@ DEPENDENCIES: - map_launcher (from `.symlinks/plugins/map_launcher/ios`) - maps_launcher (from `.symlinks/plugins/maps_launcher/ios`) - native_device_orientation (from `.symlinks/plugins/native_device_orientation/ios`) + - OpenTok (~> 2.22.0) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`) - pay_ios (from `.symlinks/plugins/pay_ios/ios`) @@ -331,6 +335,7 @@ SPEC REPOS: - Libyuv - MTBBarcodeScanner - nanopb + - OpenTok - OrderedSet - PromisesObjC - Reachability @@ -339,6 +344,7 @@ SPEC REPOS: - SwiftyGif - Toast - Try + - VonageWebRTC - WebRTC-SDK EXTERNAL SOURCES: @@ -449,8 +455,8 @@ SPEC CHECKSUMS: file_picker: 3e6c3790de664ccf9b882732d9db5eaf6b8d4eb1 Firebase: 13d8d96499e2635428d5bf0ec675df21f95d9a95 firebase_analytics: 7a7528bb2abf4ca22cff7a57bbf909dcab73e13d - firebase_core: dfcae4c150a5e24436a0b7677c470478a234d5bf - firebase_messaging: c4696ded2f44fb5c2bf6e94f9a575105793e58fa + firebase_core: c263d7daf1dc92fcd9895e6abdc04872b0ee07ff + firebase_messaging: dff5cd08781ee1de988565a83c977e435405cd7e FirebaseAnalytics: 4ab446ce08a3fe52e8a4303dd997cf26276bf968 FirebaseCore: 599ee609343eaf4941bd188f85e3aa077ffe325b FirebaseCoreDiagnostics: 56fb7216d87e0e6ec2feddefa9d8a392fe8b2c18 @@ -486,6 +492,7 @@ SPEC CHECKSUMS: MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb nanopb: a0ba3315591a9ae0a16a309ee504766e90db0c96 native_device_orientation: 3b4cfc9565a7b879cc4fde282b3e27745e852d0d + OpenTok: 481bc2ea0affccdd721b4cd41fa8c7e6a6e1f200 OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e path_provider_ios: 7d7ce634493af4477d156294792024ec3485acd5 @@ -506,11 +513,12 @@ SPEC CHECKSUMS: url_launcher_ios: 02f1989d4e14e998335b02b67a7590fa34f971af vibration: b5a33e764c3f609a975b9dca73dce20fdde627dc video_player: ecd305f42e9044793efd34846e1ce64c31ea6fcb + VonageWebRTC: 20e0e56f656ddbf49287cacbd33e69dbbe5736f8 wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f WebRTC-SDK: 21dbc6028a68f3a89718057a2caa970a4da8ebb7 webview_flutter_wkwebview: 005fbd90c888a42c5690919a1527ecc6649e1162 wifi: d7d77c94109e36c4175d845f0a5964eadba71060 -PODFILE CHECKSUM: cc1f88378b4bfcf93a6ce00d2c587857c6008d3b +PODFILE CHECKSUM: 87c85be30da5343f66afbb978b1a421a87b82b01 COCOAPODS: 1.11.2 diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift index 8826bbdd..35a3c022 100644 --- a/ios/Runner/AppDelegate.swift +++ b/ios/Runner/AppDelegate.swift @@ -29,12 +29,12 @@ var userNotificationCenterDelegate:UNUserNotificationCenterDelegate? = nil 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")) + 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")) + OpenTokPlatformBridge.initialize(flutterViewController: flutterViewController, registrar: self.registrar(forPlugin: "open-tok")) } } diff --git a/ios/Runner/Helper/OpenTokPlatformBridge.swift b/ios/Runner/Helper/OpenTokPlatformBridge.swift index 132f1384..4da39dc4 100644 --- a/ios/Runner/Helper/OpenTokPlatformBridge.swift +++ b/ios/Runner/Helper/OpenTokPlatformBridge.swift @@ -13,46 +13,49 @@ import SystemConfiguration.CaptiveNetwork 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("") -// } -// } + 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) + + case "hangupCall": + openTok?.hangupCall(call: call, result: result) + + default: + result(FlutterMethodNotImplemented) + } + + print("") + } + } } diff --git a/ios/Runner/OpenTok/OpenTok.swift b/ios/Runner/OpenTok/OpenTok.swift index f91d83d5..34d13bb1 100644 --- a/ios/Runner/OpenTok/OpenTok.swift +++ b/ios/Runner/OpenTok/OpenTok.swift @@ -6,7 +6,7 @@ // import Foundation -//import OpenTok +import OpenTok import UIKit enum SdkState: String { @@ -18,163 +18,163 @@ enum SdkState: String { class OpenTok : NSObject{ -// private var mainViewController:MainFlutterVC! -// private var registrar:FlutterPluginRegistrar? -// var methodChannel: FlutterMethodChannel? -// -// init(mainViewController:MainFlutterVC, registrar:FlutterPluginRegistrar?){ -// self.mainViewController = mainViewController -// self.methodChannel = FlutterMethodChannel(name: "OpenTok-Platform-Bridge", binaryMessenger: mainViewController.binaryMessenger) -// self.registrar = registrar -// -// let remoteVDOFactory = OpenTokRemoteVideoFactory(messenger: registrar!.messenger()) -// registrar?.register(remoteVDOFactory, withId: "remote-video-container") -// -// let localVDOFactory = OpenTokLocalVideoFactory(messenger: registrar!.messenger()) -// registrar?.register(localVDOFactory, withId: "local-video-container") -// } -// -// var otSession: OTSession? -// -// 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) { -// methodChannel?.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 OpenTokLocalVideoFactory.view == nil { -// OpenTokLocalVideoFactory.viewToAddPub = pubView -// } else { -// OpenTokLocalVideoFactory.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: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height) -// -// if OpenTokRemoteVideoFactory.view == nil { -// OpenTokRemoteVideoFactory.viewToAddSub = subView -// } else { -// OpenTokRemoteVideoFactory.view?.addSubscriberView(subView) -// } -// } -// } -// -// func subscriber(_ subscriber: OTSubscriberKit, didFailWithError error: OTError) { -// print("Subscriber failed: \(error.localizedDescription)") -// } + private var mainViewController:MainFlutterVC! + private var registrar:FlutterPluginRegistrar? + var methodChannel: FlutterMethodChannel? + + init(mainViewController:MainFlutterVC, registrar:FlutterPluginRegistrar?){ + self.mainViewController = mainViewController + self.methodChannel = FlutterMethodChannel(name: "OpenTok-Platform-Bridge", binaryMessenger: mainViewController.binaryMessenger) + self.registrar = registrar + + let remoteVDOFactory = OpenTokRemoteVideoFactory(messenger: registrar!.messenger()) + registrar?.register(remoteVDOFactory, withId: "remote-video-container") + + let localVDOFactory = OpenTokLocalVideoFactory(messenger: registrar!.messenger()) + registrar?.register(localVDOFactory, withId: "local-video-container") + } + + var otSession: OTSession? + + 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) { + publisher.publishAudio = !publisher.publishAudio + result("") + } + + func toggleVideo(call:FlutterMethodCall, result: @escaping FlutterResult) { + publisher.publishVideo = !publisher.publishVideo + result("") + } + + func hangupCall(call:FlutterMethodCall, result: @escaping FlutterResult) { + var error:OTError? + otSession?.disconnect(&error) + result(error == nil) + } + + + func notifyFlutter(state: SdkState) { + methodChannel?.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 OpenTokLocalVideoFactory.view == nil { + OpenTokLocalVideoFactory.viewToAddPub = pubView + } else { + OpenTokLocalVideoFactory.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: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height) + + if OpenTokRemoteVideoFactory.view == nil { + OpenTokRemoteVideoFactory.viewToAddSub = subView + } else { + OpenTokRemoteVideoFactory.view?.addSubscriberView(subView) + } + } + } + + func subscriber(_ subscriber: OTSubscriberKit, didFailWithError error: OTError) { + print("Subscriber failed: \(error.localizedDescription)") + } } diff --git a/lib/analytics/flows/appointments.dart b/lib/analytics/flows/appointments.dart index 6c7cb547..57fab8b2 100644 --- a/lib/analytics/flows/appointments.dart +++ b/lib/analytics/flows/appointments.dart @@ -153,7 +153,7 @@ class Appointment{ 'doctor_nationality' : doctor.nationalityName, 'doctor_gender' : doctor.genderDescription, 'appointment_day' : day, - 'appointment_hour' : time + 'appointment_hour' : time // '5-6' }); } diff --git a/lib/analytics/flows/offers_promotions.dart b/lib/analytics/flows/offers_promotions.dart index 3fd3e60b..17a6232c 100644 --- a/lib/analytics/flows/offers_promotions.dart +++ b/lib/analytics/flows/offers_promotions.dart @@ -8,8 +8,8 @@ class OfferAndPromotion{ final offers_and_promotion = 'offers_&_promotion'; log(){ - logger('offers_&_promotion', parameters: { - 'action' : "click" + logger('offers_and_promotion', parameters: { + 'promotion_name' : "offer" }); } diff --git a/lib/analytics/google-analytics.dart b/lib/analytics/google-analytics.dart index 792175ee..cd68e89a 100644 --- a/lib/analytics/google-analytics.dart +++ b/lib/analytics/google-analytics.dart @@ -9,6 +9,8 @@ import 'package:diplomaticquarterapp/analytics/flows/offers_promotions.dart'; import 'package:diplomaticquarterapp/analytics/flows/todo_list.dart'; import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; import 'package:diplomaticquarterapp/routes.dart'; +import 'package:diplomaticquarterapp/uitl/location_util.dart'; +import 'package:diplomaticquarterapp/uitl/utils.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:firebase_analytics/firebase_analytics.dart'; import 'package:firebase_analytics/observer.dart'; @@ -52,9 +54,11 @@ class GAnalytics { setUser(AuthenticatedUser user){ if(user != null){ _analytics.setUserProperty(name: 'user_country', value: user.iSOCountryID); - _analytics.setUserProperty(name: 'user_language', value: user.preferredLanguage); - _analytics.setUserProperty(name: 'userid', value: user.patientID.toString() ); - _analytics.setUserProperty(name: 'login_status', value: 'yes'); + _analytics.setUserProperty(name: 'user_language', value: user.preferredLanguage == '1' ? 'arabic' : 'english'); + _analytics.setUserProperty(name: 'userid', value: Utils.generateMd5Hash(user.emailAddress)); + _analytics.setUserProperty(name: 'login_status', value: 'loggedin'); + }else{ + _analytics.setUserProperty(name: 'login_status', value: 'guest'); } } diff --git a/lib/config/config.dart b/lib/config/config.dart index 6fccb5ae..a2fb00eb 100644 --- a/lib/config/config.dart +++ b/lib/config/config.dart @@ -4,6 +4,8 @@ import 'package:diplomaticquarterapp/models/Request.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; var MAX_SMALL_SCREEN = 660; +final OPENTOK_API_KEY = '46209962'; +// final OPENTOK_API_KEY = '47464241'; // PACKAGES and OFFERS var EXA_CART_API_BASE_URL = 'https://mdlaboratories.com/offersdiscounts'; diff --git a/lib/models/LiveCare/IncomingCallData.dart b/lib/models/LiveCare/IncomingCallData.dart index d98b4c5b..cfb1395d 100644 --- a/lib/models/LiveCare/IncomingCallData.dart +++ b/lib/models/LiveCare/IncomingCallData.dart @@ -22,6 +22,7 @@ class IncomingCallData { String name; String videoUrl; String picture; + String token; String isCall; String sound; @@ -70,6 +71,7 @@ class IncomingCallData { appointmenttime = json['appointmenttime']; type = json['type']; sessionId = json['session_id']; + token = json['token']; identity = json['identity']; name = json['name']; videoUrl = json['videoUrl']; @@ -97,6 +99,7 @@ class IncomingCallData { data['appointmenttime'] = this.appointmenttime; data['type'] = this.type; data['session_id'] = this.sessionId; + data['token'] = this.token; data['identity'] = this.identity; data['name'] = this.name; data['videoUrl'] = this.videoUrl; diff --git a/lib/pages/BookAppointment/widgets/DentalComplaintCard.dart b/lib/pages/BookAppointment/widgets/DentalComplaintCard.dart index e5935ff3..d2adaafc 100644 --- a/lib/pages/BookAppointment/widgets/DentalComplaintCard.dart +++ b/lib/pages/BookAppointment/widgets/DentalComplaintCard.dart @@ -1,3 +1,5 @@ +import 'package:diplomaticquarterapp/analytics/google-analytics.dart'; +import 'package:diplomaticquarterapp/locator.dart'; import 'package:diplomaticquarterapp/models/Appointments/DentalChiefComplaintsModel.dart'; import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart'; import 'package:diplomaticquarterapp/pages/BookAppointment/SearchResults.dart'; @@ -24,6 +26,7 @@ class _DentalComplaintCardState extends State { return Container( child: InkWell( onTap: () { + // locator().appointment.book_appointment_chief_complaints(appointment_type: 'regular', hospital: widget.listDentalChiefComplain.); getChiefComplaintsList(); }, child: Container( diff --git a/lib/pages/conference/web_rtc/call_home_page_.dart b/lib/pages/conference/web_rtc/call_home_page_.dart index 69161f4c..1f36a8e9 100644 --- a/lib/pages/conference/web_rtc/call_home_page_.dart +++ b/lib/pages/conference/web_rtc/call_home_page_.dart @@ -201,6 +201,4 @@ class _CallHomePageState extends State { print('onHangup'); Navigator.of(context).pop(); } - - } diff --git a/lib/pages/landing/fragments/home_page_fragment2.dart b/lib/pages/landing/fragments/home_page_fragment2.dart index 39887467..2ddf9694 100644 --- a/lib/pages/landing/fragments/home_page_fragment2.dart +++ b/lib/pages/landing/fragments/home_page_fragment2.dart @@ -287,7 +287,7 @@ class _HomePageFragment2State extends State { flex: 1, child: InkWell( onTap: () { - // projectViewModel.analytics.offerPackages + projectViewModel.analytics.offerPackages.log(); AuthenticatedUser user = projectViewModel.user; Navigator.of(context).push(MaterialPageRoute(builder: (context) => PackagesOfferTabPage(user))); }, diff --git a/lib/pages/landing/landing_page.dart b/lib/pages/landing/landing_page.dart index a12c6419..d9f69edb 100644 --- a/lib/pages/landing/landing_page.dart +++ b/lib/pages/landing/landing_page.dart @@ -560,6 +560,7 @@ class _LandingPageState extends State with WidgetsBindingObserver { authService.selectDeviceImei(token).then((SelectDeviceIMEIRES value) => setUserValues(value)); if (authenticatedUserObject.isLogin) { var data = AuthenticatedUser.fromJson(await sharedPref.getObject(USER_PROFILE)); + projectViewModel.analytics.setUser(data); if (data != null) { authService.registeredAuthenticatedUser(data, token, 0, 0).then((res) => {}); authService.getDashboard().then((value) => { @@ -572,6 +573,8 @@ class _LandingPageState extends State with WidgetsBindingObserver { }), }); } - } else {} + } else { + projectViewModel.analytics.setUser(null); + } } } diff --git a/lib/pages/livecare/incoming_call.dart b/lib/pages/livecare/incoming_call.dart index d81aaec5..db2882f0 100644 --- a/lib/pages/livecare/incoming_call.dart +++ b/lib/pages/livecare/incoming_call.dart @@ -1,12 +1,14 @@ import 'dart:ui'; import 'package:camera/camera.dart'; +import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/models/LiveCare/IncomingCallData.dart'; import 'package:diplomaticquarterapp/models/LiveCare/room_model.dart'; import 'package:diplomaticquarterapp/pages/conference/web_rtc/call_home_page_.dart'; import 'package:diplomaticquarterapp/pages/conference/widgets/platform_exception_alert_dialog.dart'; import 'package:diplomaticquarterapp/pages/landing/landing_page.dart'; import 'package:diplomaticquarterapp/pages/livecare/video-call-web-page.dart'; +import 'package:diplomaticquarterapp/pages/webRTC/OpenTok/OpenTok.dart'; import 'package:diplomaticquarterapp/pages/webRTC/signaling.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/uitl/utils_new.dart'; @@ -14,6 +16,7 @@ import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/material.dart'; import 'package:just_audio/just_audio.dart'; + class IncomingCall extends StatefulWidget { IncomingCallData incomingCallData; @@ -230,16 +233,24 @@ class _IncomingCallState extends State with SingleTickerProviderSt Future _submit() async { try { // backToHome(); - final roomModel = RoomModel(name: widget.incomingCallData.name, token: widget.incomingCallData.sessionId, identity: widget.incomingCallData.identity); + // final roomModel = RoomModel(name: widget.incomingCallData.name, token: widget.incomingCallData.sessionId, identity: widget.incomingCallData.identity); await _controller.dispose(); await Navigator.of(context).pushReplacement( MaterialPageRoute( // fullscreenDialog: true, builder: (BuildContext context) { - // if (openCallInWeb) - return VideoCallWebPage(receiverId: widget.incomingCallData.receiverID, callerId: widget.incomingCallData.callerID); - // else - // return CallHomePage(receiverId: widget.incomingCallData.receiverID, callerId: widget.incomingCallData.callerID); + // return VideoCallWebPage(receiverId: widget.incomingCallData.receiverID, callerId: widget.incomingCallData.callerID); // Web WebRTC VideoCall + // return CallHomePage(receiverId: widget.incomingCallData.receiverID, callerId: widget.incomingCallData.callerID); // App WebRTC VideoCall + // return OpenTokConnectCallPage( + // apiKey: OPENTOK_API_KEY, + // sessionId: '1_MX40NjIwOTk2Mn5-MTY0NzE3MzcwNjA0MH55RUJoZnd0ZGh2U3BPc01ENVZBelQvT1Z-fg', + // token: 'T1==cGFydG5lcl9pZD00NjIwOTk2MiZzaWc9M2I4ODYxYTIzMGQ0ZDA3OTYyNDhkODIxNzI5ZjIzODM1NjY2YzExMzpzZXNzaW9uX2lkPTFfTVg0ME5qSXdPVGsyTW41LU1UWTBOekUzTXpjd05qQTBNSDU1UlVKb1puZDBaR2gyVTNCUGMwMUVOVlpCZWxRdlQxWi1mZyZjcmVhdGVfdGltZT0xNjQ3MTczNzA2Jm5vbmNlPTAuMjA3NDI0MzA1NzcwMzY4MiZyb2xlPW1vZGVyYXRvciZleHBpcmVfdGltZT0xNjQ3MjYwMTA2JmluaXRpYWxfbGF5b3V0X2NsYXNzX2xpc3Q9' + // ); + return OpenTokConnectCallPage( + apiKey: OPENTOK_API_KEY, + sessionId: widget.incomingCallData.sessionId, + token: widget.incomingCallData.token + ); }, ), ); diff --git a/lib/pages/webRTC/OpenTok/OpenTok.dart b/lib/pages/webRTC/OpenTok/OpenTok.dart index 7abcfca5..68bc815e 100644 --- a/lib/pages/webRTC/OpenTok/OpenTok.dart +++ b/lib/pages/webRTC/OpenTok/OpenTok.dart @@ -1,3 +1,6 @@ +import 'dart:async'; + +import 'package:diplomaticquarterapp/pages/conference/conference_button_bar.dart'; import 'package:diplomaticquarterapp/pages/conference/draggable_publisher.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; @@ -24,6 +27,14 @@ class OpenTokState extends State{ OpenTokPlatformBridge openTokPlatform; OpenTokSDKState sdkState = OpenTokSDKState.LOGGED_OUT; + final StreamController _audioButton = StreamController.broadcast(); + final StreamController _videoButton = StreamController.broadcast(); + final StreamController _onButtonBarVisibleStreamController = StreamController.broadcast(); + final StreamController _onButtonBarHeightStreamController = StreamController.broadcast(); + + var audioMute = false; + var videoMute = false; + initOpenTok(){ openTokPlatform = OpenTokPlatformBridge.init( apiKey: widget.apiKey, @@ -53,50 +64,38 @@ class OpenTokState extends State{ }, child: Icon(Icons.connect_without_contact_outlined, color: Colors.green,)) ], ), - body: Column( + body: Stack( + fit: StackFit.expand, children: [ - Expanded( - child: Stack( - children: [ - if(sdkState == OpenTokSDKState.LOGGED_IN) - ...platformVideoViews(), - - - if(sdkState == OpenTokSDKState.LOGGED_OUT) - Center(child: Text("Logged Out"),), - - if(sdkState == OpenTokSDKState.ERROR) - Center(child: Text("Error opening session"),), - - if(sdkState == OpenTokSDKState.WAIT) - Center(child: CircularProgressIndicator(),), - - if(sdkState == OpenTokSDKState.ON_CALL) - Container(), - ], - ), + if(sdkState == OpenTokSDKState.LOGGED_IN) + ...platformVideoViews(), + + + if(sdkState == OpenTokSDKState.LOGGED_OUT) + Center(child: Text("Logged Out"),), + + if(sdkState == OpenTokSDKState.ERROR) + Center(child: Text("Error opening session"),), + + if(sdkState == OpenTokSDKState.WAIT) + Center(child: CircularProgressIndicator(),), + + if(sdkState == OpenTokSDKState.ON_CALL) + Container(), + + ConferenceButtonBar( + audioEnabled: _audioButton.stream, + videoEnabled: _videoButton.stream, + onAudioEnabled: _onAudioEnable, + onVideoEnabled: _onVideoEnabled, + onSwitchCamera: _onSwitchCamera, + onHangup: _onHangup, + onPersonAdd: () {}, + onPersonRemove: () {}, + onHeight: _onHeightBar, + onShow: _onShowBar, + onHide: _onHideBar, ), - Row( - children: [ - Expanded( - child: ElevatedButton( - child: Text('Mute Video') ,onPressed: () => openTokPlatform.toggleVideo() - ), - ), - SizedBox(width: 20,), - Expanded( - child: ElevatedButton( - child: Text('Mute Audio') ,onPressed: () => openTokPlatform.toggleAudio() - ), - ), - SizedBox(width: 20,), - Expanded( - child: ElevatedButton( - child: Text('Change Camera') ,onPressed: () => openTokPlatform.swapCamera() - ), - ), - ], - ) ], ), ); @@ -176,5 +175,43 @@ class OpenTokState extends State{ }, ); } - + + + _onAudioEnable() async{ + await openTokPlatform.toggleAudio(); + _audioButton.add(!audioMute); + } + + _onVideoEnabled() async{ + await openTokPlatform.toggleVideo(); + _videoButton.add(!videoMute); + } + + _onSwitchCamera() async{ + await openTokPlatform.swapCamera(); + } + + Future _onHangup() async { + print('onHangup'); + await openTokPlatform.hangupCall(); + Navigator.of(context).pop(); + } + + void _onShowBar() { + setState(() { + }); + _onButtonBarVisibleStreamController.add(true); + } + + void _onHeightBar(double height) { + _onButtonBarHeightStreamController.add(height); + } + + void _onHideBar() { + setState(() { + SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom]); + }); + _onButtonBarVisibleStreamController.add(false); + } + } \ No newline at end of file diff --git a/lib/pages/webRTC/OpenTok/OpenTokPlatformBridge.dart b/lib/pages/webRTC/OpenTok/OpenTokPlatformBridge.dart index bfdb8fb4..fd5b7a3d 100644 --- a/lib/pages/webRTC/OpenTok/OpenTokPlatformBridge.dart +++ b/lib/pages/webRTC/OpenTok/OpenTokPlatformBridge.dart @@ -67,20 +67,20 @@ class OpenTokPlatformBridge{ } Future toggleAudio() async { - _publishAudio = !_publishAudio; - dynamic params = {'publishAudio': _publishAudio}; - try { - await _platformMethodChannel.invokeMethod('publishAudio', params); + await _platformMethodChannel.invokeMethod('toggleAudio'); } on PlatformException catch (e) {} } Future toggleVideo() async { - _publishVideo = !_publishVideo; - dynamic params = {'publishVideo': _publishVideo}; + try { + await _platformMethodChannel.invokeMethod('toggleVideo'); + } on PlatformException catch (e) {} + } + Future hangupCall() async { try { - await _platformMethodChannel.invokeMethod('toggleVideo', params); + await _platformMethodChannel.invokeMethod('hangupCall'); } on PlatformException catch (e) {} } } diff --git a/lib/routes.dart b/lib/routes.dart index ab92ee53..fe620bbd 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -1,3 +1,4 @@ +import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/health-weather/health-weather-indicator.dart'; import 'package:diplomaticquarterapp/pages/DrawerPages/family/add-family-member.dart'; import 'package:diplomaticquarterapp/pages/DrawerPages/family/add-family_type.dart'; @@ -84,8 +85,8 @@ var routes = { CALL_PAGE: (_) => CallPage(), INCOMING_CALL_PAGE: (_) => IncomingCall(), OPENTOK_CALL_PAGE: (_) => OpenTokConnectCallPage( - apiKey: '46209962', - sessionId: '1_MX40NjIwOTk2Mn5-MTYzNDY0ODM3NDY2Nn5PcnpnNGM0R1Q3ODZ6UXlFQ01lMDF5YWJ-fg', - token: - 'T1==cGFydG5lcl9pZD00NjIwOTk2MiZzaWc9Y2ZhZjMzZjA3MWFkMjkxN2JmYjEwZDkxYTRkOTdhN2NmNWE4YjMyYTpzZXNzaW9uX2lkPTFfTVg0ME5qSXdPVGsyTW41LU1UWXpORFkwT0RNM05EWTJObjVQY25wbk5HTTBSMVEzT0RaNlVYbEZRMDFsTURGNVlXSi1mZyZjcmVhdGVfdGltZT0xNjM0NjQ4Mzc1Jm5vbmNlPTAuNzczMzcxNDUxMDgzMjQyMyZyb2xlPW1vZGVyYXRvciZleHBpcmVfdGltZT0xNjM0NzM0Nzc1JmluaXRpYWxfbGF5b3V0X2NsYXNzX2xpc3Q9'), + apiKey: OPENTOK_API_KEY, + sessionId: '1_MX40NjIwOTk2Mn5-MTY0NzE3MzcwNjA0MH55RUJoZnd0ZGh2U3BPc01ENVZBelQvT1Z-fg', + token: 'T1==cGFydG5lcl9pZD00NjIwOTk2MiZzaWc9M2I4ODYxYTIzMGQ0ZDA3OTYyNDhkODIxNzI5ZjIzODM1NjY2YzExMzpzZXNzaW9uX2lkPTFfTVg0ME5qSXdPVGsyTW41LU1UWTBOekUzTXpjd05qQTBNSDU1UlVKb1puZDBaR2gyVTNCUGMwMUVOVlpCZWxRdlQxWi1mZyZjcmVhdGVfdGltZT0xNjQ3MTczNzA2Jm5vbmNlPTAuMjA3NDI0MzA1NzcwMzY4MiZyb2xlPW1vZGVyYXRvciZleHBpcmVfdGltZT0xNjQ3MjYwMTA2JmluaXRpYWxfbGF5b3V0X2NsYXNzX2xpc3Q9' + ), }; diff --git a/lib/uitl/utils.dart b/lib/uitl/utils.dart index aed0f47f..9a2d13f7 100644 --- a/lib/uitl/utils.dart +++ b/lib/uitl/utils.dart @@ -51,6 +51,10 @@ import 'app_shared_preferences.dart'; import 'app_toast.dart'; import 'gif_loader_dialog_utils.dart'; import 'navigation_service.dart'; +import 'package:crypto/crypto.dart' as crypto; +import 'dart:convert'; +import 'package:convert/convert.dart'; + AppSharedPreferences sharedPref = new AppSharedPreferences(); @@ -735,6 +739,10 @@ class Utils { ], ); } + + static String generateMd5Hash(String input) { + return crypto.md5.convert(utf8.encode(input)).toString(); + } } Widget applyShadow({Color color = Colors.grey, double shadowOpacity = 0.5, double spreadRadius = 2, double blurRadius = 7, Offset offset = const Offset(2, 2), @required Widget child}) {