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
import android.util.Log
import androidx.mediarouter.app.MediaRouteChooserDialog
import androidx.mediarouter.app.MediaRouteControllerDialog
import com.google.android.gms.cast.framework.CastContext
import io.flutter.plugin.common.MethodCall
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.PluginRegistry.Registrar
class FlutterCastFrameworkPlugin(registrar: Registrar, private val channel: MethodChannel): MethodCallHandler {
companion object {
@JvmStatic
fun registerWith(registrar: Registrar) {
val channel = MethodChannel(registrar.messenger(), "flutter_cast_framework")
channel.setMethodCallHandler(FlutterCastFrameworkPlugin(registrar, channel))
}
}
class FlutterCastFrameworkPlugin(private val registrar: Registrar, private val channel: MethodChannel) : MethodCallHandler {
companion object {
const val TAG = "AndroidCastPlugin"
init {
CastContext.getSharedInstance(registrar.activeContext()).addCastStateListener { i ->
Log.d("Android", "Method call on flutter: $i")
channel.invokeMethod("onCastStateChanged", i)
}
}
// @StyleRes
// var customStyleResId: Int? = null
// private val themeResId get() = customStyleResId ?: R.style.Theme_AppCompat_DayNight_Dialog_Alert
override fun onMethodCall(call: MethodCall, result: Result) {
if (call.method == "getPlatformVersion") {
result.success("Android ${android.os.Build.VERSION.RELEASE}")
} else {
result.notImplemented()
@JvmStatic
fun registerWith(registrar: Registrar) {
val channel = MethodChannel(registrar.messenger(), "flutter_cast_framework")
channel.setMethodCallHandler(FlutterCastFrameworkPlugin(registrar, channel))
}
}
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 {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
testImplementation 'junit:junit:4.12'
implementation 'androidx.appcompat:appcompat:1.1.0'
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
}

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<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
Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>

View file

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

View file

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

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_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 _init() {
_channel.setMethodCallHandler((MethodCall call) async {
String method = call.method;
@ -14,7 +20,7 @@ class FlutterCastFramework {
debugPrint("Method call on flutter: $method $arguments");
switch (method) {
case "onCastStateChanged":
case MethodNames.onCastStateChanged:
int castState = arguments;
castContext.state.value = CastState.values[castState];
break;
@ -26,9 +32,16 @@ class FlutterCastFramework {
});
}
static CastContext _castContext;
// This must be the plugin entry point
static CastContext get castContext {
if (!_isInitiated) _init();
return CastContext.instance;
if (!_isInitiated || _castContext == null) {
_castContext = CastContext(_channel);
// TODO: find a better way to init the plugin
_isInitiated = true;
_init();
}
return _castContext;
}
}