Flutter与原生通信(上)

一 、flutter中通信的三种方式

BasicMessageChannel:用于传递字符串和半结构化的信息
MethodChannel:用于传递方法调用(method invocation)通常用来调用native中某个方法
EventChannel: 用于数据流(event streams)的通信。有监听功能,比如电量变化之后直接推送数据给flutter端。


二 、MethodChannel的使用

1.搭建流程:
Flutter ------>Native
MethodChannel是Flutter和原生交互的基础,通过传入Flutter插件的名字,调用invokeMethod方法,便可以调用原生的方法,有点类似于Java的反射。
注册渠道:在两端同时创建一个MethodChannel对象,注册相同的字符串值。
Android端

MethodChannel a2FChannel = new MethodChannel((FlutterView)flutterView,"A2FChannel");

Flutter端

 var channel = MethodChannel("A2FChannel");
 final String result = await channel.invokeMethod(nativeMethod, args);

setMethodCallHandler 方法注解

channel.setMethodCallHandler { call, result ->
           //call.method 来获取方法名
           //call.arguments 来获取入参
           //result.success来放回成功处理结果
           //result.error来放回失败后的结果
           //result.notImplemented来放回为实现该方法
     }

Native ------>Flutter
在( Flutter ——> Native)代码基础上面
Native端

channel.invokeMethod(flutterMethod, args, new MethodChannel.Result () {
			 //方法重写
        @Override
        public void success(@Nullable Object o) {
        }
       @Override
       public void error(String s, @Nullable String s1, @Nullable Object o) {
			}
			@Override
       public void notImplemented() {
                }
            })

Flutter端

_channel.setMethodCallHandler((MethodCall call) {
      //call.method 来获取方法名
      //call.arguments 来获取参数
    });

2.本地方法编写

在 Flutter 1.12 ,插件 API 升 级到了 2.0 。
API 2.0 之前。
开发者通常要在 MainActivity 的 onCreate() 方法中手动调用 GeneratedPluginRegistrant.registerWith() 来执行插件类中的一个静态方法初始化插件。
API 2.0 之后,出现了 FlutterPlugin 接口。
开发者只要让创建的插件类实现它,并把初始化代码放到一个重写的方法中就好了。

//API 2.0 之前。
public class MainActivity extends FlutterActivity {
	 @Override
	 protected void onCreate(Bundle savedInstanceState) {
	 super.onCreate(savedInstanceState);
	 GeneratedPluginRegistrant.registerWith(this);
 }
}
 //API2.0之后
     @Override
     public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
     super.configureFlutterEngine(flutterEngine);
  }

PS知识点

  1. 启动一个 Android 应用,启动的通常是一个 Activity ,如果这个应用是 Flutter 应用,那么这个 Activity 是 FlutterActivity 。
  2. 在 FlutterActivity 的 onCreate() 方法中,创建了一个 FlutterEngine ,是一个单独的 Flutter 执行环境,通过它,可以让一个 Android 应用运行 Dart 代码。FlutterEngine 提供了,FlutterRenderer 负责渲染视图。DartExecutor 作为 BinaryMessenger 用来和 Flutter 端通信。我们创建 MethodChannel 就要用到这个。

3.flutter通过原生获取手机电量示例代码如下:


Flutter与原生通信(上)_第1张图片

MainActivity

package com.example.item_1;

import androidx.annotation.NonNull;

import io.flutter.embedding.android.FlutterActivity;

import io.flutter.embedding.engine.FlutterEngine;

import io.flutter.plugins.GeneratedPluginRegistrant;

import io.flutter.plugin.common.MethodChannel;

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;
//单独打开android环境下能够查看目录
public class MainActivity extends FlutterActivity {
    //定义一个私有的静态成员变量
    private static final String CHANNEL = "com.jk/battery";
    //初始化
    @Override
    public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
        super.configureFlutterEngine(flutterEngine);
        //创建MethodChannel对象,添加调用方法
        //写法1:
//        new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(
//                new MethodChannel.MethodCallHandler() {
//                    @Override
//                    public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
//                        // 通过methodCall可以获取参数和方法名  执行对应的平台业务逻辑即可
//                        if(methodCall.method.equals("getBatteryLevel")){
//                            int batteryLevel = getBatteryLevel();
//                            if(batteryLevel != -1){
//                                result.success(batteryLevel);
//                            }else{
//                                result.error("UNAVAILABLE", "Battery level not available.", null);
//                            }
//                        }else{
//                            result.notImplemented();
//                        }
//                    }
//                }
//        );
        //写法2:
        //新版的Flutter SDK默认使用的是 import io.flutter.embedding.android.FlutterActivity; 包,
        // 则在MethodChannel方法中的第一个参数填写 getFlutterEngine().getDartExecutor().getBinaryMessenger()
        //如果你使用的Flutter的SDK是旧版本,那么默认的是 import io.flutter.app.FlutterActivity; 包
        // 则MethodChannel方法中的第一个参数填写 getFlutterView()
        MethodChannel methodChannel = new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL);
        methodChannel.setMethodCallHandler(
                (call, result) -> {
                    //如果等于flutter中传过来的方法名称
                    if (call.method.equals("getBatteryInfo")) {
                        //调用另外一个自定义方法回去电量信息
                        int batteryLevel = getBatteryLevel();
                        if (batteryLevel != -1) {
                            result.success(batteryLevel);
                        } else {
                            result.error("UNAVAILABLE", "Battery level not available.", null);
                        }
                    } else {
                        //如果没有这个方法名称就返回没有这个接口
                        result.notImplemented();
                    }
                }
        );
    }
    private int getBatteryLevel() {

        int batteryLevel = -1;

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

            BatteryManager batteryManager = (BatteryManager) getSystemService(BATTERY_SERVICE);

            batteryLevel = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);

        } else {

            Intent intent = new ContextWrapper(getApplicationContext()).

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

            batteryLevel = (intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) * 100) /

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

        }
        return batteryLevel;
    }
}

Flutter

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class PageOne extends StatefulWidget {
  const PageOne({Key key}) : super(key: key);

  @override
  State<PageOne> createState() => _Page_oneState();
}
class _Page_oneState extends State<PageOne> {
  String value = "电量剩余";
  //建立与原生交互的连接点
  static const channel = const MethodChannel("com.jk/battery");
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("通过原生获取电量"),
      ),
      body: Container(
        child: Column(
          children: [
            Text("$value"),
            FloatingActionButton(onPressed: ()=>getData(),child: Text("电量"),)
          ],
        ),
      ),
    );
  }
  Future getData()async{
    String batteryLevel;
    final int result = await channel.invokeMethod("getBatteryInfo");
    try{
      //从原生种获取当前channel中的方法值
      final int result = await channel.invokeMethod("getBatteryInfo");
      batteryLevel = 'Battery level at $result % .';
    }on PlatformException catch(e){
      batteryLevel = "Failed to get battery level: '${e.message}'.";
    }
    setState(() {
      value = batteryLevel;
    });
  }
}

Flutter与原生通信(上)_第2张图片

你可能感兴趣的:(移动开发,flutter,android,java)