Flutter与原生通信的一切

简介

Flutter与原生之间的通信依赖灵活的消息传递方式:

  • 应用的Flutter部分通过平台通道(platform channel)将消息发送到其应用程序的所在的宿主(iOS或Android)应用(原生应用)。

  • 宿主监听平台通道,并接收该消息。然后它会调用该平台的API,并将响应发送回客户端,即应用程序的Flutter部分。

  1. MethodChannel  // Flutter与原生方法相互调用,用于方法掉用

  2. BasicMessageChannel // Flutter与原生相互发送消息,用于数据传递

  3. EventChannel // 原生发送消息,Flutter接收,用于数据流通信

640?wx_fmt=other

可以传递的数据结构
DartAndroidiOS
nullnullnil(NSNull when nested)
boolJava.lang.BooleanNSNumber numberWithBool:
intJava.lang.IntegerNSNumber numberWithInt:
int, if 32 bits not enoughJava.lang.LongNSNumber numberWithLong:
int, if 64 bits not enoughJava.lang.BigIntegerFlutterStandardBigInteger
doubleJava.lang.DoubleNSNumber numberWithDouble
Stringjava.lang.StringNSString
Unit8Listbyte[]FlutterStandardTypedData typedDataWithBytes:
Int32Listint[]FlutterStandardTypedData typedDataWithInt32:
Int64Listlong[]FlutterStandardTypedData typedDataWithInt64:
Float64Listdouble[]FlutterStandardTypedData typedDataWithFloat64:
ListJava.util.ArrayListNSArray
MapJava.util.HashMapNSDictionary
MethodChannel(互相调用方法)

Android调用Flutter方法:

Android:

  1. 初始化MethodChannel

//初始化,传递1. flutterView(MainActivity中getFlutter获取),2. name常量,Flutter中使用同名常量	
MethodChannel methodChannel = new MethodChannel(flutterView, “testflutter”);
  1. 调用Flutter方法

 
 

通过MethodChannel调用invokeMethod("方法名","传递参数",[Flutter返回参数回调,非必须]);

Flutter:

  1. 初始化MethodChannel

static const methodChannel = const MethodChannel('testflutter');
复制代码
  1. 添加处理方法到MethodChannel

methodChannel.setMethodCallHandler(_addNativeMethod);
  1. 处理android调用的方法,根据方法名

 
 

Flutter调用Android方法:

Android:

  1. 初始化MethodChannel,并添加自定义plugin

MethodChannel methodChannel = new MethodChannel(flutterView, METHOD_CHANNEL);	
methodChannel.setMethodCallHandler(plugin);
  1. 自定义的plugin实现MethodChannel.MethodCallHandler接口的onMethodCall方法

@Override	
public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {	
  // Flutter调用Native的方法	
  if (methodCall.method.equals("getBatteryLevel")) {	
    int batteryLevel = getBatteryLevel();	
    if (batteryLevel != -1) {	
      result.success(batteryLevel);	
    } else {	
      result.error("UNAVALIABLE", "battery level unavaliable", null);	
    }	
  } else {	
    result.notImplemented();	
  }	
}	
//在onMethodCall中监听Flutter调用什么名字的方法(此处getBatterLevel),通过result返回方法的执行结果。

Flutter:

  1. 初始化MethodChannel

static const methodChannel = const MethodChannel('testflutter');

复制代码
  1. 调用Android的方法,接收返回数据

//方法通道的方法是异步的	
Future<Null> _getBatteryLevel() async {	
  String batteryLevel;	
  try {	
    final int result = await methodChannel.invokeMethod('getBatteryLevel');	
    batteryLevel = 'Battery level $result .';	
  } on PlatformException catch (e) {	
    batteryLevel = 'Battery level unknown ${e.message}';	
  }	
  setState(() {	
    _batteryLevel = batteryLevel;	
  });	
}


BasicMessageChannel(互相发送消息)

Android给Flutter发消息:

Android:

  1. 初始化BasicMethodChannel

	
BasicMessageChannel messageChannel =	
 new BasicMessageChannel<>(flutterView, 	
"messageChannel", StandardMessageCodec.INSTANCE);	
	
复制代码
  1. 调用发送消息的方法

private void sendMessageToFlutter() {	
  if (this.mBasicMessageChannel != null) {	
    this.mBasicMessageChannel.send("Message From Native");	
  }	
}	

Flutter:

  1. 初始化BasicMessageChannel

static const basicMessageChannel = BasicMessageChannel('messageChannel', StandardMessageCodec());
复制代码
  1. 添加接收信息处理方法

void _listenMessageFromNative() {	
  basicMessageChannel.setMessageHandler(_receiveMessageFromNative);	
}


  1. 处理接收的数据

