背景
flutter现在无疑是移动端跨平台最火的ui框架之一(个人理解他只是一款框架),有些功能免不了会调用原生功能,如摄像头、指纹认证等底层功能。本次主要讲解是flutter与原生android互相通信实现方式。
1.编写flutter公共页面
数据双向通信主要有以下实现步骤:
(1)发送通道定义:
static const receive = const EventChannel('com.gxx.receive/plugin');
//跳转到原生Activity界面
Future<Null> _statrtToNativeActivity() async {
String result = await sendToNative.invokeMethod('startToEditActivity');
}
// 通过插件将传递数据到原生界面
Future<Null> _sendDataToNative() async {
Map<String, String> map = {"flutter": "我是flutter 传递过来的"};
String result = await sendToNative.invokeMethod('mapData', map);
print(result);
}
(2)接收通道定义:
//接收来自本地的消息
static const receiveFromNative =const EventChannel('com.gxx.send/plugin');
//监听接收消息
StreamSubscription _streamSubscription;
(3)在initState()方法中实例化数据接收监听
@override
void initState() {
super.initState();
//开启监听,通过原生界面将数据传递到flutter界面
if (_streamSubscription == null) {
_streamSubscription =
receiveFromNative.receiveBroadcastStream().listen((event) {
setState(() {
_currentCount = event;
print("ChannelPage: $event");
});
}, onError: (Object error) {
setState(() {
_currentCount = "计时器异常";
print(error);
});
});
}
}
(4)在dispose()方法中取消息订阅通道
@override
void dispose() {
// TODO: implement dispose
super.dispose();
//取消监听
if (_streamSubscription != null) {
_streamSubscription.cancel();
}
}
(6)整个完整代码如下:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: TestWidget());
}
}
class TestWidget extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return TestState();
}
}
class TestState extends State<TestWidget> {
//获取插件与原生Native的交互通道
static const sendToNative =
const MethodChannel('com.gxx.receive/plugin');
//具体要做的功能
Future<Null> _statrtToNativeActivity() async {
String result = await sendToNative.invokeMethod('startToEditActivity');
print(result);
}
// 具体要做的功能
Future<Null> _sendDataToNative() async {
Map<String, String> map = {"flutter": "我是flutter 传递过来的"};
String result = await sendToNative.invokeMethod('mapData', map);
print(result);
}
//接收来自本地的消息
static const receiveFromNative =
const EventChannel('com.gxx.send/plugin');
StreamSubscription _streamSubscription;
var _currentCount;
@override
void initState() {
super.initState();
//开启监听
if (_streamSubscription == null) {
_streamSubscription =
receiveFromNative.receiveBroadcastStream().listen((event) {
setState(() {
_currentCount = event;
print("ChannelPage: $event");
});
}, onError: (Object error) {
setState(() {
_currentCount = "计时器异常";
print(error);
});
});
}
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Container(
child: Column(
children: <Widget>[
RaisedButton(
child: Text('跳转到原生界面'),
onPressed: (){
_statrtToNativeActivity();
},
),
RaisedButton(
child: Text('让原生接收到数据'),
onPressed: (){
_sendDataToNative();
},
),
RaisedButton(child: Text("原生传递过来的数据:$_currentCount"),
onPressed: (){
},)
],
),
);
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
//取消监听
if (_streamSubscription != null) {
_streamSubscription.cancel();
}
}
}
2.原生代码编写
(1)定义数据接收插件(从flutter到原生界面)
public class FlutterPluginFtoA implements MethodChannel.MethodCallHandler {
//这里要注意和Flutter使用的相同
public static final String A_TO_F_CHANNEL = "com.gxx.receive/plugin";
private Activity handlerActivity;
public FlutterPluginFtoA(Activity activity) {
this.handlerActivity = activity;
}
public static void registerWith(PluginRegistry.Registrar registrar) {
//主要的方法MethodChannel
MethodChannel methodChannel = new MethodChannel(registrar.messenger(), A_TO_F_CHANNEL);
FlutterPluginFtoA instance = new FlutterPluginFtoA(registrar.activity());
methodChannel.setMethodCallHandler(instance);
}
@Override
public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
switch (methodCall.method){
case "showToast":
//接收Flutter 传递过来的参数
Object arguments = methodCall.arguments;
Toast.makeText(handlerActivity, "收到Flutter传过来的" + arguments, Toast.LENGTH_SHORT).show();
break;
case "startToEditActivity":
//跳转到原生界面
Intent editActivityIntent = new Intent(handlerActivity, TestActivity.class);
handlerActivity.startActivity(editActivityIntent);
result.success("startOk");
break;
case "mapData":
//Flutter 传递过来的数据
//解析参数
String text = methodCall.argument("flutter");
Toast.makeText(handlerActivity, "接收: " + text, Toast.LENGTH_SHORT).show();
break;
}
}
}
(2)定义原生端到flutter端数据传递
public class FlutterPluginAtoF implements EventChannel.StreamHandler {
public static final String F_TO_A_CHANNEL = "com.gxx.send/plugin";
private static FlutterPluginAtoF instance;
private EventChannel.EventSink events;
public static FlutterPluginAtoF getInstance(){
return instance;
}
@Override
public void onListen(Object o, EventChannel.EventSink eventSink) {
this.events=eventSink;
}
public static void registerWith(PluginRegistry.Registrar registrar){
EventChannel eventChannel=new EventChannel(registrar.messenger(),F_TO_A_CHANNEL);
instance=new FlutterPluginAtoF();
eventChannel.setStreamHandler(instance);
}
@Override
public void onCancel(Object o) {
}
public void sendEventData(Object data){
if(events!=null){
events.success(data);
}
}
}
(3)在MainActivity分别注册接收端插件与发送端插件
class MainActivity : FlutterActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// setContentView(R.layout.activity_edit_h5)
//获取到自身的Registry
val registry = flutterView.pluginRegistry;
//注册插件
FlutterPluginFtoA.registerWith(registry.registrarFor(FlutterPluginFtoA.A_TO_F_CHANNEL));
FlutterPluginAtoF.registerWith(registry.registrarFor(FlutterPluginAtoF.F_TO_A_CHANNEL));
}
}
(4)flutter页面直接跳转到原生界面 点击确定后将原生端数据传递给flutter页面
public class TestActivity extends Activity implements View.OnClickListener {
private int currentCount = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_edit_h5);
Button btn=findViewById(R.id.tvIntentTxt);
btn.setText("传递给flutter");
btn.setOnClickListener(this);
}
@Override
public void onClick(View view) {
//
FlutterPluginAtoF.getInstance().sendEventData(""+ currentCount++); //通过这个发送消息到Flutter
Toast.makeText(this, currentCount+"", Toast.LENGTH_SHORT).show();
}
}
3.效果
说明:以上为原生界面传递到flutter界面
说明:以上为flutter界面传递到原生界面
4.最后
本篇博客只作为学习记录知识,感谢其他博客提供思路。源码地址:github.com/guoxuxiong/…