所谓“平台特定”或“特定平台”,平台指的就是原生Android或IOS,本文主要讲原生和Flutter之间如何通信、如何进行功能互调。

Flutter使用了一个灵活的系统,允许您调用特定平台的API,无论在Android上的Java或Kotlin代码中,还是iOS上的ObjectiveC或Swift代码中均可用。

Flutter平台特定的API支持不依赖于代码生成,而是依赖于灵活的消息传递的方式:

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

  • 宿主监听的平台通道,并接收该消息。然后它会调用特定于该平台的API(使用原生编程语言) - 并将响应发送回客户端,即应用程序的Flutter部分。

 

框架概述: 平台通道

使用平台通道在客户端(Flutter UI)和宿主(平台)之间传递消息,如下图所示:

消息和响应是异步传递的,以确保用户界面保持响应(不会挂起)。

在客户端,MethodChannel (API)可以发送与方法调用相对应的消息。 在宿主平台上,MethodChannel 在Android((API) 和 FlutterMethodChannel iOS (API) 可以接收方法调用并返回结果。这些类允许您用很少的“脚手架”代码开发平台插件。

注意: 如果需要,方法调用也可以反向发送,宿主作为客户端调用Dart中实现的API。 

平台通道数据类型支持和解码器

标准平台通道使用标准消息编解码器,以支持简单的类似JSON值的高效二进制序列化,例如 booleans,numbers, Strings, byte buffers, List, Maps(请参阅StandardMessageCodec了解详细信息)。 当您发送和接收值时,这些值在消息中的序列化和反序列化会自动进行。

从UI代码中分离平台特定的代码

如果您希望在多个Flutter应用程序中使用特定于平台的代码,将代码分离为位于主应用程序之外的目录中,做一个平台插件会很有用。

将平台特定的代码作为一个包发布

如果您希望与Flutter生态系统中的其他开发人员分享您的特定平台的代码,请参阅发[发布 packages](/developing-packages/#publish以了解详细信息。

自定义平台通道和编解码器

除了上面提到的MethodChannel,你还可以使用BasicMessageChannel,它支持使用自定义消息编解码器进行基本的异步消息传递。 此外,您可以使用专门的BinaryCodecStringCodec和 JSONMessageCodec类,或创建自己的编解码器。


代码示例:

1.Flutter代码:

//使用平台通道编写平台特定的代码import 'dart:async';import 'package:flutter/material.dart';import 'package:flutter/services.dart';void main(){  runApp(MaterialApp(    home: PlatformChannel(),  ));}class PlatformChannel extends StatefulWidget {  @override  _PlatformChannelState createState() => _PlatformChannelState();}class _PlatformChannelState extends State {  static const MethodChannel methodChannel = MethodChannel('yinlei/battery');  static const EventChannel eventChannel = EventChannel('yinlei/charging');  String _batteryLevel = '当前电量: 未知.';  String _chargingStatus = '电量状态: 未知.';  Future _getBatteryLevel() async{    String batteryLevel;    try{      final int result = await methodChannel.invokeMethod('getBatteryLevel');      batteryLevel = '当前电量: $result%.';    } on PlatformException{      batteryLevel = '获取当前电量失败。';    }    setState(() {      _batteryLevel = batteryLevel;    });  }  @override  void initState() {    super.initState();    eventChannel.receiveBroadcastStream().listen(_onEvent,onError: _onError);  }  void _onEvent(Object event){    setState(() {      _chargingStatus = '当前电量状态: ${event == 'charging' ? '正在' : '未在'}充电.';    });  }  void _onError(Object error){    setState(() {      _chargingStatus = '电量状态未知出错。';    });  }  @override  Widget build(BuildContext context) {    return Material(      child: Column(        mainAxisAlignment: MainAxisAlignment.spaceEvenly,        children: [          Column(            mainAxisAlignment: MainAxisAlignment.center,            children: [              Text(_batteryLevel,key: const Key('当前电量'),),              Padding(                padding: const EdgeInsets.all(16.0),                child: RaisedButton(                  child: const Text('刷新'),                  onPressed: _getBatteryLevel,                ),              ),            ],          ),          Text(_chargingStatus),        ],      ),    );  }}

2.android代码:

package com.example.flutter_batterylevel;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;import android.os.Bundle;import io.flutter.app.FlutterActivity;import io.flutter.plugin.common.EventChannel;import io.flutter.plugin.common.MethodCall;import io.flutter.plugin.common.MethodChannel;import io.flutter.plugins.GeneratedPluginRegistrant;public class MainActivity extends FlutterActivity {  private static final String BATTERY_CHANNEL = "yinlei/battery";  private static final String CHARGING_CHANNEL = "yinlei/charging";  @Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    GeneratedPluginRegistrant.registerWith(this);    new EventChannel(getFlutterView(),CHARGING_CHANNEL).setStreamHandler(new EventChannel.StreamHandler() {      private BroadcastReceiver chargingStateChangeReceiver;      @Override      public void onListen(Object o, EventChannel.EventSink eventSink) {        chargingStateChangeReceiver = createChargingStateChangeReceiver(eventSink);        registerReceiver(chargingStateChangeReceiver,new IntentFilter(Intent.ACTION_BATTERY_CHANGED));      }      @Override      public void onCancel(Object o) {        unregisterReceiver(chargingStateChangeReceiver);        chargingStateChangeReceiver = null;      }    });    new MethodChannel(getFlutterView(),BATTERY_CHANNEL).setMethodCallHandler(new MethodChannel.MethodCallHandler() {      @Override      public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {        if(methodCall.method.equals("getBatteryLevel")){            int batteryLevel = getBatteryLevel();            if(batteryLevel != -1){              result.success(batteryLevel);            }else {              result.error("不可依赖。","当前电量等级不可依赖。",null);            }        }else {          result.notImplemented();        }      }    });  }  private BroadcastReceiver createChargingStateChangeReceiver(final 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("不可依赖的","充电状态是不可依赖的。",null);        }else {          boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING || status == BatteryManager.BATTERY_STATUS_FULL;          eventSink.success(isCharging ? "正在充电" : "未在充电");        }      }    };  }  private int getBatteryLevel(){    if(Build.VERSION.SDK_INT >= Build.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);    }  }}

3.权限:

运行结果:

更多相关文章

  1. 《第一行代码》学习笔记之服务
  2. 使用多字节字符集的跨平台(PC、Android、IOS、WP)编码/解码方法
  3. Android(安卓)Hybird App开发
  4. Cocos2d-x跨Android&iOS平台开发入门
  5. Android电量优化
  6. 一文学会所有 Android(安卓)TextView 属性,妈妈再也不担心我的代
  7. Android、iOS和Java通用的AES128加密解密示例代码
  8. Unity 与 Android(安卓)互调用
  9. [转]修改Android的自带程序“屏幕锁”

随机推荐

  1. MediaTest
  2. 仿微信运动步数折线统计图
  3. Android(安卓)Development
  4. android下多线程下载,断点续传,及暂停按
  5. Android中fragment模式
  6. Android(安卓)ToggleButton example
  7. Android(安卓)DES加密解密算法
  8. Android(安卓)gallery详解
  9. android.support.v7.app.AlertDialog显示
  10. driving mode block