Flutter與Android 互相通信(Kotlin版)

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章