1. 程式人生 > 其它 >Flutter 和Android 的互動之 MethodChannel

Flutter 和Android 的互動之 MethodChannel

技術標籤:Flutter 原生互動MethodChannel

Flutter 和 Android 的互動網上的博文非常多,包括Flutter中文網上面關於MethodChannel 的內容,都已經過時了。比如Fluter 中文網上面寫道的Android客戶端整合如下:


import io.flutter.app.FlutterActivity;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.
MethodChannel.MethodCallHandler; import io.flutter.plugin.common.MethodChannel.Result; public class MainActivity extends FlutterActivity { private static final String CHANNEL = "samples.flutter.io/battery"; @Override public void onCreate(Bundle savedInstanceState) { super
.onCreate(savedInstanceState); new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler( new MethodCallHandler() { @Override public void onMethodCall(MethodCall call, Result result) { // TODO } }); } }

上面整合的是 io.flutter.app.FlutterActivity,通過 getFlutterView() 和 字串來 構造 MethodChannel ,然後設定來自於 Flutter 呼叫的監聽。

現在我們整合新的 Flutter SDK ,繼承的Activity是 io.flutter.embedding.android.FlutterActivity,此FlutterActivity已經不存在 getFlutterView() 方法了,所以Android 和 Flutter的互動也要改變。

整合的流程如下:

1.Android 客戶端的程式碼如下:

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

import androidx.annotation.Nullable;

import io.flutter.embedding.android.FlutterActivity;
import io.flutter.plugin.common.MethodChannel;

public class FlutterAppActivity extends FlutterActivity {

    private final static String CHANNEL_NATIVE = "com.zhujiangtao.flutter";
    private MethodChannel mMethodChannel;

    public static void enter(Context context) {
        Intent intent = new NewEngineIntentBuilder(FlutterAppActivity.class)
                    .initialRoute("zhujiangtao?msg=test&id=10010")
                    .build(context);
        context.startActivity(intent);
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 初始化 MethodChannel
        mMethodChannel = new MethodChannel(getFlutterEngine().getDartExecutor().getBinaryMessenger(), CHANNEL_NATIVE);
        // Flutter 呼叫 android 的方法會執行到此回撥
        mMethodChannel.setMethodCallHandler((call, result) -> {
            Log.e("xxxxx", "method = " + call.method);
            switch (call.method) {
                case "callNative":
                    Toast.makeText(FlutterAppActivity.this, call.argument("arg1"), Toast.LENGTH_LONG).show();
                    callFlutter();
                    // 將結果回撥給 Flutter 
                    result.success("我是來自Native的回撥");
                    break;
            }
        });

    }

    private void callFlutter() {
        // Android 端呼叫 Flutter 的方法
        mMethodChannel.invokeMethod("callFlutter", "name=zhujiangtao", new MethodChannel.Result() {
            @Override
            public void success(@Nullable Object result) { // Flutter 回撥過來的結果
                if (result != null) {
                    Toast.makeText(FlutterAppActivity.this, result.toString(), Toast.LENGTH_LONG).show();
                }
            }

            @Override
            public void error(String errorCode, @Nullable String errorMessage, @Nullable Object errorDetails) {

            }

            @Override
            public void notImplemented() {

            }
        });
    }
}

裡面清晰的註釋了,Android 是如何呼叫 Flutter 和 Flutter 是怎麼呼叫Android的。

2. AndroidManifest.xml 中註冊且處理跳轉到Flutter頁面黑屏問題


<!--就是之前寫的Activity-->
 <activity android:name=".ui.FlutterAppActivity"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">

            <meta-data
                android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
                android:value="true" />
            <!--解決android進入Flutter的黑屏問題-->
            <meta-data
                android:name="io.flutter.embedding.android.SplashScreenDrawable"
                android:resource="@drawable/flutter_splash_bg" />

        </activity>

3. Flutter 端的程式碼呼叫原生方法和原生呼叫Flutter的回撥


import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:my_flutter/pages/list_view.dart';

class MyMethodChannel extends StatefulWidget{

  @override
  State<StatefulWidget> createState() {
    return MyMethodState();
  }

}

class MyMethodState extends State<MyMethodChannel>{
  String _content;
  // 這裡面的 “com.zhujiangtao.flutter”要和 Java 程式碼中 初始化 MethodChannel的值保持一致
  static MethodChannel _methodChannel = MethodChannel('com.zhujiangtao.flutter');
  
  @override
  void initState() {
    _methodChannel.setMethodCallHandler(_methodChannelHandler);
    super.initState();
  }
  
  @override
  Widget build(BuildContext context) {
   return Scaffold(
     appBar: AppBar(title: Text("TestMethodChannel"),),
     body: Center(
       child: Column(
         children: <Widget>[
           Text('$_content'),
           RaisedButton(
             onPressed: callNative,
             child: Text("callNative"),
           ),
           
           RaisedButton(
             onPressed: (){
             Navigator.push(context, MaterialPageRoute(builder: (context) => TestListView()));
           },
             child: Text('ListView'),
           ),
         ],
       ),
     ),
   );
  }

  /// Flutter 呼叫原生
  Future<void> callNative() async {
    print("----------------callNative--------------------");
   var res = await _methodChannel.invokeMethod("callNative", {"arg1": "I am from Flutter"});
    //Android收到呼叫之後返回的資料
    setState(() {
      _content = res;
    });
  }

  /// 原生 呼叫 Flutter的結果回撥
  Future<String> _methodChannelHandler(MethodCall call) async{
    String result = "";
    print("---------------_methodChannelHandler------------------------ method = ${call.method}");
    switch(call.method){
      case "callFlutter":
        setState(() {
          _content = call.arguments.toString();
        });
        result = "Flutter 收到 Android發來的訊息";
        break;
    }
    return result;
  }
  
}

裡面也是 初始化 MethodChannel ,然後邏輯和原生的差不多;

invokeMethod :原生和Flutter都是呼叫此方法來和對方通訊;

setMethodCallHandler:都是結果的回撥。

以上就是 Flutter 和 原生 的互動過程。

以後文章會同步到個人公眾號,歡迎關注交流

在這裡插入圖片描述