Merge branch 'zik_new_design_2.0' into 'development_new_design_2.0'
Zik new design 2.0 See merge request Cloud_Solution/diplomatic-quarter!454merge-requests/456/merge
commit
d6d85092ee
@ -0,0 +1,74 @@
|
||||
{
|
||||
"agcgw":{
|
||||
"backurl":"connect-drcn.hispace.hicloud.com",
|
||||
"url":"connect-drcn.dbankcloud.cn",
|
||||
"websocketbackurl":"connect-ws-drcn.hispace.dbankcloud.com",
|
||||
"websocketurl":"connect-ws-drcn.hispace.dbankcloud.cn"
|
||||
},
|
||||
"agcgw_all":{
|
||||
"CN":"connect-drcn.dbankcloud.cn",
|
||||
"CN_back":"connect-drcn.hispace.hicloud.com",
|
||||
"DE":"connect-dre.dbankcloud.cn",
|
||||
"DE_back":"connect-dre.hispace.hicloud.com",
|
||||
"RU":"connect-drru.dbankcloud.cn",
|
||||
"RU_back":"connect-drru.hispace.hicloud.com",
|
||||
"SG":"connect-dra.dbankcloud.cn",
|
||||
"SG_back":"connect-dra.hispace.hicloud.com"
|
||||
},
|
||||
"client":{
|
||||
"cp_id":"2640966000002322881",
|
||||
"product_id":"736430079244816567",
|
||||
"client_id":"563735388191982656",
|
||||
"client_secret":"650C7C799812AFFD53A10C7756CF05FB9F215A7E49032ABA8EBF3E14B77535CF",
|
||||
"project_id":"736430079244816567",
|
||||
"app_id":"102857389",
|
||||
"api_key":"CgB6e3x9DJzMgRCmnT6dyUEkp6UsIfddb6l3w0ZEXzeiRMHEFi3400Z5fJ5qaHneU0OrAI/JRpk+DMGVs3QpUxlI",
|
||||
"package_name":"com.ejada.hmg"
|
||||
},
|
||||
"oauth_client":{
|
||||
"client_id":"102857389",
|
||||
"client_type":1
|
||||
},
|
||||
"app_info":{
|
||||
"app_id":"102857389",
|
||||
"package_name":"com.ejada.hmg"
|
||||
},
|
||||
"service":{
|
||||
"analytics":{
|
||||
"collector_url":"datacollector-drcn.dt.hicloud.com,datacollector-drcn.dt.dbankcloud.cn",
|
||||
"collector_url_ru":"datacollector-drru.dt.hicloud.com,datacollector-drru.dt.dbankcloud.cn",
|
||||
"collector_url_sg":"datacollector-dra.dt.hicloud.com,datacollector-dra.dt.dbankcloud.cn",
|
||||
"collector_url_de":"datacollector-dre.dt.hicloud.com,datacollector-dre.dt.dbankcloud.cn",
|
||||
"collector_url_cn":"datacollector-drcn.dt.hicloud.com,datacollector-drcn.dt.dbankcloud.cn",
|
||||
"resource_id":"p1",
|
||||
"channel_id":""
|
||||
},
|
||||
"search":{
|
||||
"url":"https://search-drcn.cloud.huawei.com"
|
||||
},
|
||||
"cloudstorage":{
|
||||
"storage_url":"https://agc-storage-drcn.platform.dbankcloud.cn"
|
||||
},
|
||||
"ml":{
|
||||
"mlservice_url":"ml-api-drcn.ai.dbankcloud.com,ml-api-drcn.ai.dbankcloud.cn"
|
||||
}
|
||||
},
|
||||
"region":"CN",
|
||||
"configuration_version":"3.0",
|
||||
"appInfos":[
|
||||
{
|
||||
"package_name":"com.ejada.hmg",
|
||||
"client":{
|
||||
"app_id":"102857389"
|
||||
},
|
||||
"app_info":{
|
||||
"package_name":"com.ejada.hmg",
|
||||
"app_id":"102857389"
|
||||
},
|
||||
"oauth_client":{
|
||||
"client_type":1,
|
||||
"client_id":"102857389"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Binary file not shown.
@ -0,0 +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)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,168 @@
|
||||
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.opentok.android.*
|
||||
import io.flutter.embedding.engine.FlutterEngine
|
||||
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<String>("apiKey"))
|
||||
val sessionId = requireNotNull(call.argument<String>("sessionId"))
|
||||
val token = requireNotNull(call.argument<String>("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<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: OpenTokSDKState) {
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "OpenTok-Platform-Bridge")
|
||||
.invokeMethod("updateState", state.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +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)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1 +1 @@
|
||||
e52eba3667a38bec777870899c15ae7d
|
||||
3f8c659591fcdd0e47e3895f74af395c
|
||||
@ -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,179 @@
|
||||
//
|
||||
// OpenTok.swift
|
||||
// Runner
|
||||
//
|
||||
// Created by Zohaib Iqbal Kambrani on 18/10/2021.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import OpenTok
|
||||
import UIKit
|
||||
|
||||
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?
|
||||
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)")
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,91 @@
|
||||
//
|
||||
// OpenTokLocalVideoFactory.swift
|
||||
// Runner
|
||||
//
|
||||
// Created by Zohaib Iqbal Kambrani on 20/10/2021.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class OpenTokLocalVideoFactory: NSObject, FlutterPlatformViewFactory {
|
||||
static var view: LocalVideoPlatformView?
|
||||
|
||||
static var viewToAddPub: UIView?
|
||||
|
||||
static func getViewInstance(
|
||||
frame: CGRect,
|
||||
viewId: Int64,
|
||||
args: Any?,
|
||||
messenger: FlutterBinaryMessenger?
|
||||
) -> LocalVideoPlatformView{
|
||||
if(view == nil) {
|
||||
view = LocalVideoPlatformView()
|
||||
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 OpenTokLocalVideoFactory.getViewInstance(
|
||||
frame: frame,
|
||||
viewId: viewId,
|
||||
args: args,
|
||||
messenger: messenger)
|
||||
}
|
||||
}
|
||||
|
||||
class LocalVideoPlatformView: NSObject, FlutterPlatformView {
|
||||
private let videoContainer: LocalVideoContainer
|
||||
|
||||
override init() {
|
||||
videoContainer = LocalVideoContainer()
|
||||
super.init()
|
||||
}
|
||||
|
||||
public func addPublisherView(_ view: UIView) {
|
||||
videoContainer.addPublisherView(view)
|
||||
}
|
||||
|
||||
func view() -> UIView {
|
||||
return videoContainer
|
||||
}
|
||||
}
|
||||
|
||||
final class LocalVideoContainer: UIView {
|
||||
private let publisherContainer = UIView()
|
||||
|
||||
init() {
|
||||
super.init(frame: .zero)
|
||||
addSubview(publisherContainer)
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
publisherContainer.frame = CGRect(x: 0, y: 0, width: width, height: height)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,91 @@
|
||||
//
|
||||
// OpenTokRemoteVideoFactory.swift
|
||||
// Runner
|
||||
//
|
||||
// Created by Zohaib Iqbal Kambrani on 20/10/2021.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class OpenTokRemoteVideoFactory: NSObject, FlutterPlatformViewFactory {
|
||||
static var view: RemoteVideoPlatformView?
|
||||
|
||||
static var viewToAddSub: UIView?
|
||||
|
||||
static func getViewInstance(
|
||||
frame: CGRect,
|
||||
viewId: Int64,
|
||||
args: Any?,
|
||||
messenger: FlutterBinaryMessenger?
|
||||
) -> RemoteVideoPlatformView{
|
||||
if(view == nil) {
|
||||
view = RemoteVideoPlatformView()
|
||||
if viewToAddSub != nil {
|
||||
view?.addSubscriberView(viewToAddSub!)
|
||||
}
|
||||
}
|
||||
|
||||
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 OpenTokRemoteVideoFactory.getViewInstance(
|
||||
frame: frame,
|
||||
viewId: viewId,
|
||||
args: args,
|
||||
messenger: messenger)
|
||||
}
|
||||
}
|
||||
|
||||
class RemoteVideoPlatformView: NSObject, FlutterPlatformView {
|
||||
private let videoContainer: RemoteVideoContainer
|
||||
|
||||
override init() {
|
||||
videoContainer = RemoteVideoContainer()
|
||||
super.init()
|
||||
}
|
||||
|
||||
public func addSubscriberView(_ view: UIView) {
|
||||
videoContainer.addSubscriberView(view)
|
||||
}
|
||||
|
||||
func view() -> UIView {
|
||||
return videoContainer
|
||||
}
|
||||
}
|
||||
|
||||
final class RemoteVideoContainer: UIView {
|
||||
private let subscriberContainer = UIView()
|
||||
|
||||
init() {
|
||||
super.init(frame: .zero)
|
||||
addSubview(subscriberContainer)
|
||||
}
|
||||
|
||||
|
||||
public func addSubscriberView(_ view: UIView) {
|
||||
subscriberContainer.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
|
||||
subscriberContainer.frame = CGRect(x: 0, y: 0, width: width, height: height)
|
||||
}
|
||||
}
|
||||
@ -1,20 +1,41 @@
|
||||
import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
||||
class PackagesCustomerRequestModel {
|
||||
|
||||
String username;
|
||||
String first_name;
|
||||
String last_name;
|
||||
String email;
|
||||
String phoneNumber;
|
||||
String phone;
|
||||
String national_id;
|
||||
String date_of_birth;
|
||||
|
||||
PackagesCustomerRequestModel({@required this.email, @required this.phoneNumber});
|
||||
|
||||
PackagesCustomerRequestModel.fromUser(AuthenticatedUser user){
|
||||
this.username = "${user.patientID}";
|
||||
this.first_name = user.firstName;
|
||||
this.last_name = user.lastName;
|
||||
this.email = user.emailAddress;
|
||||
this.phone = user.mobileNumber;
|
||||
this.national_id = user.patientIdentificationNo;
|
||||
this.date_of_birth = user.dateofBirth;
|
||||
}
|
||||
|
||||
Map<String, dynamic> json() {
|
||||
return {
|
||||
"customer" : {
|
||||
"email": email,
|
||||
"addresses": [{
|
||||
"email": email,
|
||||
"phone_number": phoneNumber
|
||||
}]
|
||||
"email": email ?? '',
|
||||
"username": username ?? '',
|
||||
"national_id": national_id ?? '',
|
||||
"phone": phone ?? '',
|
||||
"date_of_birth": date_of_birth ?? '',
|
||||
"first_name": first_name ?? '',
|
||||
"last_name": last_name ?? '',
|
||||
// "addresses": [{
|
||||
// "email": email,
|
||||
// "phone_number": phoneNumber
|
||||
// }]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -0,0 +1,180 @@
|
||||
import 'package:diplomaticquarterapp/pages/conference/draggable_publisher.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'OpenTokPlatformBridge.dart';
|
||||
|
||||
|
||||
class OpenTokConnectCallPage extends StatefulWidget{
|
||||
final String sessionId;
|
||||
final String token;
|
||||
final String apiKey;
|
||||
OpenTokConnectCallPage({@required this.sessionId, @required this.token, @required this.apiKey});
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => OpenTokState();
|
||||
|
||||
}
|
||||
|
||||
class OpenTokState extends State<OpenTokConnectCallPage>{
|
||||
OpenTokPlatformBridge openTokPlatform;
|
||||
OpenTokSDKState sdkState = OpenTokSDKState.LOGGED_OUT;
|
||||
|
||||
initOpenTok(){
|
||||
openTokPlatform = OpenTokPlatformBridge.init(
|
||||
apiKey: widget.apiKey,
|
||||
sessionID: widget.sessionId,
|
||||
token: widget.token,
|
||||
onStateChange: (state) {
|
||||
setState(() => sdkState = state);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
initOpenTok();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
extendBodyBehindAppBar: true,
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
actions: [
|
||||
TextButton(onPressed: (){
|
||||
initOpenTok();
|
||||
}, child: Icon(Icons.connect_without_contact_outlined, color: Colors.green,))
|
||||
],
|
||||
),
|
||||
body: Column(
|
||||
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(),
|
||||
],
|
||||
),
|
||||
),
|
||||
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()
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
bool remoteVideoOnFull = true;
|
||||
List<Widget> platformVideoViews(){
|
||||
return [
|
||||
SizedBox(
|
||||
width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height,
|
||||
child: remoteVideoOnFull ? remotePlatformVideoView() : localPlatformVideoView()
|
||||
),
|
||||
|
||||
DraggablePublisher(
|
||||
onButtonBarHeight: ((double)async*{}(50)),
|
||||
onButtonBarVisible: ((bool)async*{}(true)),
|
||||
availableScreenSize: MediaQuery.of(context).size,
|
||||
child: InkWell(
|
||||
child: (remoteVideoOnFull ? localPlatformVideoView() : remotePlatformVideoView()),
|
||||
onTap: (){
|
||||
print('');
|
||||
},
|
||||
),
|
||||
)
|
||||
];
|
||||
}
|
||||
|
||||
Widget localPlatformVideoView(){
|
||||
return PlatformViewLink(
|
||||
viewType: 'local-video-container', // custom platform-view-type
|
||||
surfaceFactory:
|
||||
(BuildContext context, PlatformViewController controller) {
|
||||
return AndroidViewSurface(
|
||||
controller: controller,
|
||||
gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{},
|
||||
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
|
||||
);
|
||||
},
|
||||
|
||||
onCreatePlatformView: (PlatformViewCreationParams params) {
|
||||
return PlatformViewsService.initSurfaceAndroidView(
|
||||
id: params.id,
|
||||
viewType: 'local-video-container',
|
||||
// custom platform-view-type,
|
||||
layoutDirection: TextDirection.ltr,
|
||||
creationParams: {},
|
||||
creationParamsCodec: StandardMessageCodec(),
|
||||
)
|
||||
..addOnPlatformViewCreatedListener(params.onPlatformViewCreated)
|
||||
..create();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget remotePlatformVideoView(){
|
||||
return PlatformViewLink(
|
||||
viewType: 'remote-video-container', // custom platform-view-type
|
||||
surfaceFactory:
|
||||
(BuildContext context, PlatformViewController controller) {
|
||||
return AndroidViewSurface(
|
||||
controller: controller,
|
||||
gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{},
|
||||
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
|
||||
);
|
||||
},
|
||||
onCreatePlatformView: (PlatformViewCreationParams params) {
|
||||
return PlatformViewsService.initSurfaceAndroidView(
|
||||
id: params.id,
|
||||
viewType: 'remote-video-container',
|
||||
// custom platform-view-type,
|
||||
layoutDirection: TextDirection.ltr,
|
||||
creationParams: {},
|
||||
creationParamsCodec: StandardMessageCodec(),
|
||||
)
|
||||
..addOnPlatformViewCreatedListener(params.onPlatformViewCreated)
|
||||
..create();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,86 @@
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
enum OpenTokSDKState{ LOGGED_OUT, LOGGED_IN, WAIT, ON_CALL, ERROR }
|
||||
final _platformMethodChannel = const MethodChannel('OpenTok-Platform-Bridge');
|
||||
|
||||
class OpenTokPlatformBridge{
|
||||
|
||||
|
||||
OpenTokSDKState _sdkState = OpenTokSDKState.LOGGED_OUT;
|
||||
bool _publishAudio = true;
|
||||
bool _publishVideo = true;
|
||||
|
||||
final void Function(OpenTokSDKState) onStateChange;
|
||||
|
||||
OpenTokPlatformBridge.init({@required String sessionID, @required String token, @required String apiKey, this.onStateChange}){
|
||||
_initSession({'apiKey':apiKey, 'sessionId':sessionID, 'token':token, });
|
||||
_platformMethodChannel.setMethodCallHandler(incomingMethodHadler);
|
||||
}
|
||||
|
||||
Future<dynamic> incomingMethodHadler(MethodCall methodCall) async {
|
||||
switch (methodCall.method) {
|
||||
case 'updateState':
|
||||
{
|
||||
var arguments = 'OpenTokSDKState.${methodCall.arguments}';
|
||||
_sdkState = OpenTokSDKState.values.firstWhere((v) {
|
||||
return v.toString() == arguments;
|
||||
});
|
||||
onStateChange(_sdkState);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw MissingPluginException('notImplemented');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Future<void> _initSession(Map<String,String> openTokCredentials) async {
|
||||
await requestPermissions();
|
||||
try {
|
||||
await _platformMethodChannel.invokeMethod('initSession', openTokCredentials);
|
||||
} on PlatformException catch (e) {
|
||||
print(e);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> makeCall() async {
|
||||
try {
|
||||
await requestPermissions();
|
||||
|
||||
await _platformMethodChannel.invokeMethod('makeCall');
|
||||
} on PlatformException catch (e) {
|
||||
print(e);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> requestPermissions() async {
|
||||
await [Permission.microphone, Permission.camera].request();
|
||||
}
|
||||
|
||||
Future<void> swapCamera() async {
|
||||
try {
|
||||
await _platformMethodChannel.invokeMethod('swapCamera');
|
||||
} on PlatformException catch (e) {}
|
||||
}
|
||||
|
||||
Future<void> toggleAudio() async {
|
||||
_publishAudio = !_publishAudio;
|
||||
dynamic params = {'publishAudio': _publishAudio};
|
||||
|
||||
try {
|
||||
await _platformMethodChannel.invokeMethod('publishAudio', params);
|
||||
} on PlatformException catch (e) {}
|
||||
}
|
||||
|
||||
Future<void> toggleVideo() async {
|
||||
_publishVideo = !_publishVideo;
|
||||
dynamic params = {'publishVideo': _publishVideo};
|
||||
|
||||
try {
|
||||
await _platformMethodChannel.invokeMethod('toggleVideo', params);
|
||||
} on PlatformException catch (e) {}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue