Flutter插件混编的各种奇葩问题以及Flutter与Native数据交互,MethodChannel(仅Android)

前言

Flutter目前还不稳定,git上目前还有**5000+**的问题没有解决,所以入坑需谨慎啊

背景

在做Android和flutter的混编,混编教程可参考上一篇 Flutter与Android的混编 我们项目在flutter的开发中 引入了 相机相册框架 Image_picker ,二维码扫描 barcode_scan ,还有阿里的 flutter_boost路由框架(这个框架有很多的坑),还有一些其他框架就不介绍了! 其实就目前我来说,这些框架都是坑,在flutter项目上没有什么问题,但是一混编就完蛋了,各种问题,而且你要是网上找答案,资料很少,(拖他的福,我最近英语功力突飞猛进orz…,希望慢慢变好吧)这里简单介绍下:
先说明一下啊,flutter的很多问题可以通过升级flutterSDK到最新版本,flutter插件升级到最新版本去解决(然而混编不行 -_-);混编的话你如果使用了AndroidX 则一些支持库需要统一处理(androidX与flutter兼容有问题)

  1. Image_picker
    与Android混编的时候,首先的一个限制就是版本问题,现在最新的版本是0.6.0+9,在flutter项目里面编译一切正常,但是一混编,就会提示你 :

    This version of image_picker will break your Android build if it or its dependencies

    很明显版本问题,然后就开始降版本,结果都不行,最后查资料 0.4.12+1 这个版本可以运行,,NMMP…确实可以编译了(真特么奇葩);好了这个bug解决了,然后运行 成功,打开相机 一切OK,然后拍照,返回的数据是NULL,what?然后再启动 启动不了了,提示:
    PlatformException(already_active, Image picker is already active, null)
    相机已经运行了,但是就是看不到界面,一开始查资料说是权限的问题,我目标版本是26然后我加了动态获取权限,或者改到22都不行,其实image_picker插件做了权限方面的处理操作,在混编中 插件都会生成对应的 library,例如:
    Flutter插件混编的各种奇葩问题以及Flutter与Native数据交互,MethodChannel(仅Android)_第1张图片其中在ImagePickerDelegate 中做了权限的相关处理,这个问题纠结了我很久,查了N多的方案,改配置,改插件里面的代码(混编有个好处就是可以修改插件生成的代码),添加 onActivityResult,然而都不行,曾经把咸鱼的flutter文档都翻了一个遍(本人水平有限,很多高大尚的东西看不懂),然并卵啊,(我们老大就是看着咸鱼用了flutter就让我们也用-_----),当然 目前依然没有解决(别打我—),如果有解决可以通知我,我学习下姿势!

2.barcode_scan
这个插件的问题更多,版本问题,然后我的项目中已经有了zxing的扫描包,然后这两个会起冲突,因为barcode_scan中引入了一个第三方,而这个第三方又引入了ZXing,就算删掉本地的引用也不行,所以就废弃不用啦…手动笑脸
3. cached_network_image
这是一个图片资源的缓存插件,这个里面也有坑(针对AndroidX),他引用了flutter的一个插件flutter_cache_manager,而这个插件里面又引入了 path_provider 插件,而AndroidX支持path_provider版本为最高path_provider: 0.4.1,你如果直接引入这个版本也会报错,所以只能修改flutter_cache_manager的版本,我试了很多版本最高0.5.1可以使用
关于flutter插件与AndroidX兼容版本可以参考该链接
以上的问题,ios没有遇到,只要Android遇到了,,呵呵呵,,是不是使用姿势有问题啊,不得而知…
饭可以不吃,app不能不上线啊,手动 笑着哭
总有方法可以完成任务的,插件不行我就手动调用原生,who 怕 who!

解决办法: Flutter与Native数据交互

  1. Flutter APP同iOS&Android native之间的数据通信如下图所示(手动盗图)
    Flutter插件混编的各种奇葩问题以及Flutter与Native数据交互,MethodChannel(仅Android)_第2张图片
    消息和响应是异步传递,以确保用户界面保持响应。
    在客户端,MethodChannel(API)允许发送对应于方法调用的消息。在平台端,Android上的MethodChannel(API)和iOS上的FlutterMethodChannel(API)支持接收方法调用并返回结果。
    2.平台信道数据类型支持和编解码器
    Flutter插件混编的各种奇葩问题以及Flutter与Native数据交互,MethodChannel(仅Android)_第3张图片3. flutter dart代码里添加
  MethodChannel platform;

  @override
  void initState() {
    platform = const MethodChannel('sample.flutter.io/camera');
    platform.setMethodCallHandler(methodHandler);
    super.initState();
  }

  // 接收原生平台的方法调用处理
  Future methodHandler(MethodCall call) async {
    switch (call.method) {
      case "action1":
        break;
    }
  }

首先是约定好双方通信的 通道,在这里是标识(sample.flutter.io/camera)。
同时设置好原生调用flutter的方法处理 methodHandler
flutter 调用Android原生的代码如下

  _getCamera() async {
    String result;
    try {
      result = await platform.invokeMethod('getCamera', "2");
    } on PlatformException catch (e) {
      result = "Failed to  openCamera";
    }
    setState(() {
      _imgPath = new File(result);
    });
  }

await platform.invokeMethod(‘getCamera’, “2”); 这个方法就是调用原生的处理,加上await 会有返回值,第一个参数用来做标识,第二个作为参数传递

在Android端:

    private lateinit var mChannel: MethodChannel

    private fun inintListener() {
        mChannel = MethodChannel(flutterView, "sample.flutter.io/camera")

        mChannel.setMethodCallHandler { methodCall, result ->
            [email protected] = result
            when (methodCall.method) {
                "getBatteryLevel" -> {
                    val args = methodCall.arguments()
                    Log.e("tag", args)
                    val batteryLevel = getBatteryLevel()
                    if (batteryLevel != -1) {
                        result.success(batteryLevel)
                    } else {
                        result.error("UNAVAILABLE", "Battery level not available.", null)
                    }
                }
                "getCamera" -> {
                    val arg = methodCall.arguments()
                    Log.e("tag", arg)
                    if (arg == "1")
                        uploadPictures(1)
                    else
                        uploadPictures(2)
                }
            }
        }

    }

这里的代码是用来监听回调的,当 dart 调用invokeMethod这里会被触发
三、总结

其实总结下来,flutter调用Android原生代码就一下四点

1.flutter端创建一个MethodChannel,名字要和Android端的相同,并使用MethodChannel通过唯一方法名对应调用Android原生方法。
2.Android端同样生成一个MethodChannel,名字要和上步骤Flutter中创建的相同。继承MethodCallHandler方法后实现onMethodCall(MethodCall call, Result result)方法,通过call拿到上步骤调用的唯一方法名实现不同的方法。
3.在继承了FlutterActivity的Activity中注册步骤2中实现了MethodCallHandler的通道。
4. 开始在flutter的控件中调用原生方法。

写的比较简单,是以完成项目目前的功能为前提下匆匆记录的,希望能帮助到一些人。

你可能感兴趣的:(flutter混编尝试)