【Flutter 问题系列第 70 篇】Flutter 与 Android 原生交互(通信)方式之 MethodChannel(精简教程)

这是【Flutter 问题系列第 70 篇】,如果觉得有用的话,欢迎关注专栏。

博文所用 Flutter SDK:2.2.3,Dart SDK:2.13.4。

摘要:

因为有人注重结果,所以想直接把代码拿过来先运行下看效果,那么这篇博客就是为你量身打造的。

也有人看重过程,那么这篇 详细说明 Flutter 与 Android 原生交互(通信)方式之 MethodChannel(保姆级图文教程)值得你一看。

一:简述 Flutter 与原生通信的三种方式

Flutter 与原生通信有三种方式

  • MethodChannel
  • EventChannel
  • BasicMessageChannel

这三种方式,无论是传递方法还是事件,本质上都是传递的数据。

二:Flutter 与 Android 原生通信

因为我在工作中用到最多的通信方式是 MethodChannel,后面我将以该方式为例,说下 Flutter 与 Android 原生是如何通信的,下面我们分端进行描述。

三:Flutter 端

先看示例代码

import 'dart:convert';
import 'package:flutter/services.dart';

// ------------------------------------------------------
// author:Allen Su
// date  :2022/6/20 22:25
// usage :插件理器 - Flutter 端
// ------------------------------------------------------

class PackageManager {
    
    
	// _channel 是通道的实例,package_manager 是自定义的通道名称
	static const MethodChannel _channel = const MethodChannel("package_manager"); 

	// 根据传入的包名安装 App
	// 注:方法名install和invokeMethod中的参数install不是要一定相同,这里相同是为了方便一眼看出函数的功能
	Future<bool> install() async {
    
    
      // install 调用方法的名称,com.allensu 传递的数据
  	  bool res = await _channel.invokeMethod("install", "com.allensu"); 
  	  return res;
    }
}

设置 Flutter 端的通道比较简单,一共需要两步

第 1 步:创建通道

在 Flutter 中,使用 MethodChannel 创建通道。有一个必传参数 name ,是通道起的名称,一个通道对应一个唯一的名称,不同的通道用了相同的名称会彼此干扰。

第 2 步:发起通道方法的调用

在 Flutter 端我们使用 MethodChannel 类中的方法 invokeMethod 发起一次调用。

invokeMethod 是一个返回值为泛型的异步方法(返回值根据需要设置,可有可无),有一个必传参数 method ,是要调用的方法的名称,还有一个可传参数 arguments ,是方法调用时传递的数据,类型是 dynamic 。

四:Android 端

先看示例代码

第一部分是关于具体要实现功能类的写法,如下代码所示

package com.package.manager.package_demo;

import androidx.annotation.NonNull;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.Result;

// ------------------------------------------------------
// author:suxing
// date  :2022/6/20 22:40
// usage :插件理器 - Android 端
// ------------------------------------------------------

public class PackageManagerPlugin implements FlutterPlugin {
    
    

    @Override
    public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
    
    
        // 声明通道,第二个参数 name 要和 Flutter 中定义的通道名称保持一致
        MethodChannel channel = new MethodChannel(binding.getBinaryMessenger(), "package_manager");
        // 在此通道上注册方法调用将要处理的功能(函数)
        channel.setMethodCallHandler(this::onMethodCall);
    }
	
    /// 处理不同名称方法的回调
    public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
    
    
        // call.method 回调中的方法名,要和在 Flutter 中定义的保持一致
        switch (call.method) {
    
    
           case "install":
              // 这里的 packageName 是在 Flutter 中定义的 com.allensu
              String packageName = call.arguments();
              // 执行安装功能,并返回安装结果
              boolean res = install(packageName); 
              // 将安装结果回调给 Flutter
              result.success(res); 
              break;
           case "other":
              // 这里的 other 是一个测试,意思是如果方法名是 other,则执行 doSomething 函数
              doSomething();
              // 如果不需要回调数据,则参数填 null
              result.success(null); 
              break;
           default:
              // 如果回调异常,则设置相关信息
              result.error("错误码","错误信息","错误详情");
              break;
           }
      }
}

第二部分是在 MainActivity 中注册插件的实例,如下代码所示

package com.package.manager.package_demo;

import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngin e;

// ------------------------------------------------------
// author:Allen Su
// date  :2022/6/20 22:45
// usage :Flutter 与 Android 通信的入口
// ------------------------------------------------------

public class MainActivity extends FlutterActivity {
    
    

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
    }

    @Override
    public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
    
    
        // 注册插件的实例(如果有多个需要册插件的实例,依次增加即可)
        flutterEngine.getPlugins().add(new PackageManagerPlugin());
        super.configureFlutterEngine(flutterEngine);
    }
}

设置 Android 端的通道相对麻烦一点,一共需要三步

第 1 步:创建通道

同样使用 MethodChannel 声明一个通道,特别要注意,第二个参数 name 要和 Flutter 中定义的通道名称保持一致。

第 2 步:在通道上注册方法

通过 channel.setMethodCallHandler 在通道上注册方法,通过 call.method 获取当前通信的方法名,通过 result.success 和 result.error 设置回调状态。

第 3 步:在 MainActivity 中注册插件的实例

通过 flutterEngine.getPlugins().add 方法注册插件的实例即可。

你的问题得到解决了吗?欢迎在评论区留言。

赠人玫瑰,手有余香,如果觉得文章不错,希望可以给个一键三连,感谢。


结束语

Google 的 Flutter 越来越火,截止 2022年6月21日 GitHub 标星已达 142K,Flutter 毅然是一种趋势,所以作为前端开发者,没有理由不趁早去学习。

无论你是 Flutter 新手还是已经入门了,不妨先点个关注,后续我会将 Flutter 中的常用组件(含有源码分析、组件的用法及注意事项)以及可能遇到的问题写到 CSDN 博客中,希望自己学习的同时,也可以帮助更多的人。

猜你喜欢

转载自blog.csdn.net/qq_42351033/article/details/125389117