//Flutter接收Native发来的消息	
Future<dynamic> _receiveMessageFromNative(Object result) async {	
  setState(() {	
    _messageFromNative = result.toString();	
  });	
}	

Flutter给Android发消息:

Android:

  1. 初始化BasicMessageChannel并添加plugin给handler

BasicMessageChannel messageChannel = new BasicMessageChannel<>(flutterView, "messageChannel", StandardMessageCodec.INSTANCE);	
messageChannel.setMessageHandler(plugin);
  1. plugin实现BasicMessageChannel.MessageHandler接口的onMessage方法,处理接收到的信息

@Override	
public void onMessage(Object o, BasicMessageChannel.Reply reply) {	
  Toast.makeText(mContext, o.toString(), Toast.LENGTH_LONG).show();	
  reply.reply(o.toString()+" back from native");	
}	
//reply返回数据给Flutter


Flutter:

  1. 初始化BasicMessageChannel

static const basicMessageChannel = 	
BasicMessageChannel('messageChannel', StandardMessageCodec());

  1. 发送消息给Android并接收返回数据

 
 
EventChannel(原生发送消息,Flutter接收)

Android:

  1. 初始化EventChannel并添加plugin给handler

EventChannel eventChannel = new EventChannel(flutterView, EVENT_CHANNEL);	
eventChannel.setStreamHandler(plugin);


  1. plugin实现EventChannel.StreamHandler接口及onListen、onCancel方法

  2. 在onListen中通过EventChannel.EventShink的实例发消息给Flutter

@Override	
public void onListen(Object o, EventChannel.EventSink eventSink) {	
  BroadcastReceiver chargingBroadcastReceiver = createChargingBroadcaseReceiver(eventSink);	
  mContext.registerReceiver(chargingBroadcastReceiver,new IntentFilter(Intent.ACTION_BATTERY_CHANGED));	
}	
@Override	
public void onCancel(Object o) {	
}	
private BroadcastReceiver createChargingBroadcaseReceiver(EventChannel.EventSink eventSink) {	
  return new BroadcastReceiver() {	
    @Override	
    public void onReceive(Context context, Intent intent) {	
      int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);	
      if (status == BatteryManager.BATTERY_STATUS_UNKNOWN) {	
        eventSink.error("UNAVALIABLE", "charging status is unavailable", null);	
      } else {	
        boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING;	
        eventSink.success(isCharging ? "charging" : "disCharging");	
      }	
    }	
  };	
}


Flutter:

  1. 初始化EventChannel

static const _eventChannel = const EventChannel('charging');
  1. 添加接收数据方法

void listenNativeEvent() {	
  _eventChannel.receiveBroadcastStream().listen(_onEvent, onError: _onError);	
}	
//接收返回的数据	
void _onEvent(Object object) {	
  String s = "Battery is ${object == 'charging' ? '' : 'dis'}Charging";	
  setState(() {	
    _batteryStatus = s;	
  });	
}


桥接View给Flutter使用

Android:

  1. 自定义View,继承自PlatformView

 
 
  1. 实现PlatformViewFactory

public class TextViewFactory extends PlatformViewFactory {	
  private MessageCodec<Object> messageCodec;	
  public TextViewFactory(MessageCodec<Object> createArgsCodec) {	
    super(createArgsCodec);	
    this.messageCodec = createArgsCodec;	
  }	
  	
  @Override	
  public PlatformView create(Context context, int i, Object o) {	
    return new MyTextview(context, messageCodec, i, (Map<String, Object>) o);	
  }	
}

  1. 注册View给Flutter使用

registrar.platformViewRegistry().registerViewFactory("TextView", new TextViewFactory(new StandardMessageCodec()));	
//起名叫TextView,给Flutter用做viewType

Flutter:

  1. 使用桥接的View

AndroidView(	
  viewType: 'TextView',	
  creationParams: {'text': 'TTTeeeXXXttt'},	
  creationParamsCodec: new StandardMessageCodec(),	
),//其中creationParams,creationParamsCodec必须同时存在或不存在

以上,正文结束;

官方还有一些其他建议

发布pub使用:
  1. Hosted packages(发布到pub.dartlang.org)

    $flutter packages pub publish --dry-run
    $flutter packages pub publish
    复制代码

    在yaml文件和其他dependencies一样使用。

  2. Git packages(远端)

    代码上传到Git,并打一个tag

    yaml文件引用

    dependencies:
    	flutter_remote_package:
    		git:
    			url: git@gitlab....
    			ref: 0.0.1 //可以是commit、branch、tag
    
    
  3. 本地

    在Flutter App根目录下创建plugins文件夹,把插件移动到plugins下。

    
    

    以上限于在创建工程的时候,使用的是plugins创建的,有时候会在自己的Android或iOS工程内部开发,就不这么方便分离发布了。

  4. dependencies:flutter_plugin_batterylevel:	
        path: plugins/flutter_plugin_batterylevel
  5. dependencies:	
      flutter_plugin_batterylevel:	
        path: plugins/flutter_plugin_batterylevel

