diff --git a/ios/Classes/MessageCastingChannel.swift b/ios/Classes/MessageCastingChannel.swift new file mode 100644 index 0000000..7b19687 --- /dev/null +++ b/ios/Classes/MessageCastingChannel.swift @@ -0,0 +1,67 @@ +// +// MessageCastingChannel.swift +// flutter_cast_framework +// +// Created by Gianluca Paradiso on 16/11/2019. +// + +import Foundation +import GoogleCast + +class MessageCastingChannel : GCKCastChannel { + + let channel: FlutterMethodChannel + let namespace: String + + init(namespace: String, channel: FlutterMethodChannel) { + self.channel = channel + self.namespace = namespace + super.init(namespace: namespace) + } + + override func didReceiveTextMessage(_ message: String) { + print("Message received: .\(message)") + let argsMap: NSDictionary = [ + "namespace": namespace, + "message": message + ] + + channel.invokeMethod(MethodNames.onMessageReceived.rawValue, arguments: argsMap) + } + + public static func sendMessage(allCastingChannels: Dictionary, arguments: Any?) { + let argsMap = arguments as? NSDictionary + if (argsMap == nil) { + print("Arguments not valid: can't send message") + return + } + + let namespaceRaw = argsMap?.value(forKey: "namespace") as? String + let messageRaw = argsMap?.value(forKey: "message") as? String + + if (namespaceRaw == nil) { + print("Namespace not valid: can't send message") + return + } + + let namespace = namespaceRaw! + let message = messageRaw ?? "" + + let castingChannel = allCastingChannels[namespace] + + if (castingChannel == nil) { + print("Namespace not registered: can't send message") + } + + castingChannel?.sendMessage(message: message) + } + + private func sendMessage(message: String) { + var error: GCKError? + self.sendTextMessage(message, error: &error) + + if error != nil { + print("Error sending text message \(error.debugDescription)") + } + } +} diff --git a/ios/Classes/MethodNames.swift b/ios/Classes/MethodNames.swift index b733592..7427b22 100644 --- a/ios/Classes/MethodNames.swift +++ b/ios/Classes/MethodNames.swift @@ -22,4 +22,8 @@ enum MethodNames : String { case onSessionResumeFailed = "SessionManager.onSessionResumeFailed" case onSessionSuspended = "SessionManager.onSessionSuspended" // end-region + + case getSessionMessageNamespaces = "CastSession.getSessionMessageNamespaces" + case onMessageReceived = "CastSession.onMessageReceived" + case sendMessage = "CastSession.sendMessage" } diff --git a/ios/Classes/SwiftFlutterCastFrameworkPlugin.swift b/ios/Classes/SwiftFlutterCastFrameworkPlugin.swift index 7fcec4c..549614a 100644 --- a/ios/Classes/SwiftFlutterCastFrameworkPlugin.swift +++ b/ios/Classes/SwiftFlutterCastFrameworkPlugin.swift @@ -15,18 +15,48 @@ public class SwiftFlutterCastFrameworkPlugin: NSObject, FlutterPlugin, GCKSessio private let sessionManager: GCKSessionManager + private var castingChannels: Dictionary = [:] + var _castSession: GCKCastSession? var castSession: GCKCastSession? { get { return _castSession } set { print("Updating castSession - castSession changed: \(_castSession != newValue)") - // if (_castSession == newValue) return // Despite the instances are the same, I need to re-attach the listener to every new session instance - - // val result = NamespaceResult(oldSession = field, newSession = value) - + + let oldSession = _castSession + let newSession = newValue + _castSession = newValue - // channel.invokeMethod(MethodNames.getSessionMessageNamespaces, null, result) + channel.invokeMethod(MethodNames.getSessionMessageNamespaces.rawValue, arguments: nil) { (args) in + print("Updating castSession - success - param: \(args ?? "-")") + if (oldSession == nil && newSession == nil) { + return // nothing to do here + } + + let namespaces = args as? NSArray + if (namespaces == nil || namespaces?.count == 0) { + return // nothing to do here + } + + // removing castingChannels from old session + if (oldSession != nil && self.castingChannels.count != 0) { + self.castingChannels.values.forEach { (castingChannel) in + oldSession?.remove(castingChannel) + } + } + + namespaces?.forEach({ (namespaceRaw) in + if (!(namespaceRaw is String)) { + return + } + + let namespace = namespaceRaw as! String + let castingChannel = MessageCastingChannel.init(namespace: namespace, channel: self.channel) + self.castingChannels[namespace] = castingChannel + newSession?.add(castingChannel) + }) + } } } @@ -44,9 +74,9 @@ public class SwiftFlutterCastFrameworkPlugin: NSObject, FlutterPlugin, GCKSessio let app = UIApplication.shared notificationCenter.addObserver(self, selector: #selector(appDidBecomeActive), name: NSNotification.Name.UIApplicationDidBecomeActive, object: app) notificationCenter.addObserver(self, selector: #selector(appWillResignActive), name: NSNotification.Name.UIApplicationWillResignActive, object: app) - notificationCenter.addObserver(self, selector: #selector(appDidEnterBackground), name: NSNotification.Name.UIApplicationDidEnterBackground, object: app) - notificationCenter.addObserver(self, selector: #selector(appWillEnterForeground), name: NSNotification.Name.UIApplicationWillEnterForeground, object: app) - notificationCenter.addObserver(self, selector: #selector(appWillTerminate), name: NSNotification.Name.UIApplicationWillTerminate, object: app) + //notificationCenter.addObserver(self, selector: #selector(appDidEnterBackground), name: NSNotification.Name.UIApplicationDidEnterBackground, object: app) + //notificationCenter.addObserver(self, selector: #selector(appWillEnterForeground), name: NSNotification.Name.UIApplicationWillEnterForeground, object: app) + //notificationCenter.addObserver(self, selector: #selector(appWillTerminate), name: NSNotification.Name.UIApplicationWillTerminate, object: app) } @objc func appDidBecomeActive() { @@ -63,18 +93,6 @@ public class SwiftFlutterCastFrameworkPlugin: NSObject, FlutterPlugin, GCKSessio self.castSession = nil } - @objc func appDidEnterBackground() { - print("AppLife: appDidEnterBackground") - } - - @objc func appWillEnterForeground() { - print("AppLife: appWillEnterForeground") - } - - @objc func appWillTerminate() { - print("AppLife: appWillTerminate") - } - private func onCastStateChanged(state: GCKCastContext, change: NSKeyValueObservedChange) { let castState = GCKCastContext.sharedInstance().castState print("cast state change to: \(castState.rawValue)") @@ -92,6 +110,8 @@ public class SwiftFlutterCastFrameworkPlugin: NSObject, FlutterPlugin, GCKSessio switch call.method { case MethodNames.showCastDialog.rawValue: castContext.presentCastDialog() + case MethodNames.sendMessage.rawValue: + MessageCastingChannel.sendMessage(allCastingChannels: self.castingChannels, arguments: call.arguments) default: print("Method [\(call.method)] is not implemented.") }