Flutter與原生android通信

Flutter使用了一個靈活的系統,允許您調用特定平臺的API,Flutter平臺特定的API支持不依賴于代碼生成,而是依賴于靈活的消息傳遞的方式:

應用的Flutter部分通過平臺通道(platform channel)將消息發送到其應用程序的所在的宿主(iOS或Android)。

宿主監聽的平臺通道,并接收該消息。然后它會調用特定于該平臺的API(使用原生編程語言) - 并將響應發送回客戶端,即應用程序的Flutter部分。

平臺通道(platform channel)

既然Flutter是通過平臺通道(platform channel)實現Flutter和原生端的數據傳遞的。那么先看下官網的架構圖


圖一

由圖一可以看出,在客戶端,MethodChannel (API)可以發送與方法調用相對應的消息。 在宿主平臺上MethodChannel 在Android((API) 和 FlutterMethodChannel iOS (API) 可以接收方法調用并返回結果。

Flutter中定義了幾種不同的channel:


圖二

根據圖二可以看出幾種channel 之間的區別

BasicMessageChannel:

通過異步傳遞message與平臺進行通信

/// A named channel for communicating with platform plugins using asynchronous

/// message passing.

EventChannel:

通過流的方式與平臺進行通信

/// A named channel for communicating with platform plugins using event streams.

MethodChannel:

通過異步方法調用的方式與平臺進行通信

/// A named channel for communicating with platform plugins using asynchronous

/// method calls.

OptionalMethodChannel:

繼承于MethodChannel 忽略了平臺

/// A [MethodChannel] that ignores missing platform plugins.

暫時拿MethodChannel進行深入分析


圖三

根據MethodChannel構造方法知道,MethodChannel對象的創建需要兩個參數 name跟MethodCodec。

name是MethodChannel的唯一標識,可以理解成channel名字。

codec是用于方法調用和封裝結果的編解碼器,決定了我們能傳遞什么類型的數據。

標準的編解碼器有如下規則:


圖四

接下來先學習下MethodChannel的使用,邊用邊分析,Flutter和native間的通信,分為 Flutter主動發送 和 native主動發送 兩種情況。

Flutter主動發送給原生

官網例子:https://github.com/flutter/flutter/tree/master/examples/platform_channel

在dart文件中的實現:

```

static const MethodChannel methodChannel =

? MethodChannel('samples.flutter.io/battery');

? Future<void> _getBatteryLevel() async {

? ? String batteryLevel;

? ? try {

? ? ? final int result = await methodChannel.invokeMethod('getBatteryLevel');

? ? ? batteryLevel = 'Battery level: $result%.';

? ? } on PlatformException {

? ? ? batteryLevel = 'Failed to get battery level.';

? ? }

? ? setState(() {

? ? ? _batteryLevel = batteryLevel;

? ? });

? }

```

```

package com.example.platformchannel;

import android.content.BroadcastReceiver;

import android.content.Context;

import android.content.ContextWrapper;

import android.content.Intent;

import android.content.IntentFilter;

import android.os.BatteryManager;

import android.os.Build.VERSION;

import android.os.Build.VERSION_CODES;

import android.os.Bundle;

import io.flutter.app.FlutterActivity;

import io.flutter.plugin.common.EventChannel;

import io.flutter.plugin.common.EventChannel.EventSink;

import io.flutter.plugin.common.EventChannel.StreamHandler;

import io.flutter.plugin.common.MethodChannel;

import io.flutter.plugin.common.MethodChannel.MethodCallHandler;

import io.flutter.plugin.common.MethodChannel.Result;

import io.flutter.plugin.common.MethodCall;

import io.flutter.plugins.GeneratedPluginRegistrant;

public class MainActivity extends FlutterActivity {

? private static final String BATTERY_CHANNEL = "samples.flutter.io/battery";

? private static final String CHARGING_CHANNEL = "samples.flutter.io/charging";

? @Override

? public void onCreate(Bundle savedInstanceState) {

? ? super.onCreate(savedInstanceState);

? ? GeneratedPluginRegistrant.registerWith(this);

? ? new MethodChannel(getFlutterView(), BATTERY_CHANNEL).setMethodCallHandler(

? ? ? ? new MethodCallHandler() {

? ? ? ? ? @Override

? ? ? ? ? public void onMethodCall(MethodCall call, Result result) {

? ? ? ? ? ? if (call.method.equals("getBatteryLevel")) {

? ? ? ? ? ? ? int batteryLevel = getBatteryLevel();

? ? ? ? ? ? ? if (batteryLevel != -1) {

? ? ? ? ? ? ? ? result.success(batteryLevel);

? ? ? ? ? ? ? } else {

? ? ? ? ? ? ? ? result.error("UNAVAILABLE", "Battery level not available.", null);

? ? ? ? ? ? ? }

? ? ? ? ? ? } else {

? ? ? ? ? ? ? result.notImplemented();

? ? ? ? ? ? }

? ? ? ? ? }

? ? ? ? }

? ? );

? }

? private int getBatteryLevel() {

? ? if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {

? ? ? BatteryManager batteryManager = (BatteryManager) getSystemService(BATTERY_SERVICE);

? ? ? return batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);

? ? } else {

? ? ? Intent intent = new ContextWrapper(getApplicationContext()).

? ? ? ? ? registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));

? ? ? return (intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) * 100) /

? ? ? ? ? intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);

? ? }

? }

}

```

以上就是從Flutter端主動發起與native端的通信,dart通過await methodChannel.invokeMethod(‘getBatteryLevel’)發送消息,native端通過MethodChannel中MethodCallHandler的onMethodCall進行接收flutter的通信,并通過result.success進行回傳信息。

有幾點需要注意

dart中methodChannel 聲明的時候的 name要保證與native端的一致,且唯一。

dart中methodChannel.invokeMethod(‘getBatteryLevel’),在native端要進行判斷,只有方法名匹配才給予響應, if (call.method.equals(“getBatteryLevel”))。

這里flutter通過 invokeMethod與native進行通信


圖五

查看invokeMethod()方法, method為 MethodCall的標識, arguments為參數,注意這里的參數必須要遵守上面的規則(默認情況下不能直接傳自定義類,但是我們可以將其轉為Json之后再傳遞,也可以去改造 MethodCode,以此進行復雜數據結構的傳遞)。

注:可以看到,其是一個 async標記的方法,返回值為Future。那么我們在接受這個方法的返回值的時候,就必須要使用 await進行修飾。要調用使用 await,必須在有 async標記的函數中運行。具體調用和使用的方式可以看官網的例子。在這我們先繼續深入。

BinaryMessages.send()


圖6

接下來_sendPlatformMessage()——window.sendPlatformMessage()


圖七
圖8

最終調用native方法與原生進行通信的。

在flutter engine中查看源碼


圖9


圖10

看最關鍵的方法: dart_state->window()->client()->HandlePlatformMessage()


圖11


圖12

一步一步跟下來 到了 這里g_handle_platform_message_method

圖13


圖14

接下來就是 在FlutterJNI 與 FlutterNativeView 之間進行綁定了

圖16


圖17

這里就可以通過JNI調用Android 端了。

原生主動發送給Flutter

```

/**

? ? * native data to? dart

? ? */

? ? private void native2Dart() {

? ? ? ? /**

? ? ? ? * 數據流的通信(event streams)

? ? ? ? */

? ? ? ? EventChannel eventChannel = new EventChannel(getFlutterView(), EVENT_CHANNEL);

? ? ? ? EventChannel.StreamHandler streamHandler = new EventChannel.StreamHandler() {

? ? ? ? ? ? @Override

? ? ? ? ? ? public void onListen(Object arguments, EventSink eventSink) {

? ? ? ? ? ? ? ? Log.e("plateform_channel", "arguments: " + arguments.toString());

? ? ? ? ? ? ? ? eventSink.success(data);

? ? ? ? ? ? }

? ? ? ? ? ? @Override

? ? ? ? ? ? public void onCancel(Object arguments) {

? ? ? ? ? ? ? ? Log.e("plateform_channel", "arguments: " + arguments.toString());

? ? ? ? ? ? }

? ? ? ? };

? ? ? ? eventChannel.setStreamHandler(streamHandler);

? ? }

```

Flutter端:

```

static const EventChannel eventChannel =

? EventChannel(FlutterChannel.CHANNEL_RECEIVE_DATA);

? @override

? void initState() {

? ? super.initState();

? ? eventChannel.receiveBroadcastStream(['arg1', 'arg2']).listen(_onEvent,

? ? ? ? onError: _onError);

? }

? void _onEvent(Object event) {

? ? var animal = json.decode(event);

? ? print(AnimalsRoot.fromJson(animal).animals.cat.name);

? ? setState(() {

? ? ? _receive_data = '$event';

? ? });

? }

? void _onError(Object error) {

? ? setState(() {

? ? ? _receive_data = 'Receive? failed';

? ? });

? }

```

用圖表示其中的關聯就是


圖18
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。