Android Flutter混合開發問題總結(二)

JavaNoober發表於2019-11-05

Android Flutter混合開發問題總結
Android Flutter混合開發問題總結(二)

之前介紹過一些Android Flutter混合開發的注意點以及一些基本知識, 接下來介紹一下實際開發過程中,目前一定會遇到的兩個坑。
在Flutter開發過程中,如果是以module的形式進行依賴,是無法進行android原生部分的除錯的,無法進行attach debug to android process操作; 為了解決這一問題,我們需要考慮使用aar的方式,以library的形式進行依賴,但是講flutter打包成library的時候,如果使用第三方框架,會導致第三方框架無法打包進入aar,因此我們需要來解決這一問題。

混合開發的依賴方式

打包成獨立aar

打包aar很簡單,進入flutter工程,然後進入.android目錄,輸入指令: 打debug的aar包:

./gradlew flutter:assembleDebug
複製程式碼

打debug的release包:

./gradlew flutter:assembleRelease
複製程式碼

打好的包在 flutter module/.android/Flutter/build/outputs/aar

aar的包打好後可以直接複製到Android工程去依賴即可。
但是如果使用第三方框架會導致第三方框架的無法打入aar,我們可以使用fat-aar-android來解決這一問題:
在flutter工程的build.gradle加入:

    classpath 'com.kezong:fat-aar:1.2.7'
複製程式碼

在Flutter的build.gradle加入如下配置:

apply plugin: 'com.kezong.fat-aar'

dependencies {

    def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
    def plugins = new Properties()
    def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
    if (pluginsFile.exists()) {
        pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
    }
    plugins.each { name, _ ->
        println name
        embed project(path: ":$name", configuration: 'default')
    }
}
複製程式碼

在Android工程下的settings.gradle中加入如下配置:

def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()

def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists()) {
    pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
}

plugins.each { name, path ->
    def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
    include ":$name"
    project(":$name").projectDir = pluginDirectory
}
複製程式碼

這樣打包出來的aar就包含了第三方的aar。

Flutter工程作為module依賴

以module方式依賴之前介紹過,可以直接檢視文章Android Flutter混合開發問題總結

混合開發的除錯填坑

Flutter android混合工程的依賴方式寫到這裡,但是實際開發中會有一個無法避免的坑,就是flutter工程無法除錯android程式碼,如下圖所示例:
原生Android專案:

image

Flutter專案:

image

為了解決這一問題,我想到的解決方法就輸使用aar模式來進行原生Android的開發,用依賴module的方式來進行flutter工程的開發。

開發模式引數配置

我們可以通過一個變數來控制當前開發環境是Android還是Flutter,效果如下:

image

通過gradle.properties的一個值來控制進行flutter開發還是Android部分開發。

具體操作如下:
1、講Flutter部分打包成aar放入libs資料夾下
2、Android工程的project的build.gradle加入如下依賴:

    classpath 'com.kezong:fat-aar:1.2.7'
複製程式碼

3、app的build.gradle加入如下配置:

dependencies{
    def properties = new Properties()
    def pluginsFile = new File("${rootDir.getAbsolutePath()}/gradle.properties")
    if (pluginsFile.exists()) {
        pluginsFile.withReader('UTF-8') { reader -> properties.load(reader) }
    }
    def isFlutterDebug = properties.getProperty('isFlutterDebug').toBoolean()
    if (isFlutterDebug) {
        implementation project(':flutter')
    } else {
        implementation files('libs/flutter-release.aar')
//        implementation files('libs/flutter-debug.aar')
    }
}
複製程式碼

4、gradle.properties加入如下引數來控制除錯方式:

## 是否線上除錯flutter程式碼
isFlutterDebug=false
複製程式碼

5、settings.gradle修改為如下配置:
xxx_flutter為自己flutter工程的名字。

def properties = new Properties()
def rootProjectFile = new File(settingsDir.getPath()).getAbsolutePath()
def propertiesFile = new File("${rootProjectFile}/gradle.properties")
if (propertiesFile.exists()) {
    propertiesFile.withReader('UTF-8') { reader -> properties.load(reader) }
}
def isFlutterDebug = properties.getProperty("isFlutterDebug").toBoolean()
if (isFlutterDebug) {
    setBinding(new Binding([gradle: this]))
    evaluate(new File(settingsDir.parentFile,
            'xxx_flutter/.android/include_flutter.groovy'
    ))
    include ':xxx_flutter'
    project(':xxx_flutter').projectDir = new File('../xxx_flutter')
}else {
    def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()

    def plugins = new Properties()
    def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
    if (pluginsFile.exists()) {
        pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
    }

    plugins.each { name, path ->
        def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
        include ":$name"
        project(":$name").projectDir = pluginDirectory
    }
}
複製程式碼

這樣配置完成後就可以由自己來控制到底進行Flutter開發還是Android開發。

總結

Flutter開發的坑還有不少,以此記錄方便大家來解決問題。

相關文章