Flutter原生插件-Android

Flutter原生插件

一、什么是Flutter插件

1、Flutter的四种工程类型
a、Flutter Application

​ 全新的APP,标准的Flutter App工程,包含标准的Dart层与Native平台层

b、Flutter Module

​ 混编到已有的安卓/iOS工程内

c、Flutter Plugin

​ Flutter平台插件工程,包含Dart层与Native平台层的实现。Plugin其实就是一个特殊的Package。 Flutter Plugin提供Android或者iOS的底层封装,在Flutter层提供组件功能,使Flutter可以较方便的调取 Native的模块。很多平台相关性或者对于Flutter实现起来比较复杂的部分,都可以封装成Plugin。其原理 如下

Flutter原生插件-Android_第1张图片

d、Flutter Package

​ Flutter纯Dart插件工程,仅包含Dart层的实现,往往定义一些公共Widget

二、创建Flutter Plugin工程

1、ide创建
a、在菜单栏中选择 File -> New -> New Flutter Project
b、在弹出的窗口选择Flutter Plugin 然后一路 Next 就可以了

Flutter原生插件-Android_第2张图片

这是IDE创建的目录结构,包括ios和Android目录

图中包含的几个主要的目录分别为 androidexampleioslib 这四个目录: - android 目录是一个完整的 Android 工程,用来开发 Android 端的插件功能 - example 目录用来测试 Android 或者 IOS 端的插件功能 - ios 目录是一个完整的 IOS 工程,用来开发 IOS 端的插件功能 - lib 目录中的文件负责和 Android 或者 IOS 端的交互

2、命令行创建(尝试后发现有问题,没有ios和Android目录)
flutter create -t plugin flutter_plugin_demo

Flutter原生插件-Android_第3张图片

这个命令行创建没有Android和ios目录,但这是flutter官网上的创建命令行,不知道是不是flutter SDK更新的原因,所以还是用IDE创建

三、Android原生插件运行前配置

环境:flutter SDK:1.20.3

**1、**远程拉的代码要先在Perfrences(Mac)/Settings(Windows)里配置flutter SDK路径

Flutter原生插件-Android_第4张图片

**2、**此时进入project下的android/src.main.java.com.xxx.xxx目录,打开FlutterPlugin目录,发现flutter相关类全部报红,这是因为插件里没有配置flutter的sdk,解决办法如下:

​ 在android/src.main目录下新建libs文件夹,将fluttersdk目录下的bin/cache/artifacts/engine文件夹下的随便一个Android平台的jar包复制到刚刚创建的libs目录下(我用的是android-arm的flutter.jar包);

​ 复制之后,在as中右键单击flutter.jar包,选择Add As Library…

Flutter原生插件-Android_第5张图片

​ 再在as->file->open…打开project下的android项目,会发现flutter的相关import都正常了,NonNull的引用还是红色,直接alt+enter引入依赖即可。

​ 最后在project的android目录下的build.gradle文件中将dependencies中的:

implementation files('src/main/libs/flutter.jar')

​ 改成:

compileOnly files('src/main/libs/flutter.jar')

**3、**project目录下的Android项目是插件,不能单独运行,要在project下的example项目中才能运行(example项目创建时就添加了对此插件的依赖,专门用于测试插件运行的,是个示例程序。

既然不能运行,为什么要打开project下的Android工程? 因为在example中虽然可以修改plugin中的java文件的代码,但是不能看到build.gradle和setting.gradle的配置文件

**4、**在project下的Android项目中完成flutter和native的桥接接口开发之后,在as->file->open…打开example下的Android项目,此时已经可以运行项目了。

注:也可直接在项目中运行插件,在项目的yaml文件中配置插件路径即可引入插件

四、FlutterPlugin的开发

1、介绍

​ 在 Flutter 1.12 开始 Flutter 团队调整了 Android 插件的实现代码,在 1.12 之后 Android 开始使用新的插件 API ,基于的旧的 PluginRegistry.Registrar 不会立即被弃用,但官方建议迁移到基于的新API FlutterPlugin ,另外新版本官方建议插件直接使用 Androidx 支持,官方提供的插件也已经全面升级到 Androidx

与旧的 API 相比,新 API 的优势在于:为插件所依赖的生命周期提供了一套更解耦的使用方法,例如以前 PluginRegistry.Registrar.activity() 在使用时,如果 Flutter 还没有添加到 Activity 上时可能返回 null ,同时插件不知道自己何时被引擎加载使用,而新的 API 上这些问题都得到了优化。

2、FlutterPlugin的使用

以下是创建flutter plugin时自动生成的插件代码:

package com.example.flutter_plugin;

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.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry.Registrar;

/** FlutterPlugin */
public class FlutterDemoPlugin implements FlutterPlugin, MethodCallHandler {
  /// The MethodChannel that will the communication between Flutter and native Android
  ///
  /// This local reference serves to register the plugin with the Flutter Engine and unregister it
  /// when the Flutter Engine is detached from the Activity
  private MethodChannel channel;

  @Override
  public void onAttachedToEngine(@NonNull io.flutter.embedding.engine.plugins.FlutterPlugin.FlutterPluginBinding flutterPluginBinding) {
    channel = new MethodChannel(flutterPluginBinding.getFlutterEngine().getDartExecutor(), "flutter_plugin");
    channel.setMethodCallHandler(this);
  }

  // This static function is optional and equivalent to onAttachedToEngine. It supports the old
  // pre-Flutter-1.12 Android projects. You are encouraged to continue supporting
  // plugin registration via this function while apps migrate to use the new Android APIs
  // post-flutter-1.12 via https://flutter.dev/go/android-project-migration.
  //
  // It is encouraged to share logic between onAttachedToEngine and registerWith to keep
  // them functionally equivalent. Only one of onAttachedToEngine or registerWith will be called
  // depending on the user's project. onAttachedToEngine or registerWith must both be defined
  // in the same class.
  //针对旧版本做兼容支持的方法
  public static void registerWith(Registrar registrar) {
    final MethodChannel channel = new MethodChannel(registrar.messenger(), "flutter_plugin");
    channel.setMethodCallHandler(new FlutterDemoPlugin());
  }

  //flutter桥接接口方法
  @Override
  public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
    if (call.method.equals("getPlatformVersion")) {
      result.success("Android " + android.os.Build.VERSION.RELEASE);
    } else {
      result.notImplemented();
    }
  }

  @Override
  public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
    channel.setMethodCallHandler(null);
  }
}

