Android 專案整合 Flutter

ooyao發表於2021-06-02

Flutter是谷歌的移動UI框架,可以快速在iOS和Android上構建高質量的原生使用者介面。 Flutter可以與現有的程式碼一起工作。在全世界,Flutter正在被越來越多的開發者和組織使用,並且Flutter是完全免費、開源的。

相信大家在 最開始學習 Flutter 時都是使用命令列或者 Android Studio 等整合開發環境建立的 Flutter 專案,自動生成的 Flutter 專案模板包含了 Flutter 程式碼、Android 程式碼、iOS程式碼,直接執行就行。

但是公司的專案都是分開管理的,例如 Android、iOS是兩個獨立的專案在 git 中管理,與 Flutter 的模板專案還是存在差別的。

Android 現有專案整合 Flutter 方案

在現有 Android 專案中整合 Flutter 官方給出兩種方案。

  1. 將 Flutter 打包成 AAR 包,然後在現有專案引入。
  2. 將 Flutter 原始碼視為 Gradle Module 引入現有專案。

1. 將 Flutter 打包成 AAR 包,然後在現有專案引入

使用 AAR 形式整合 Flutter 可以不用安裝 Flutter SDK。可以將 AAR 上傳到Maven 或 jcenter 倉庫(jcenter 即將停止服務,所以還是使用 maven 吧)。這樣應用起來更方便。如果程式碼更新比較頻繁使用 AAR 形式整合則需要經常構建、釋出,所以大家根據自己的專案及使用場景自行選擇整合方案。

如何生成 AAR 包

生成 AAR 包通常有兩種方式。

1. 使用 flutter 命令

假設構建一個 Flutter 模組 some/path/my_flutter,然後執行:

$ cd some/path/my_flutter
$ flutter build aar
複製程式碼

build-aar-instructions-59deccd46ba2e0b0552f4dfe7e195406395d24aa6ac03eb8ff4ec2c1ca182fd9.png

至此 flutter 命令會在本地建立一個 maven 倉庫,其目錄結構如下:

build/host/outputs/repo
└── com
    └── example
        └── my_flutter
            ├── flutter_release
            │   ├── 1.0
            │   │   ├── flutter_release-1.0.aar
            │   │   ├── flutter_release-1.0.aar.md5
            │   │   ├── flutter_release-1.0.aar.sha1
            │   │   ├── flutter_release-1.0.pom
            │   │   ├── flutter_release-1.0.pom.md5
            │   │   └── flutter_release-1.0.pom.sha1
            │   ├── maven-metadata.xml
            │   ├── maven-metadata.xml.md5
            │   └── maven-metadata.xml.sha1
            ├── flutter_profile
            │   ├── ...
            └── flutter_debug
                └── ...
複製程式碼

如果要引用本地倉庫中的 aar 包則需要在宿主應用的 build.gradle 中做如下配置即可:

android {
  // ...
}

repositories {
  maven {
    url 'some/path/my_flutter/build/host/outputs/repo'
    // This is relative to the location of the build.gradle file
    // if using a relative path.
  }
  maven {
    url 'https://storage.googleapis.com/download.flutter.io'
  }
}

dependencies {
  // ...
  debugImplementation 'com.example.flutter_module:flutter_debug:1.0'
  profileImplementation 'com.example.flutter_module:flutter_profile:1.0'
  releaseImplementation 'com.example.flutter_module:flutter_release:1.0'
}
複製程式碼

2. 使用 Android Studio

第二種生成 AAR 包的方式就是使用 Android Studio,這用方式比較簡單,依次選擇 AS > Build > Flutter > Build AAR 然後等著就行了。剩下的步驟和使用 flutter 命令一樣。

image.png

2. 將 Flutter 原始碼視為 Gradle Module 引入現有專案。

這種方式是推薦的方式,因為在團隊協作過程中這種方式更方便,相對於 AAR 方式可以省掉每次單獨構建 AAR 包的步驟。可以一鍵構建 Android、Flutter 程式碼。

使用此種整合方式可以按照如下步驟進行。

1. 組織目錄結構

因為絕大多數的現有 Android、iOS 專案都是作為獨立專案使用 svn 或 git 進行版本管理的(這裡以 git 為例)。在不改變原有專案管理方式的前提下整合 Flutter 需要將 Flutter 的程式碼作為獨立的工程使用 git 進行管理,並在 Android 專案中以 module 的形式進行依賴。其目錄結構如下。

