Flutter接入現有Android工程踩坑之旅

鵾鵬發表於2019-03-04

把Flutter作為一個模組接入到現有的Android工程,Flutter有官方推薦方案 Add Flutter to existing apps,通過這樣的工程配置,可以在debug支援HotReload,也可以輸出Release包供釋出。不過在使用過程中有一些需要調整的地方,特此記錄希望對大家能有借鑑意義。

工程目錄調整

flutter create -t module

命令會建立一個支援Flutter的Android Library,其中Android Library的目錄位於Flutter工程的隱藏目錄 .android/flutter 中, 一般情況下,我們會把Flutter程式碼和Android程式碼放在兩個git倉庫,通過submodule的方式進行依賴,可以把這個Library的程式碼copy到你的工程目錄下,同時修改flutter的資源目錄到你自己的相對路徑下:

flutter {
source ` your own flutter project directory `
}

另外需要Copy include_flutter.groovy 這個檔案到你的工程目錄下,修改相應的目錄新增對於Library的依賴。

armeabi支援

Flutter官方只提供了四種CPU架構的SO庫:armeabi-v7a、arm64-v8a、x86和x86-64。但是目前我們對接的兩個專案組分別是隻支援armeabi和只支援armeabi-v7a,所以需要對官方的jar包進行改造。官方SDK提供的jar包路徑在 $flutterRoot/bin/cache/artifacts/engine中,複製這幾個目錄下的armeabi-v7a中的so到armeabi路徑下:

  • android-arm
  • android-arm-dynamic-profile
  • android-arm-dynamic-release
  • android-arm-profile
  • android-arm-release

可以通過如下指令碼實現:

unzip flutter.jar lib/armeabi-v7a/libflutter.so
mkdir lib/armeabi
cp lib/armeabi-v7a/libflutter.so lib/armeabi/libflutter.so
zip flutter.jar lib/armeabi-v7a/libflutter.so lib/armeabi/libflutter.so
複製程式碼

Library中的build.gradle中有一段是通過本地的一個gradle檔案新增flutter.jar的依賴:

apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
複製程式碼

我們把flutter.gradle檔案以及我們剛才處理的flutter.jar檔案Copy到自己的工程路徑下,我自己的工程路徑配置如下:

project
│   app
└───flutter
│   │   build.gradle
│   │   flutter.gradle
│   │   include_flutter.groovy
│   └───flutter-jars
│       └───android-arm
|              |   flutter.jar
│       └───android-arm-dynamic-profile
|              |   flutter.jar
│       └───android-arm-dynamic-release
|              |   flutter.jar
|       └───android-arm-profile
|              |   flutter.jar
|       └───aandroid-arm-release
|              |   flutter.jar
│   settings.gradle
複製程式碼

將flutter.gradle 中jar檔案的路徑改為本地工程:

debugFlutterJar = new File(`flutter-jars/debug/flutter.jar`)
profileFlutterJar = new File(`flutter-jars/profile/flutter.jar`)
releaseFlutterJar = new File(`flutter-jars/release/flutter.jar`)
dynamicProfileFlutterJar = new File(`flutter-jars/dynamicProfile/flutter.jar`)
dynamicReleaseFlutterJar = new File(`flutter-jars/dynamicRelease/flutter.jar`)
複製程式碼

這樣打出的AAR就能同時支援兩種架構。

打包AAR問題

按照上面的配置,可以在工程中打出支援Debug HotReload和Release的包,不過在輸出AAR給別的業務模組使用時會報一個崩潰:

must be able to initialize the ICU context.

這是Android Gradle Plugin 3.+ 版本的一個bug,它會丟棄flutter.jar 中的 /assets/flutter_shared/icudtl.dat檔案到AAR中,導致執行時找不到這個檔案崩潰,在2.+版本中發現沒有這個問題,所以需要使用Android Gradle Plugin 2.+版本,我這邊測試2.2.3版本是ok的。但是Android Gradle 2的版本有一個由來已久的問題就是Library不能獲取project一致 的BuildType,Library預設只發布Release的AAR。這是因為Android中預設指定了釋出type:

private String defaultPublishConfig = "release";
private boolean publishNonDefault = false;
複製程式碼

預設Release,而flutter.gradle中通過buildtype來確定flutter的buildmode,在Android Gradle Plugin 3.+版本中,這個buildtype的問題已經得到解決,這也可能是flutter選用3.+版本的一個原因。

如果避免2.+的buildtype問題呢,網上是有一些獲取project的buildtype配置給Library的方案,比如如何讓library的buildType型別跟app的buildType型別一致(自由定義library的buildType) ??。 我的實現方案是擯棄通過buildtype確定flutter的buildmode的方案,通過直接讀取本地local.properties中的引數來決定,這樣需要自己在本地手動的進行mode的切換,尤其是要注意上線的時候修改為Release模式。不過debug模式下頁面有明顯的debug標識,所以一般也不會出錯。將flutter.gradle 中原有的buildmodefor方法:

private static String buildModeFor(buildType) {
       if (buildType.name == "profile") {
           return "profile"
       } else if (buildType.name == "dynamicProfile") {
           return "dynamicProfile"
       } else if (buildType.name == "dynamicRelease") {
           return "dynamicRelease"
       } else if (buildType.debuggable) {
           return "debug"
       }
       return "release"
   }
複製程式碼

修改為:

private String buildModeFor(Project project) {
        return resolveProperty(project, `flutter.buildMode`, `release`)
    }
複製程式碼

這樣在local.properties 中就可以進行debug和Release的切換:

flutter.buildMode=release

flutter.buildMode=debug

切換mode的崩潰問題

在第一次配置好工程或者切換mode的過程中,可能會遇到以下的崩潰問題:

Check failed: vm. Must be able to initialize the VM.

主要是由於不同模式下的產物沒有清理使用了快取,解決辦法是刪除掉所有build檔案的內容再全量編譯一次就可以了。

總結

這是我在做flutter工程配置中遇到的一些坑,文風偏流水賬,請大家見諒,只希望能對大家有一些借鑑意義。另外,我們已經在專案的兩個模組中使用了flutter,開發效率確實能有很大提高,畢竟兩端只需要一個人開發就ok,而且UI小姐姐要求的頁面效果都能不折不扣的完成,上線之後目前還沒發現什麼問題。下一步需要做的是建立一個有效的監控體系,畢竟靠使用者反饋還是不可靠也是滯後的。相信Flutter的未來一定是光明的!

相關文章