CustomMessage handling: send and receive;
Code re-organization: CastDialogOpener, MethodNames;
This commit is contained in:
parent
9e10c120bc
commit
b4b8eb258a
9 changed files with 267 additions and 42 deletions
|
|
@ -7,6 +7,8 @@ import androidx.lifecycle.OnLifecycleEvent
|
||||||
import androidx.lifecycle.ProcessLifecycleOwner
|
import androidx.lifecycle.ProcessLifecycleOwner
|
||||||
import androidx.mediarouter.app.MediaRouteChooserDialog
|
import androidx.mediarouter.app.MediaRouteChooserDialog
|
||||||
import androidx.mediarouter.app.MediaRouteControllerDialog
|
import androidx.mediarouter.app.MediaRouteControllerDialog
|
||||||
|
import com.gianlucaparadise.flutter_cast_framework.cast.CastDialogOpener
|
||||||
|
import com.gianlucaparadise.flutter_cast_framework.cast.MessageCastingChannel
|
||||||
import com.google.android.gms.cast.framework.CastContext
|
import com.google.android.gms.cast.framework.CastContext
|
||||||
import com.google.android.gms.cast.framework.CastSession
|
import com.google.android.gms.cast.framework.CastSession
|
||||||
import com.google.android.gms.cast.framework.SessionManager
|
import com.google.android.gms.cast.framework.SessionManager
|
||||||
|
|
@ -28,23 +30,6 @@ class FlutterCastFrameworkPlugin(private val registrar: Registrar, private val c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private object MethodNames {
|
|
||||||
const val onCastStateChanged = "CastContext.onCastStateChanged"
|
|
||||||
const val showCastDialog = "showCastDialog"
|
|
||||||
|
|
||||||
// region SessionManager
|
|
||||||
const val onSessionStarting = "SessionManager.onSessionStarting"
|
|
||||||
const val onSessionStarted = "SessionManager.onSessionStarted"
|
|
||||||
const val onSessionStartFailed = "SessionManager.onSessionStartFailed"
|
|
||||||
const val onSessionEnding = "SessionManager.onSessionEnding"
|
|
||||||
const val onSessionEnded = "SessionManager.onSessionEnded"
|
|
||||||
const val onSessionResuming = "SessionManager.onSessionResuming"
|
|
||||||
const val onSessionResumed = "SessionManager.onSessionResumed"
|
|
||||||
const val onSessionResumeFailed = "SessionManager.onSessionResumeFailed"
|
|
||||||
const val onSessionSuspended = "SessionManager.onSessionSuspended"
|
|
||||||
// end-region
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
ProcessLifecycleOwner.get().lifecycle.addObserver(this)
|
ProcessLifecycleOwner.get().lifecycle.addObserver(this)
|
||||||
|
|
||||||
|
|
@ -57,16 +42,32 @@ class FlutterCastFrameworkPlugin(private val registrar: Registrar, private val c
|
||||||
private lateinit var mSessionManager: SessionManager
|
private lateinit var mSessionManager: SessionManager
|
||||||
private val mSessionManagerListener = CastSessionManagerListener()
|
private val mSessionManagerListener = CastSessionManagerListener()
|
||||||
|
|
||||||
|
private val mMessageCastingChannel = MessageCastingChannel(channel)
|
||||||
|
|
||||||
|
private var mCastSession: CastSession? = null
|
||||||
|
set(value) {
|
||||||
|
Log.d(TAG, "Updating mCastSession - castSession changed: ${field != value}")
|
||||||
|
// if (field == value) 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)
|
||||||
|
|
||||||
|
field = value
|
||||||
|
|
||||||
|
channel.invokeMethod(MethodNames.getSessionMessageNamespaces, null, result)
|
||||||
|
}
|
||||||
|
|
||||||
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
|
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
|
||||||
fun onCreate() {
|
fun onCreate() {
|
||||||
Log.d(TAG, "App: ON_CREATE")
|
Log.d(TAG, "App: ON_CREATE")
|
||||||
mSessionManager = CastContext.getSharedInstance(registrar.activeContext()).sessionManager
|
mSessionManager = CastContext.getSharedInstance(registrar.activeContext()).sessionManager
|
||||||
|
mCastSession = mSessionManager.currentCastSession
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
|
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
|
||||||
fun onResume() {
|
fun onResume() {
|
||||||
Log.d(TAG, "App: ON_RESUME")
|
Log.d(TAG, "App: ON_RESUME")
|
||||||
mSessionManager.addSessionManagerListener(mSessionManagerListener, CastSession::class.java)
|
mSessionManager.addSessionManagerListener(mSessionManagerListener, CastSession::class.java)
|
||||||
|
mCastSession = mSessionManager.currentCastSession
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
|
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
|
||||||
|
|
@ -76,39 +77,53 @@ class FlutterCastFrameworkPlugin(private val registrar: Registrar, private val c
|
||||||
mSessionManagerListener,
|
mSessionManagerListener,
|
||||||
CastSession::class.java
|
CastSession::class.java
|
||||||
)
|
)
|
||||||
|
// I can't set this to null because I need the cast session to send commands from notification
|
||||||
|
// mCastSession = null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMethodCall(call: MethodCall, result: Result) {
|
override fun onMethodCall(call: MethodCall, result: Result) {
|
||||||
when (call.method) {
|
val method = call.method
|
||||||
MethodNames.showCastDialog -> showCastDialog()
|
val arguments = call.arguments
|
||||||
|
|
||||||
|
when (method) {
|
||||||
|
MethodNames.showCastDialog -> CastDialogOpener.showCastDialog(registrar)
|
||||||
|
MethodNames.sendMessage -> this.mMessageCastingChannel.sendMessage(mCastSession, arguments)
|
||||||
else -> result.notImplemented()
|
else -> result.notImplemented()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showCastDialog() {
|
private inner class NamespaceResult(val oldSession: CastSession?, val newSession: CastSession?) : Result {
|
||||||
val castContext = CastContext.getSharedInstance(registrar.activeContext())
|
override fun notImplemented() {
|
||||||
val castSession = castContext.sessionManager.currentCastSession
|
Log.d(TAG, "Updating mCastSession - notImplemented")
|
||||||
|
}
|
||||||
|
|
||||||
val activity = this.registrar.activity()
|
override fun error(p0: String?, p1: String?, p2: Any?) {
|
||||||
val themeResId = activity.packageManager.getActivityInfo(activity.componentName, 0).themeResource
|
Log.d(TAG, "Updating mCastSession - error - $p0 $p1 $p2")
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
override fun success(args: Any?) {
|
||||||
if (castSession != null) {
|
Log.d(TAG, "Updating mCastSession - success - param: $args")
|
||||||
// This dialog allows the user to control or disconnect from the currently selected route.
|
if (oldSession == null && newSession == null) return // nothing to do here
|
||||||
MediaRouteControllerDialog(registrar.activeContext(), themeResId)
|
if (args == null) return // nothing to do here
|
||||||
.show()
|
|
||||||
} else {
|
if (args !is ArrayList<*>)
|
||||||
// This dialog allows the user to choose a route that matches a given selector.
|
throw IllegalArgumentException("${MethodNames.getSessionMessageNamespaces} method expects an ArrayList<String>")
|
||||||
MediaRouteChooserDialog(registrar.activeContext(), themeResId).apply {
|
|
||||||
routeSelector = castContext.mergedSelector
|
if (!args.any()) return // nothing to do here
|
||||||
show()
|
|
||||||
|
if (args[0] !is String)
|
||||||
|
throw IllegalArgumentException("${MethodNames.getSessionMessageNamespaces} method expects an ArrayList<String>")
|
||||||
|
|
||||||
|
val namespaces = args as ArrayList<String>
|
||||||
|
namespaces.forEach {
|
||||||
|
try {
|
||||||
|
oldSession?.removeMessageReceivedCallbacks(it)
|
||||||
|
newSession?.setMessageReceivedCallbacks(it, mMessageCastingChannel)
|
||||||
|
}
|
||||||
|
catch (e: java.lang.Exception) {
|
||||||
|
Log.e(TAG, "Updating mCastSession - Exception while creating channel", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (ex: IllegalArgumentException) {
|
|
||||||
Log.d(TAG, "Exception while opening Dialog")
|
|
||||||
throw IllegalArgumentException("Error while opening MediaRouteDialog." +
|
|
||||||
" Did you use AppCompat theme on your activity?" +
|
|
||||||
" Check https://developers.google.com/cast/docs/android_sender/integrate#androidtheme", ex)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -123,11 +138,15 @@ class FlutterCastFrameworkPlugin(private val registrar: Registrar, private val c
|
||||||
override fun onSessionStarting(session: CastSession?) {
|
override fun onSessionStarting(session: CastSession?) {
|
||||||
Log.d(TAG, "onSessionStarting")
|
Log.d(TAG, "onSessionStarting")
|
||||||
channel.invokeMethod(MethodNames.onSessionStarting, null)
|
channel.invokeMethod(MethodNames.onSessionStarting, null)
|
||||||
|
|
||||||
|
mCastSession = session
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSessionResuming(session: CastSession?, p1: String?) {
|
override fun onSessionResuming(session: CastSession?, p1: String?) {
|
||||||
Log.d(TAG, "onSessionResuming")
|
Log.d(TAG, "onSessionResuming")
|
||||||
channel.invokeMethod(MethodNames.onSessionResuming, null)
|
channel.invokeMethod(MethodNames.onSessionResuming, null)
|
||||||
|
|
||||||
|
mCastSession = session
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSessionEnding(session: CastSession?) {
|
override fun onSessionEnding(session: CastSession?) {
|
||||||
|
|
@ -148,11 +167,15 @@ class FlutterCastFrameworkPlugin(private val registrar: Registrar, private val c
|
||||||
override fun onSessionStarted(session: CastSession, sessionId: String) {
|
override fun onSessionStarted(session: CastSession, sessionId: String) {
|
||||||
Log.d(TAG, "onSessionStarted")
|
Log.d(TAG, "onSessionStarted")
|
||||||
channel.invokeMethod(MethodNames.onSessionStarted, null)
|
channel.invokeMethod(MethodNames.onSessionStarted, null)
|
||||||
|
|
||||||
|
mCastSession = session
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSessionResumed(session: CastSession, wasSuspended: Boolean) {
|
override fun onSessionResumed(session: CastSession, wasSuspended: Boolean) {
|
||||||
Log.d(TAG, "onSessionResumed")
|
Log.d(TAG, "onSessionResumed")
|
||||||
channel.invokeMethod(MethodNames.onSessionResumed, null)
|
channel.invokeMethod(MethodNames.onSessionResumed, null)
|
||||||
|
|
||||||
|
mCastSession = session
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSessionEnded(session: CastSession, error: Int) {
|
override fun onSessionEnded(session: CastSession, error: Int) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.gianlucaparadise.flutter_cast_framework
|
||||||
|
|
||||||
|
object MethodNames {
|
||||||
|
const val onCastStateChanged = "CastContext.onCastStateChanged"
|
||||||
|
const val showCastDialog = "showCastDialog"
|
||||||
|
|
||||||
|
// region SessionManager
|
||||||
|
const val onSessionStarting = "SessionManager.onSessionStarting"
|
||||||
|
const val onSessionStarted = "SessionManager.onSessionStarted"
|
||||||
|
const val onSessionStartFailed = "SessionManager.onSessionStartFailed"
|
||||||
|
const val onSessionEnding = "SessionManager.onSessionEnding"
|
||||||
|
const val onSessionEnded = "SessionManager.onSessionEnded"
|
||||||
|
const val onSessionResuming = "SessionManager.onSessionResuming"
|
||||||
|
const val onSessionResumed = "SessionManager.onSessionResumed"
|
||||||
|
const val onSessionResumeFailed = "SessionManager.onSessionResumeFailed"
|
||||||
|
const val onSessionSuspended = "SessionManager.onSessionSuspended"
|
||||||
|
// end-region
|
||||||
|
|
||||||
|
const val getSessionMessageNamespaces = "CastSession.getSessionMessageNamespaces"
|
||||||
|
const val onMessageReceived = "CastSession.onMessageReceived"
|
||||||
|
const val sendMessage = "CastSession.sendMessage"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
package com.gianlucaparadise.flutter_cast_framework.cast
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.mediarouter.app.MediaRouteChooserDialog
|
||||||
|
import androidx.mediarouter.app.MediaRouteControllerDialog
|
||||||
|
import com.gianlucaparadise.flutter_cast_framework.FlutterCastFrameworkPlugin
|
||||||
|
import com.google.android.gms.cast.framework.CastContext
|
||||||
|
import io.flutter.plugin.common.PluginRegistry
|
||||||
|
|
||||||
|
object CastDialogOpener {
|
||||||
|
fun showCastDialog(registrar: PluginRegistry.Registrar) {
|
||||||
|
val castContext = CastContext.getSharedInstance(registrar.activeContext())
|
||||||
|
val castSession = castContext.sessionManager.currentCastSession
|
||||||
|
|
||||||
|
val activity = registrar.activity()
|
||||||
|
val themeResId = activity.packageManager.getActivityInfo(activity.componentName, 0).themeResource
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (castSession != null) {
|
||||||
|
// This dialog allows the user to control or disconnect from the currently selected route.
|
||||||
|
MediaRouteControllerDialog(registrar.activeContext(), themeResId)
|
||||||
|
.show()
|
||||||
|
} else {
|
||||||
|
// This dialog allows the user to choose a route that matches a given selector.
|
||||||
|
MediaRouteChooserDialog(registrar.activeContext(), themeResId).apply {
|
||||||
|
routeSelector = castContext.mergedSelector
|
||||||
|
show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (ex: IllegalArgumentException) {
|
||||||
|
Log.d(FlutterCastFrameworkPlugin.TAG, "Exception while opening Dialog")
|
||||||
|
throw IllegalArgumentException("Error while opening MediaRouteDialog." +
|
||||||
|
" Did you use AppCompat theme on your activity?" +
|
||||||
|
" Check https://developers.google.com/cast/docs/android_sender/integrate#androidtheme", ex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
package com.gianlucaparadise.flutter_cast_framework.cast
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import com.gianlucaparadise.flutter_cast_framework.MethodNames
|
||||||
|
import com.google.android.gms.cast.Cast
|
||||||
|
import com.google.android.gms.cast.CastDevice
|
||||||
|
import com.google.android.gms.cast.framework.CastSession
|
||||||
|
import io.flutter.plugin.common.MethodChannel
|
||||||
|
|
||||||
|
class MessageCastingChannel(private val channel: MethodChannel) : Cast.MessageReceivedCallback {
|
||||||
|
companion object {
|
||||||
|
const val TAG = "MessageCastingChannel"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMessageReceived(castDevice: CastDevice?, namespace: String?, message: String?) {
|
||||||
|
Log.d(TAG, "Message received: $message:")
|
||||||
|
val argsMap: HashMap<String, String?> = hashMapOf(
|
||||||
|
"namespace" to namespace,
|
||||||
|
"message" to message
|
||||||
|
)
|
||||||
|
|
||||||
|
channel.invokeMethod(MethodNames.onMessageReceived, argsMap)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sendMessage(castSession: CastSession?, arguments: Any) {
|
||||||
|
Log.d(TAG, "Send Message arguments: $arguments:")
|
||||||
|
val argsMap = arguments as HashMap<String, String?>
|
||||||
|
val namespace = argsMap["namespace"]
|
||||||
|
val message = argsMap["message"]
|
||||||
|
|
||||||
|
sendMessage(castSession, namespace, message)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sendMessage(castSession: CastSession?, namespace: String?, message: String?) {
|
||||||
|
try {
|
||||||
|
if (castSession == null) {
|
||||||
|
Log.d(TAG, "No session")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
castSession.sendMessage(namespace, message)
|
||||||
|
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
Log.e(TAG, "Error while sending ${message}:")
|
||||||
|
Log.e(TAG, ex.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -14,12 +14,25 @@ class MyApp extends StatefulWidget {
|
||||||
class _MyAppState extends State<MyApp> {
|
class _MyAppState extends State<MyApp> {
|
||||||
CastState _castState = CastState.idle;
|
CastState _castState = CastState.idle;
|
||||||
SessionState _sessionState = SessionState.idle;
|
SessionState _sessionState = SessionState.idle;
|
||||||
|
String _message = '';
|
||||||
|
|
||||||
|
final textMessageController = TextEditingController();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
FlutterCastFramework.castContext.state.addListener(_onCastStateChanged);
|
FlutterCastFramework.castContext.state.addListener(_onCastStateChanged);
|
||||||
FlutterCastFramework.castContext.sessionManager.state.addListener(_onSessionStateChanged);
|
FlutterCastFramework.castContext.sessionManager.state
|
||||||
|
.addListener(_onSessionStateChanged);
|
||||||
|
FlutterCastFramework.castContext.sessionManager.onMessageReceived =
|
||||||
|
_onMessageReceived;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
// Clean up the controller when the widget is disposed.
|
||||||
|
textMessageController.dispose();
|
||||||
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onCastStateChanged() {
|
void _onCastStateChanged() {
|
||||||
|
|
@ -32,10 +45,24 @@ class _MyAppState extends State<MyApp> {
|
||||||
void _onSessionStateChanged() {
|
void _onSessionStateChanged() {
|
||||||
debugPrint("Session state changed from example");
|
debugPrint("Session state changed from example");
|
||||||
setState(() {
|
setState(() {
|
||||||
_sessionState = FlutterCastFramework.castContext.sessionManager.state.value;
|
_sessionState =
|
||||||
|
FlutterCastFramework.castContext.sessionManager.state.value;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _onMessageReceived(String namespace, String message) {
|
||||||
|
debugPrint("Message received from example");
|
||||||
|
setState(() {
|
||||||
|
_message = message;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onSendMessage() {
|
||||||
|
String message = this.textMessageController.text;
|
||||||
|
FlutterCastFramework.castContext.sessionManager
|
||||||
|
.sendMessage('urn:x-cast:cast-your-instructions', message);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
|
|
@ -47,8 +74,30 @@ class _MyAppState extends State<MyApp> {
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
CastButton(),
|
CastButton(),
|
||||||
|
Text(
|
||||||
|
'States',
|
||||||
|
style: Theme.of(context).textTheme.title,
|
||||||
|
),
|
||||||
Text('Cast State: $_castState'),
|
Text('Cast State: $_castState'),
|
||||||
Text('Cast State: $_sessionState'),
|
Text('Cast State: $_sessionState'),
|
||||||
|
Text(
|
||||||
|
'Message',
|
||||||
|
style: Theme.of(context).textTheme.title,
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: TextField(
|
||||||
|
controller: textMessageController,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
RaisedButton(
|
||||||
|
child: Text('Send'),
|
||||||
|
onPressed: _onSendMessage,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Text('Received Message: $_message'),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -11,4 +11,8 @@ class PlatformMethodNames {
|
||||||
static const onSessionResumed = "SessionManager.onSessionResumed";
|
static const onSessionResumed = "SessionManager.onSessionResumed";
|
||||||
static const onSessionResumeFailed = "SessionManager.onSessionResumeFailed";
|
static const onSessionResumeFailed = "SessionManager.onSessionResumeFailed";
|
||||||
static const onSessionSuspended = "SessionManager.onSessionSuspended";
|
static const onSessionSuspended = "SessionManager.onSessionSuspended";
|
||||||
|
|
||||||
|
static const getSessionMessageNamespaces = "CastSession.getSessionMessageNamespaces";
|
||||||
|
static const onMessageReceived = "CastSession.onMessageReceived";
|
||||||
|
static const sendMessage = "CastSession.sendMessage";
|
||||||
}
|
}
|
||||||
|
|
@ -18,7 +18,13 @@ class CastContext {
|
||||||
state.value = CastState.values[castState];
|
state.value = CastState.values[castState];
|
||||||
}
|
}
|
||||||
|
|
||||||
SessionManager sessionManager = SessionManager();
|
SessionManager _sessionManager;
|
||||||
|
SessionManager get sessionManager {
|
||||||
|
if (_sessionManager == null) {
|
||||||
|
_sessionManager = SessionManager(_channel);
|
||||||
|
}
|
||||||
|
return _sessionManager;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum CastState {
|
enum CastState {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,12 @@
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_cast_framework/MethodNames.dart';
|
import 'package:flutter_cast_framework/MethodNames.dart';
|
||||||
|
|
||||||
class SessionManager {
|
class SessionManager {
|
||||||
|
final MethodChannel _channel;
|
||||||
|
|
||||||
|
SessionManager(this._channel);
|
||||||
|
|
||||||
final ValueNotifier<SessionState> state = ValueNotifier(SessionState.idle);
|
final ValueNotifier<SessionState> state = ValueNotifier(SessionState.idle);
|
||||||
|
|
||||||
void onSessionStateChanged(String method, dynamic arguments) {
|
void onSessionStateChanged(String method, dynamic arguments) {
|
||||||
|
|
@ -35,8 +40,29 @@ class SessionManager {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MessageReceivedCallback onMessageReceived;
|
||||||
|
|
||||||
|
void platformOnMessageReceived(dynamic arguments) {
|
||||||
|
if (onMessageReceived == null) return;
|
||||||
|
final namespace = arguments['namespace'];
|
||||||
|
final message = arguments['message'];
|
||||||
|
|
||||||
|
onMessageReceived(namespace, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendMessage(String namespace, String message) {
|
||||||
|
final argsMap = {
|
||||||
|
'namespace': namespace,
|
||||||
|
'message': '{"message":"$message"}'
|
||||||
|
};
|
||||||
|
_channel.invokeMethod(PlatformMethodNames.sendMessage, argsMap);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef MessageReceivedCallback = void Function(
|
||||||
|
String namespace, String message);
|
||||||
|
|
||||||
enum SessionState {
|
enum SessionState {
|
||||||
idle,
|
idle,
|
||||||
session_starting,
|
session_starting,
|
||||||
|
|
|
||||||
|
|
@ -32,10 +32,19 @@ class FlutterCastFramework {
|
||||||
castContext.sessionManager.onSessionStateChanged(method, arguments);
|
castContext.sessionManager.onSessionStateChanged(method, arguments);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PlatformMethodNames.getSessionMessageNamespaces:
|
||||||
|
return ["urn:x-cast:cast-your-instructions"];
|
||||||
|
|
||||||
|
case PlatformMethodNames.onMessageReceived:
|
||||||
|
castContext.sessionManager.platformOnMessageReceived(arguments);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
debugPrint("Method not handled: $method");
|
debugPrint("Method not handled: $method");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue