Android與Flutter之間的通信共有四種實現方式。
1.由於在初始化flutter頁面時會傳遞一個字符串——route,因此我們就可以拿route來做文章,傳遞自己想要傳遞的數據。該種方式僅支持單向數據傳遞且數據類型只能爲字符串,無返回值。
2.通過EventChannel來實現,EventChannel僅支持數據單向傳遞,無返回值。
3.通過MethodChannel來實現,MethodChannel支持數據雙向傳遞,有返回值。
4.通過BasicMessageChannel來實現,BasicMessageChannel支持數據雙向傳遞,有返回值。
本文采用的是MethodChannel方式,如要看其他三種請直接移動到文章底部
Flutter 調用原生
1 首先我們要在Android中定義插件
class FlutterPluginTestNewPlugin(
private val activity: Activity) : MethodCallHandler {
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
if (call.method == "download") {
Log.e("onMethodCall", call.method)
result.success("Android")
download()
} else if(call.method=="play") {
val intent = Intent(activity, DownloadPlayActivity::class.java)
intent.putExtra("proxy_url", MainActivity.item.proxyUrl)
intent.putExtra("origin_url", MainActivity.item.url)
activity.startActivity(intent)
}else{
result.notImplemented()
}
}
companion object {
private var channel: MethodChannel? = null
/// 保留舊版本的兼容
fun registerWith(registry: PluginRegistry) {
val registrar: PluginRegistry.Registrar = registry.registrarFor("flutter_plugin_test_new")
channel = MethodChannel(registrar.messenger(), "flutter_plugin_test_new")
channel!!.setMethodCallHandler(FlutterPluginTestNewPlugin(registrar.activity()))
}
}
private fun download(){
if (MainActivity.item.isRunningTask) {
LogUtils.d("jeffmony pause downloading.")
VideoDownloadManager.getInstance().pauseDownloadTask(MainActivity.item)
} else if (MainActivity.item.isSlientTask) {
LogUtils.d("jeffmony start downloading.")
VideoDownloadManager.getInstance().startDownload(MainActivity.item)
}
}
}
我定義了兩個flutter調用Android的方法 download ,play
2 Android 插件註冊
class MainActivity: FlutterActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
GeneratedPluginRegistrant.registerWith(this@MainActivity)
FlutterPluginTestNewPlugin.registerWith(this@MainActivity)
}
3 Flutter 調用原生插件
const platform = const MethodChannel('flutter_plugin_test_new');
final String result = await platform.invokeMethod('download');
需要注意的是 方法名要一致,(方法支持帶參數),要有共同的Channel flutter_plugin_test_new (自己定義代表一個事件的tag)
簡單提一下帶參數的調用:
Flutter端發起
Map<String, Object> map = {"url": “123456”};
platform.invokeMethod('download',map);
Android端接收
val url: String? = call.argument("url")
原生調用 Flutter
1Android 定義插件
class MyFlutterEventPlugin implements EventChannel.StreamHandler {
public static EventChannel.EventSink eventSink;
public static MyFlutterEventPlugin registerWith(PluginRegistry registry) {
String CHANNEL = "event_plugin";
PluginRegistry.Registrar registrar = registry.registrarFor(CHANNEL);
EventChannel eventChannel = new EventChannel(registrar.messenger(), CHANNEL);
MyFlutterEventPlugin myFlutterEventPlugin = new MyFlutterEventPlugin();
eventChannel.setStreamHandler(myFlutterEventPlugin);
return myFlutterEventPlugin;
}
@Override
public void onListen(Object o, EventChannel.EventSink eventSink) {
this.eventSink = eventSink;
}
@Override
public void onCancel(Object o) {
}
}
2.Android 插件註冊 & 調用
public class MainActivity extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
MyFlutterEventPlugin.registerWith(this)
MyFlutterEventPlugin eventPlugin = MyFlutterEventPlugin.registerWith(this);
// 成功的回調
MyFlutterEventPlugin.eventSink!!.success(“6666”)
//失敗回調
// MyFlutterEventPlugin.eventSink!!.error("計時器異常", "計時器異常", e.message)
}
}
3.Flutter 註冊監聽器接收來自原生的消息
const myEventPlugin = const EventChannel('event_plugin');
@override
void initState() {
super.initState();
//設置監聽
myEventPlugin.receiveBroadcastStream().listen(_onEvent, onError: _onError);
}
void _onEvent(Object event) {
// 這裏的event事Object類型 可以接收各種類型的參數
print("onEvent: $event");
}
void _onError(Object error) {
print("onError: $error");
}
溫馨提示:
本文涉及到Flutter中Android插件的開發以及引用,不熟悉的同學請前往https://www.jianshu.com/p/4a9b6bf43b38學習如何構建插件,再看本文會得心應手。
本文基於Flutter 1.12之前,1.12之後插件寫法可以沿用這種(已兼容),也可以進行升級,升級注意事項請前往https://blog.csdn.net/ZuoYueLiang/article/details/103706627
Flutter與原生交互總結
https://www.jianshu.com/p/f35da4195df9