workspace
├── android_project
└── flutter_module
複製程式碼

android_project是我們現有的 Android 工程程式碼目錄。flutter_module是我們新增的 fluuter 模組程式碼目錄,將兩個工程放到同一目錄下。為了統一配置,建議必須按照這個目錄結構進行管理兩個工程的程式碼。

注意:flutter_module是 module,不是 project 型別,在 Android Studio 中一定要選擇 File > New > New Module > Flutter Module,不要選擇File > New > New Flutter Project

建立 flutter module 也可以使用如下命令:

$ flutter create -t module name_of_module
複製程式碼

2. 配置 settings.gradle

在 Android 工程的 settings.gradle做如下修改

// Include the host app project.
include ':app'                                    // assumed existing content
setBinding(new Binding([gradle: this]))                                // new
evaluate(new File(                                                     // new
  settingsDir.parentFile,                                              // new
  'my_flutter/.android/include_flutter.groovy'                         // new
))                                                                     // new
複製程式碼

3. 依賴 flutter 模組

在 Android 模組的 build.gradle中加入如下依賴。

dependencies {
  implementation project(':flutter')
}
複製程式碼

然後單擊Sync Now同步 Gradle 即可。

完成這一步就可以在 Android 原生程式碼中使用 flutter 模組了。

4. 配置 AndroidManifest.xml

啟動 flutter 模組需要使用FlutterActivity,所以需要在 AndroidManifest.xml 中註冊一下。

<activity
  android:name="io.flutter.embedding.android.FlutterActivity"
  android:theme="@style/LaunchTheme"
  android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
  android:hardwareAccelerated="true"
  android:windowSoftInputMode="adjustResize"/>
複製程式碼

5. 啟動 Flutter 模組

在任意地方執行如下程式碼即可啟動 Flutter 模組。

startActivity(FlutterActivity
                .withNewEngine()
                .initialRoute("splashRoute") // 啟動指定 Flutter page,沒有可以省略
                .build(requireContext()))
複製程式碼

注意事項

1. abiFilters 配置

因為 Flutter 目前僅支援x86_64、armeabi-v7a和arm64-v8a架構. 所以為了避免執行時崩潰建議在 build.gradle中做如下配置。

android {
  //...
  defaultConfig {
    ndk {
      // Filter for architectures supported by Flutter.
      abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86_64'
    }
  }
}
複製程式碼

2. Java 8 要求

因為Flutter Android 引擎需要使用 Java 8。所以需要在宿主 Android 工程的 build.gradle中做如下配置。

android {
  //...
  compileOptions {
    sourceCompatibility 1.8
    targetCompatibility 1.8
  }
}
複製程式碼

3. storage.googleapis.com 國內訪問不了?

  1. “學會科學上網”
  2. 使用國內映象

4. Android 模組改過名字?

Android Studio 預設建立的模組名稱是app。在 settings.gradle中有如下配置。

include ':app'
複製程式碼

只有在這裡 include 的模組才能通過 gradle 進行構建。

模組的名字是可以修改的,如果你改過 app 模組的名字,則在整合 flutter 時會報錯。

java.lang.AssertionError: Project :app doesn't exist. To custom the host app project name, set org.gradle.project.flutter.hostAppProjectName=<project-name> in gradle.properties.. Expression: (appProject != null). Values: appProject = null

因為 flutter 預設會認為名為“app”的模組依賴自己,如果你修改過名字則會報錯,此時只需要根據報錯資訊提示在宿主工程的gradle.properties中加入如下配置即可。

flutter.hostAppProjectName = your_module_name
複製程式碼

your_module_name修改成你真是的模組名稱即可。

5. flutter module 不支援自定義 buildType?

如果 app module 的 buildType 中除了releasedebug之外有自定義的 variant那麼在打包的時候可能會報錯,因為在 flutter module 並沒有你定義的 variant 型別,但是releasedebug這兩種 variant 是所有 module 都包含的。所以可以在 app module 的 buildType 中的自定義 buildType 中增加如下配置。

matchingFallbacks = ['debug', 'release']
複製程式碼

例如:

   buildTypes {
        release {...}

        debug {...}

        beta {
            ...
            matchingFallbacks = ['debug', 'release']
        }
    }
複製程式碼

參考

Integrate a Flutter module into your Android project

相關文章