有时候需要到UI thread执行channelMethod,在Android上需要post一个Runnable到Android UI线程。

new Handler(Looper.getMainLooper()).post(new Runnable() {	
  @Override	
  public void run(){	
    // call the desired channel message here.	
  }	
})
  1. 所谓的“传View”的本质是传递纹理ID,我们只需要明白Flutter是通过Presentation实现了外接纹理,在创建Presentation时,传入FlutterView对应的Context和创建出来的一个虚拟显示屏对象,使得Flutter可以直接通过ID找到并使用Native创建出来的纹理数据。

  2. 事件处理,从Native传递到Flutter这一阶段Flutter按照自己的规则处理事件,如果AndroidView获取到了事件,事件会被封装成相应的Native端的事件通过方法通道传回Native,Native再处理事件。

    对于可能出现的滑动时间冲突,可以参考官方注释:

    
    
    
  3. /// For example, with the following setup vertical drags will not be dispatched to the Android view as the vertical drag gesture is claimed by the parent [GestureDetector].	
    ///	
    /// GestureDetector(	
    ///   onVerticalDragStart: (DragStartDetails d) {},	
    ///   child: AndroidView(	
    ///     viewType: 'webview',	
    ///     gestureRecognizers: <OneSequenceGestureRecognizer>[],	
    ///   ),	
    /// )	
    ///	
    /// To get the [AndroidView] to claim the vertical drag gestures we can pass a vertical drag gesture recognizer in [gestureRecognizers] e.g:	
    ///	
    /// GestureDetector(	
    ///   onVerticalDragStart: (DragStartDetails d) {},	
    ///   child: SizedBox(	
    ///     width: 200.0,	
    ///     height: 100.0,	
    ///     child: AndroidView(	
    ///       viewType: 'webview',	
    ///       gestureRecognizers: <OneSequenceGestureRecognizer>[new VerticalDragGestureRecognizer()],	
    ///     ),	
    ///   ),	
    /// )

https://github.com/damengzai/flutter-test

                        喜欢 就关注吧,欢迎投稿!

640?wx_fmt=jpeg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Flutter 是一个跨平台的移动应用开发框架,它可以让开发者使用一套代码同时开发 iOS 和 Android 应用。而在某些情况下,我们可能需要集成原生 SDK 实现一些功能。本文将介绍如何在 Flutter 中集成原生 SDK。 首先,我们需要在 Flutter 中创建一个平台通道(Platform Channel)来实现 Flutter原生代码的通信。 1.创建一个平台通道Flutter 中,平台通道定义了 Dart 代码和原生代码之间的通信方式。我们可以通过 MethodChannel、EventChannel 或 BasicMessageChannel 等方式来创建平台通道。 以 MethodChannel 为例,我们可以在 Flutter 中创建一个 MethodChannel: ``` final MethodChannel platformChannel = MethodChannel('com.example.platform_channel'); ``` 这里的 com.example.platform_channel 是一个字符串,用来标识 Flutter原生代码之间的通道。 2.在原生代码中实现方法 在原生代码中,我们需要实现与 Flutter 中定义的 MethodChannel 对应的方法。例如,我们可以在 Android 中创建一个名为 MyPlugin 的类来实现这个方法: ``` public class MyPlugin implements MethodCallHandler { private static final String CHANNEL = "com.example.platform_channel"; public static void registerWith(Registrar registrar) { final MethodChannel channel = new MethodChannel(registrar.messenger(), CHANNEL); channel.setMethodCallHandler(new MyPlugin()); } @Override public void onMethodCall(MethodCall call, Result result) { if (call.method.equals("getDeviceInfo")) { String deviceInfo = getDeviceInfo(); result.success(deviceInfo); } else { result.notImplemented(); } } private String getDeviceInfo() { // 获取设备信息的代码 return "device info"; } } ``` 这里的 getDeviceInfo 方法用来获取设备信息,并将结果返回给 Flutter。 3.在 Flutter 中调用方法 在 Flutter 中,我们可以通过 MethodChannel 来调用 MyPlugin 中实现的方法: ``` String deviceInfo = await platformChannel.invokeMethod('getDeviceInfo'); ``` 这里的 invokeMethod 方法用来调用 getDeviceInfo 方法,并将结果返回给 Flutter。 以上就是在 Flutter 中集成原生 SDK 的基本流程。在实际使用中,我们还需要注意一些细节,例如方法参数和返回值的类型转换等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值