Flutter与安卓交互

一般的Flutter与原生平台的通信方式有3种:

  1. MethodChannel:主要用于Flutter端和原生端之间的方法调用 【常用】
  2. EventChannel:用于数据流的持续通信,收到消息后无法立即回复本次通信消息,通常用在原生平台主动向Flutter发送消息的场
  3. BasicMessageChannel:用于传递字符串或半结构体的数据

平台端与Flutter端之间的数据类型映射表

DartJavaKotlinOCSwift
nullnullnullnil (NSNull when nested)nil
booljava.lang.BooleanBooleanNSNumber numberWithBool:NSNumber(value: Bool)
intjava.lang.IntegerIntNSNumber numberWithInt:NSNumber(value: Int32)
int, if 32 bits not enoughjava.lang.LongLongNSNumber numberWithLong:NSNumber(value: Int)
doublejava.lang.DoubleDoubleNSNumber numberWithDouble:NSNumber(value: Double)
Stringjava.lang.StringStringNSStringString
Uint8Listbyte[]ByteArrayFlutterStandardTypedData typedDataWithBytes:FlutterStandardTypedData(bytes: Data)
Int32Listint[]IntArrayFlutterStandardTypedData typedDataWithInt32:FlutterStandardTypedData(int32: Data)
Int64Listlong[]LongArrayFlutterStandardTypedData typedDataWithInt64:FlutterStandardTypedData(int64: Data)
Float64Listdouble[]DoubleArrayFlutterStandardTypedData typedDataWithFloat64:FlutterStandardTypedData(float64: Data)
Listjava.util.ArrayListListNSArrayArray
Mapjava.util.HashMapHashMapNSDictionaryDictionary

MethodChannel 示例代码

Flutter端代码:

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class NativeCall{

  static const _channelName  = 'xyz.bczl/test';
  // 创建通道,并设置名称作为唯一标识
  static const  _platform = const MethodChannel(_channelName);

  static Future<void> sdkVersion() async {
    try {
      final int result = await _platform.invokeMethod('getSDKVersion');
      debugPrint('sdkVersion=$result');
    } on PlatformException catch (e) {
      debugPrint("Failed to get sdkVersion: '${e.message}'.");
    }
  }

  static Future<void> toast(String text) async {
    try {
      await _platform.invokeMethod('toast',{"text":text});
    } on PlatformException catch (e) {
      debugPrint(e.message);
    }
  }
}

Android端代码:

public class MainActivity extends FlutterActivity {
    private static final String CHANNEL = "xyz.bczl/test";

    @Override
    public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
        super.configureFlutterEngine(flutterEngine);
        new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
            .setMethodCallHandler(new MethodChannel.MethodCallHandler() {
                 @Override
                 public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
                     if(call.method.equals("getSDKVersion")){
                         // 返回SDK版本号
                         result.success(Build.VERSION.SDK_INT);
                     } else if(call.method.equals("toast")){
                         String text = call.argument("text");
                         // 弹出Toast
                         Toast.makeText(MainActivity.this,text,Toast.LENGTH_SHORT).show();
                         result.success(null);
                     }
                 }
            });
    }
}

EventChannel 示例代码

Flutter端,NativeCall中添加如下代码

static const _eventChannel = const EventChannel("xyz.bczl/event");

  StreamSubscription _subscription;
  void onEvent(){
    _subscription = _eventChannel
        .receiveBroadcastStream()
        .listen(
            (event) {
              debugPrint("from native event:$event");
            },
            onError: (e){
              PlatformException exception = e;
              debugPrint(exception.message);
            });
  }

  void cancel(){
    _subscription.cancel();
  }

Android端代码:

public class MainActivity extends FlutterActivity {
    EventChannel.EventSink mEvents;

    @Override
    public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
        super.configureFlutterEngine(flutterEngine);

        // 创建 EventChannel
        new EventChannel(flutterEngine.getDartExecutor().getBinaryMessenger(),"xyz.bczl/event")
        .setStreamHandler(new EventChannel.StreamHandler() {
            @Override
            public void onListen(Object arguments, EventChannel.EventSink events) {
                mEvents = events;
            }

            @Override
            public void onCancel(Object arguments) {}
        });
    }


    @Override
    protected void onPause() {
        super.onPause();
        if (mEvents != null) mEvents.success("onPause");
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (mEvents != null) mEvents.success("onResume");
    }
}

小结:

  • 应在原生平台的主线程中调用通道相关的方法
  • 编写调试原生混合代码是不能热更新的,请确保App重新编译、打包、安装
  • Flutter 1.12 版本后官方更新了插件API,但是旧的接口目前依旧兼容。注意,新的版本中,是通过实现FlutterActivity的configureFlutterEngine方法创建通道,旧版处理如下:
public class MainActivity extends FlutterActivity {
    private static final String CHANNEL = "xyz.bczl/test";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(
                new MethodCallHandler() {
                    @Override
                    public void onMethodCall(MethodCall call, Result result) {}
                });
    }
}
THE END
喜欢就支持一下吧
点赞5赞赏 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容