在新 API 上 Android 插件需要使用 FlutterPluginMethodCallHandler 进行实现,同时还提供了 ActivityAware 用于 Activity 的生命周期管理和获取,提供 ServiceAware 用于 Service 的生命周期管理和获取。

以前的 Flutter 插件都是直接继承 MethodCallHandler 然后提供 registerWith 静态方法;而升级后如下代码所示,这里还保留了 registerWith 静态方法,是因为还需要针对旧版本做兼容支持。

 public WxLoginPlugin initPlugin(MethodChannel channel, Registrar registrar) {
    this.channel = channel;
    mApplication = (Application) registrar.context().getApplicationContext();
    mActivity = new WeakReference<>( registrar.activity());
    return this;
  }

  //旧的插件加载方式
  public static void registerWith(Registrar registrar) {
    MethodChannel methodChannel = new MethodChannel(registrar.messenger(), PLUGIN_NAME);
    methodChannel.setMethodCallHandler(new WxLoginPlugin().initPlugin(methodChannel, registrar));
  }

以下四个方法是**ActivityAware**的接口方法,在attach和detach中初始化和释放mActivity:

  @Override
  public void onAttachedToActivity(@NonNull ActivityPluginBinding activityPluginBinding) {
    mActivity = new WeakReference<>(activityPluginBinding.getActivity());
  }

  @Override
  public void onDetachedFromActivityForConfigChanges() {

  }

  @Override
  public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding activityPluginBinding) {

  }

  @Override
  public void onDetachedFromActivity() {
    mActivity = null;
  }

五、Flutter Plugin的调用

1、新API上 ,Activity要继承自io.flutter.embedding.android.FlutterActivity,这样插件就可以自动注册;
2、如果条件不允许,不能继承io.flutter.embedding.android.FlutterActivity,需要手动调用GeneratedPluginRegistrant.registerWith 方法,并且要配置AndroidManifest.xml 文件:

在Activity节点下增加配置:

						<!-- Specifies an Android theme to apply to this Activity as soon as
                 the Android process has started. This theme is visible to the user
                 while the Flutter UI initializes. After that, this theme continues
                 to determine the Window background behind the Flutter UI. -->
            <meta-data
              android:name="io.flutter.embedding.android.NormalTheme"
              android:resource="@style/NormalTheme"
              />
            <!-- Displays an Android View that continues showing the launch screen
                 Drawable until Flutter paints its first frame, then this splash
                 screen fades out. A splash screen is useful to avoid any visual
                 gap between the end of Android's launch screen and the painting of
                 Flutter's first frame. -->
            <meta-data
              android:name="io.flutter.embedding.android.SplashScreenDrawable"
              android:resource="@drawable/launch_background"
              />

在Application节点下增加配置:

				<!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
3、之后就可以执行 flutter packages get 去生成了新的 GeneratedPluginRegistrant 文件,如下代码所示,新的 FlutterPlugin 将被 flutterEngine.getPlugins().add 直接加载,而旧的插件实现方法会通过 ShimPluginRegistry 被兼容加载到 v2 的实现当中。
@Keep
public final class GeneratedPluginRegistrant {
  public static void registerWith(@NonNull FlutterEngine flutterEngine) {
    flutterEngine.getPlugins().add(new com.example.flutter_plugin.FlutterDemoPlugin());
  }
}
4、配置pubspec.yaml文件,在项目中引入插件:
  # 登录插件
  wx_login:
#    path: ../Plugin/wx_login/
    git:
      url: http://git.wangxutech.com/mobile/flutter/plugins/wxlogin.git

path是引入本地插件代码,写代码相对路径即可

git是引入git仓库代码,默认master分支

参考链接:Flutter 升级 1.12 适配教程

你可能感兴趣的:(android开发学习记录,flutter学习记录,android,移动开发,flutter)