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

TravelingLight_發表於2020-05-21

Flutter 以 aar 的方式接入 native 專案的優點是侵入性低,不影響業務組其他成員。 最開始的時候在網上看了一下關於 aar 匯入 android 的部落格感覺稍亂,所以在此整理一下,防止大家浪費時間重複趟坑。

Flutter 編譯產物

首先需要先了解一下 flutter 的編譯產物有哪些,然後才能更好地理解如何編譯 aar。

以一個嵌入 flutter aar 的 release 版本為例看一下里面的內容:

Flutter: 以 aar 形式嵌入 android 中的方案和原理
可以很明顯的看到三個和 Flutter 先關的檔案:

  • libflutter.so: flutter engin
  • libapp.so:dart 原始碼相關
  • flutter_assets:flutter 資原始檔

其實還有一個檔案:

  • classes.dex: native 程式碼,比如 java 我們使用 dex2jar 工具看一下 classes.dex 的內容:

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

可以看到裡面有關於 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 工程:

Flutter: 以 aar 形式嵌入 android 中的方案和原理
這個工程下會包含一個 .android moudle,可以讓這個專案編譯成 apk 。

2.build aar
flutter build aar
複製程式碼

然後會看到這樣一行輸出提示:

✓ Built build/host/outputs/repo.
複製程式碼

意思是建立了一個上面的資料夾,我們到根目錄下這個資料夾就可以看到裡面是編譯好的 aar:

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

這個時候我們將這個 aar 匯入到 native 專案中會發現沒法使用,因為裡面根本沒有 flutter.so 和 flutter_embedding.jar,這個 aar 內容如下:

Flutter: 以 aar 形式嵌入 android 中的方案和原理
可以看到只有 資原始檔和 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 倉庫:

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

我們來看一下這個 maven 倉庫的配置,也就是 flutter_release-1.0.pom:

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

這樣就湊齊了所有的編譯產物,那麼我們再新建一個 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 下使用就可以了。

相關文章