Show dialog on click

This commit is contained in:
gianlucaparadise 2019-11-09 10:01:11 +01:00
parent 4af81e646d
commit 9b90e62d76
9 changed files with 102 additions and 53 deletions

View file

@ -1,6 +1,8 @@
package com.gianlucaparadise.flutter_cast_framework package com.gianlucaparadise.flutter_cast_framework
import android.util.Log import android.util.Log
import androidx.mediarouter.app.MediaRouteChooserDialog
import androidx.mediarouter.app.MediaRouteControllerDialog
import com.google.android.gms.cast.framework.CastContext import com.google.android.gms.cast.framework.CastContext
import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodChannel
@ -8,27 +10,59 @@ import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result import io.flutter.plugin.common.MethodChannel.Result
import io.flutter.plugin.common.PluginRegistry.Registrar import io.flutter.plugin.common.PluginRegistry.Registrar
class FlutterCastFrameworkPlugin(registrar: Registrar, private val channel: MethodChannel): MethodCallHandler { class FlutterCastFrameworkPlugin(private val registrar: Registrar, private val channel: MethodChannel) : MethodCallHandler {
companion object { companion object {
@JvmStatic const val TAG = "AndroidCastPlugin"
fun registerWith(registrar: Registrar) {
val channel = MethodChannel(registrar.messenger(), "flutter_cast_framework")
channel.setMethodCallHandler(FlutterCastFrameworkPlugin(registrar, channel))
}
}
init { // @StyleRes
CastContext.getSharedInstance(registrar.activeContext()).addCastStateListener { i -> // var customStyleResId: Int? = null
Log.d("Android", "Method call on flutter: $i") // private val themeResId get() = customStyleResId ?: R.style.Theme_AppCompat_DayNight_Dialog_Alert
channel.invokeMethod("onCastStateChanged", i)
}
}
override fun onMethodCall(call: MethodCall, result: Result) { @JvmStatic
if (call.method == "getPlatformVersion") { fun registerWith(registrar: Registrar) {
result.success("Android ${android.os.Build.VERSION.RELEASE}") val channel = MethodChannel(registrar.messenger(), "flutter_cast_framework")
} else { channel.setMethodCallHandler(FlutterCastFrameworkPlugin(registrar, channel))
result.notImplemented() }
}
init {
CastContext.getSharedInstance(registrar.activeContext()).addCastStateListener { i ->
Log.d(TAG, "Cast state changed: $i")
channel.invokeMethod("onCastStateChanged", i)
}
}
override fun onMethodCall(call: MethodCall, result: Result) {
when (call.method) {
"showCastDialog" -> showCastDialog()
else -> result.notImplemented()
}
}
private fun showCastDialog() {
val castContext = CastContext.getSharedInstance(registrar.activeContext())
val castSession = castContext.sessionManager.currentCastSession
val activity = this.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(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)
}
} }
}
} }

View file

@ -62,6 +62,8 @@ flutter {
dependencies { dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
implementation 'androidx.appcompat:appcompat:1.1.0'
androidTestImplementation 'androidx.test:runner:1.1.1' androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
} }

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar"> <style name="LaunchTheme" parent="@style/Theme.AppCompat">
<!-- Show a splash screen on the activity. Automatically removed when <!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame --> Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item> <item name="android:windowBackground">@drawable/launch_background</item>

View file

@ -1,6 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_cast_framework/cast/CastContext.dart'; import 'package:flutter_cast_framework/cast/CastContext.dart';
import 'package:flutter_cast_framework/cast/widget/CastButton.dart'; import 'package:flutter_cast_framework/cast/widgets/CastButton.dart';
import 'package:flutter_cast_framework/flutter_cast_framework.dart'; import 'package:flutter_cast_framework/flutter_cast_framework.dart';
void main() => runApp(MyApp()); void main() => runApp(MyApp());
@ -20,6 +20,7 @@ class _MyAppState extends State<MyApp> {
} }
void _onCastStateChanged() { void _onCastStateChanged() {
debugPrint("Cast state changed from example");
setState(() { setState(() {
_castState = FlutterCastFramework.castContext.state.value; _castState = FlutterCastFramework.castContext.state.value;
}); });
@ -33,13 +34,9 @@ class _MyAppState extends State<MyApp> {
title: const Text('Cast plugin example app'), title: const Text('Cast plugin example app'),
), ),
body: Center( body: Center(
child: Column( child: Column(
children: [ children: [Text('Cast State: $_castState'), CastButton()],
Text('Cast State: $_castState'), )),
CastButton()
],
)
),
), ),
); );
} }

View file

@ -1,13 +1,16 @@
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:flutter_cast_framework/flutter_cast_framework.dart';
class CastContext { class CastContext {
static final _instance = new CastContext._internal();
CastContext._internal();
static CastContext get instance => _instance;
final ValueNotifier<CastState> state = ValueNotifier(CastState.unavailable); final ValueNotifier<CastState> state = ValueNotifier(CastState.unavailable);
final MethodChannel _channel;
CastContext(this._channel);
void showCastChooserDialog() {
_channel.invokeMethod(MethodNames.showCastDialog);
}
} }
enum CastState { enum CastState {
@ -16,4 +19,4 @@ enum CastState {
unconnected, // 2 unconnected, // 2
connecting, // 3 connecting, // 3
connected, // 4 connected, // 4
} }

View file

@ -1,12 +0,0 @@
import 'package:flutter/widgets.dart';
import 'package:flutter_cast_framework/cast/widget/CastIcon.dart';
class CastButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GestureDetector(
child: CastIcon(),
onTap: () => debugPrint("Clicked"),
);
}
}

View file

@ -0,0 +1,12 @@
import 'package:flutter/widgets.dart';
import 'package:flutter_cast_framework/cast/widgets/CastIcon.dart';
import 'package:flutter_cast_framework/flutter_cast_framework.dart';
class CastButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GestureDetector(
child: CastIcon(),
onTap: () => FlutterCastFramework.castContext.showCastChooserDialog());
}
}

View file

@ -2,11 +2,17 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_cast_framework/cast/CastContext.dart'; import 'package:flutter_cast_framework/cast/CastContext.dart';
class FlutterCastFramework { class MethodNames {
static const onCastStateChanged = "onCastStateChanged";
static const showCastDialog = "showCastDialog";
}
static const MethodChannel _channel = const MethodChannel('flutter_cast_framework'); class FlutterCastFramework {
static const MethodChannel _channel =
const MethodChannel('flutter_cast_framework');
static bool _isInitiated = false; static bool _isInitiated = false;
static _init() { static _init() {
_channel.setMethodCallHandler((MethodCall call) async { _channel.setMethodCallHandler((MethodCall call) async {
String method = call.method; String method = call.method;
@ -14,7 +20,7 @@ class FlutterCastFramework {
debugPrint("Method call on flutter: $method $arguments"); debugPrint("Method call on flutter: $method $arguments");
switch (method) { switch (method) {
case "onCastStateChanged": case MethodNames.onCastStateChanged:
int castState = arguments; int castState = arguments;
castContext.state.value = CastState.values[castState]; castContext.state.value = CastState.values[castState];
break; break;
@ -26,9 +32,16 @@ class FlutterCastFramework {
}); });
} }
static CastContext _castContext;
// This must be the plugin entry point // This must be the plugin entry point
static CastContext get castContext { static CastContext get castContext {
if (!_isInitiated) _init(); if (!_isInitiated || _castContext == null) {
return CastContext.instance; _castContext = CastContext(_channel);
// TODO: find a better way to init the plugin
_isInitiated = true;
_init();
}
return _castContext;
} }
} }