Flutter: 以 aar 形式嵌入 android 中的方案和原理

7,070 阅读3分钟

Flutter 以 aar 的方式接入 native 项目的优点是侵入性低,不影响业务组其他成员。 最开始的时候在网上看了一下关于 aar 导入 android 的博客感觉稍乱,所以在此整理一下,防止大家浪费时间重复趟坑。

Flutter 编译产物

首先需要先了解一下 flutter 的编译产物有哪些,然后才能更好地理解如何编译 aar。

以一个嵌入 flutter aar 的 release 版本为例看一下里面的内容:

可以很明显的看到三个和 Flutter 先关的文件:

  • libflutter.so: flutter engin
  • libapp.so:dart 源码相关
  • flutter_assets:flutter 资源文件

其实还有一个文件:

  • classes.dex: native 代码,比如 java 我们使用 dex2jar 工具看一下 classes.dex 的内容:

可以看到里面有关于 Flutter 的 native 代码,其实可以称它为: flutter_embedding.jar,里面包含了 FlutterActivity,FlutterView 等,它提供了 native 项目嵌入 flutter 的能力,比如我们 natvie 要创建一个 Flutter 页面肯定要继承 FlutterActivity/FlutterFragment。

总结一下 android release 下 flutter 的编译产物包含 4 部分:

  • libflutter.so: flutter engin
  • libapp.so:dart 源码相关
  • flutter_assets:flutter 资源文件
  • flutter_embedding.jar:提供了 flutter 嵌入 native 的能力。

官方编译 aar 方案

其实官方就已经给出了以 aar 方式导入 native 项目的方案,只是大家如果不明白原理会很迷惑,所以在这里给大家解下疑惑。

1.创建一个 Flutter Moudle 工程:

这个工程下会包含一个 .android moudle,可以让这个项目编译成 apk 。

2.build aar
flutter build aar

然后会看到这样一行输出提示:

✓ Built build/host/outputs/repo.

意思是创建了一个上面的文件夹,我们到根目录下这个文件夹就可以看到里面是编译好的 aar:

这个时候我们将这个 aar 导入到 native 项目中会发现没法使用,因为里面根本没有 flutter.so 和 flutter_embedding.jar,这个 aar 内容如下:

可以看到只有 资源文件和 dart 代码。

其实 google 已经给我们设置好了方案,当你执行完 flutter build aar 之后还会看到如下提示:

Consuming the Module
  1. Open <host>/app/build.gradle
  2. Ensure you have the repositories configured, otherwise add them:

      repositories {
        maven {
            url '/Users/wangzhen/code/flutter_module/build/host/outputs/repo'
        }
        maven {
            url 'http://download.flutter.io'
        }
      }

  3. Make the host app depend on the Flutter module:

    dependencies {
      debugImplementation 'com.wangzhen.flutter_module:flutter_debug:1.0
      profileImplementation 'com.wangzhen.flutter_module:flutter_profile:1.0
      releaseImplementation 'com.wangzhen.flutter_module:flutter_release:1.0
    }


  4. Add the `profile` build type:

    android {
      buildTypes {
        profile {
          initWith debug
        }
      }
    }

To learn more, visit https://flutter.dev/go/build-aar

google 在你执行 flutter build aar 的时候会给你创建一个 maven 仓库:

我们来看一下这个 maven 仓库的配置,也就是 flutter_release-1.0.pom:

这样就凑齐了所有的编译产物,那么我们再新建一个 android 项目,按照 google 的提示就可以将将 flutter 导入到 native 项目了。

3.native 项目 接入 aar
  • 首先我们 app/build.gradle 中添加本地仓库:
android {
    ...
    repositories {
    // 本地仓库路径
        maven {
            url '/Users/wangzhen/code/flutter_module/build/host/outputs/repo'
        }
   // flutter.so 和 flutter_embedding.jar 所在的远端仓库     
        maven {
            url 'http://download.flutter.io'
        }
    }
}
  • 然后在 app/build.gradle 中添加 aar 依赖:
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar','*.aar'])
   
    debugImplementation 'com.wangzhen.flutter_module:flutter_debug:1.0'
    // 可以看到就是 pom 中的 groupId:artifactId:version
    releaseImplementation 'com.wangzhen.flutter_module:flutter_release:1.0'

}

最后在 native 中新建一个 FlutterActivity 验证一下:

class FlutterDemoActivity : FlutterActivity() {
    override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
        super.onCreate(savedInstanceState, persistentState)
    }
}

使用 fat-aar 编译 aar

如果你的 flutter 引入第三方的一些项目就需要使用 fat-aar。 但是和上面的思路也很类似,都是添加 flutter.so 和 flutter_embedding 的依赖,不同的是 fat-aar 可以将上面的两个文件直接合并到 aar 中。

接入 fat-arr

可以直接参考 fat-arr 的文档。 首先在 .android/build.gradle 中添加:

 dependencies {
        ...
        classpath 'com.kezong:fat-aar:1.2.12'
    }

然后在 .android/Flutter/build.gradle 中添加 plugin 和依赖:

dependencies {
    testImplementation 'junit:junit:4.12'
  
    // 添加 flutter_embedding.jar debug
    embed "io.flutter:flutter_embedding_debug:1.0.0-eed171ff3538aa44f061f3768eec3a5908e8e852"
    // 添加 flutter_embedding.jar release
    embed "io.flutter:flutter_embedding_release:1.0.0-e1e6ced81d029258d449bdec2ba3cddca9c2ca0c"
    // 添加各个 cpu 版本 flutter.so
    embed "io.flutter:arm64_v8a_debug:1.0.0-eed171ff3538aa44f061f3768eec3a5908e8e852"
    embed "io.flutter:armeabi_v7a_debug:1.0.0-eed171ff3538aa44f061f3768eec3a5908e8e852"
    embed "io.flutter:x86_64_debug:1.0.0-eed171ff3538aa44f061f3768eec3a5908e8e852"
    embed "io.flutter:x86_debug:1.0.0-eed171ff3538aa44f061f3768eec3a5908e8e852"

然后执行 flutter build aar 或者 flutter build aar --debug 打出 aar 文件之后直接拷贝到 native 项目中的 lib 下使用就可以了。