Flutter入門進(jìn)階之旅(十八)Flutter項(xiàng)目打包成aar集成到原生Android項(xiàng)目

前言

在前面的章節(jié)學(xué)習(xí)中我們已經(jīng)掌握了從最基本的hello flutter到各種基本W(wǎng)idget、各種布局的使用再到多頁(yè)面切換路由的使用還有各種炫酷的提示跟dialog,還有關(guān)于網(wǎng)絡(luò)請(qǐng)求庫(kù)Dio的使用,至此我們完全可以使用flutter去開發(fā)一款獨(dú)立可運(yùn)行的app了,但是基于現(xiàn)階段flutter技術(shù)棧還不是太成熟,純flutter項(xiàng)目上線風(fēng)險(xiǎn)還是比較大,所以跨平臺(tái)的混合開發(fā)模式自然還是現(xiàn)階段嘗試flutter的主流方式,今天的分享我就跟大家一塊把我們寫好的flutter項(xiàng)目打包成aar文件嵌入到現(xiàn)有的Android項(xiàng)目中去。

課程目標(biāo)

  • 掌握f(shuō)lutter打包成aar的整體流程
  • 利用fat-aar把flutter項(xiàng)目中的三方依賴打入aar資源包中

項(xiàng)目準(zhǔn)備:

flutter端項(xiàng)目我采用的是本專欄的實(shí)例代碼項(xiàng)目:https://github.com/xiedong11/flutter_app,Android端原生項(xiàng)目為新建的一個(gè)hello world項(xiàng)目,flutter端的相關(guān)配置我會(huì)上傳到github倉(cāng)庫(kù)中,原生Android項(xiàng)目比較簡(jiǎn)單,我只在本博客中貼出部分關(guān)鍵代碼

1.flutter項(xiàng)目打包成aar

flutter端項(xiàng)目工程目錄

Flutter端項(xiàng)目工程目錄

上面截圖的flutter工程需要經(jīng)過(guò)我們的改造才能作為一個(gè)aar的形式存在,要被打包成aar的flutter端的項(xiàng)目是作為一個(gè)獨(dú)立的module運(yùn)行在宿主app(原生Android)中,所以我們需要修改兩個(gè)地方,讓我們打包出來(lái)的產(chǎn)物變成aar而不是獨(dú)立運(yùn)行的apk。

1.1修改Android下的 build.gradle

// 1. 生成aar產(chǎn)物,需要把`application`改為`library`
apply plugin: 'com.android.library'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

android {
    compileSdkVersion 28

    lintOptions {
        disable 'InvalidPackage'
    }

    defaultConfig {
        // 2. flutter 作為寄存于其他app中的產(chǎn)物,所以不應(yīng)該存在applicationId,所以注釋掉該行.
        //applicationId "com.zhuandian.flutterapp"
        minSdkVersion 16
        targetSdkVersion 28
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            // TODO: Add your own signing config for the release build.
            // Signing with the debug keys for now, so `flutter run --release` works.
            signingConfig signingConfigs.debug
        }
    }
}
1. 2 修改Androidmanifest.xml文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.zhuandian.flutterapp">

    <uses-permission android:name="android.permission.INTERNET" />
   
    <!--1.項(xiàng)目作為子項(xiàng)目寄存于原生app中,不需要icon、label等屬性,這里直接省去各種配置即可-->
    <application>
        <!--android:name="io.flutter.app.FlutterApplication"-->
        <!--android:icon="@mipmap/ic_launcher"-->
        <!--android:label="flutter_app">-->
        <activity
            android:name=".MainActivity"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
            android:hardwareAccelerated="true"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:windowSoftInputMode="adjustResize">


            <!--2.項(xiàng)目作為子項(xiàng)目寄存于原生app中,入口acitvity不需要配置LAUNCHER,不然應(yīng)用集成到宿主app中,啟動(dòng)會(huì)在桌面上生成兩個(gè)應(yīng)用圖標(biāo)-->
           
            <!--<meta-data-->
                <!--android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"-->
                <!--android:value="true" />-->

            <!--<intent-filter>-->
                <!--<action android:name="android.intent.action.MAIN" />-->

                <!--<category android:name="android.intent.category.LAUNCHER" />-->
            <!--</intent-filter>-->
        </activity>
        <activity android:name=".SecondActivity"></activity>
    </application>

</manifest>

需要修改的地方,我都在源碼里留注釋了,這里就不展開贅述了,下面我們來(lái)通過(guò)gradle獲得編譯好的aar產(chǎn)物

因?yàn)樵赽uild.gradle 中,我們把apply plugin: 'com.android.application'修改成了,apply plugin: 'com.android.library'
所以,現(xiàn)在通過(guò)Terminal中我執(zhí)行gradlew assembleRelease編譯出的產(chǎn)物會(huì)有原來(lái)的apk變成aar文件,文件輸出目錄為項(xiàng)目根目錄下的/bulid/app/outputs/aar
如下圖所示:

在這里插入圖片描述

1.3 Android端項(xiàng)目配置接入aar依賴

1.3.1 新建原生Android項(xiàng)目,我上述打包產(chǎn)出的aar文件作為依賴放入libs文件夾


在這里插入圖片描述

1.3.2 修改dependencies節(jié)點(diǎn)下的fileTree依賴配置,支持引入aar依賴支持

implementation fileTree(dir: 'libs', include: ['*.jar','*.aar'])
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar','*.aar'])
    ...
}

1.3.3 在原生Android項(xiàng)目中寫一個(gè)簡(jiǎn)單的按鈕測(cè)試flutter項(xiàng)目

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        //初始化flutter運(yùn)行環(huán)境
        FlutterMain.startInitialization(this)
        tv_test_aar.setOnClickListener {
            startActivity(Intent(this, com.zhuandian.flutterapp.MainActivity::class.java))
        }
    }
}

至此,把flutter項(xiàng)目打包成aar導(dǎo)入到原生Android項(xiàng)目中的所有工程配置已經(jīng)結(jié)束了,讀者可以測(cè)試上上述整個(gè)過(guò)程;但有時(shí)候我們的flutter項(xiàng)目并不是單純的flutter官方代碼,開發(fā)過(guò)程中少不了引入一些三方依賴,像上節(jié)課我們講到的Dio網(wǎng)絡(luò)請(qǐng)求庫(kù),或者是通過(guò)pubspec.yaml引入的其他開源工具類,這種情況下,通過(guò)上邊的配置方式,你會(huì)發(fā)現(xiàn)第三方的依賴代碼是打不進(jìn)aar包里的,下面我們就講解一下借助fat-aar的形式把三方依賴代碼打入aar包中去

2.flutter項(xiàng)目中存在三方依賴

通過(guò)上邊的配置,我們只能把純flutter項(xiàng)目打包成aar文件,換句話說(shuō),如果我們的flutter項(xiàng)目存在三方依賴是不能正常打包進(jìn)flutter產(chǎn)物里的,這個(gè)時(shí)候我們就需要通過(guò)在Android原生項(xiàng)目中引入fat-aar配置,確保把flutter項(xiàng)目中的三方依賴正常打包進(jìn)去flutter產(chǎn)物中去。

2.1修改項(xiàng)目工程目錄的build.gradle文件,引入fat-aar支持

buildscript {
    repositories {
        google()
        jcenter()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:3.4.1'
        //引入fat-aar支持
        classpath 'com.kezong:fat-aar:1.1.7'
    }
}

2.2 在上邊第一部分配置app文件下build.gradle基礎(chǔ)上,增加fat-aar相關(guān)配置,這里為了切換aar library運(yùn)行環(huán)境,我引入isAarLibrary標(biāo)志位作為切換環(huán)境開關(guān),方便工程配置,具體代碼如下:

//是否作為依賴
boolean isAarLibrary = true


if (isAarLibrary) {
    apply plugin: 'com.android.library'
} else {
    apply plugin: 'com.android.application'
}

apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

if (isAarLibrary) {
    //引入fat-aar
    apply plugin: 'com.kezong.fat-aar'
}

android {
    compileSdkVersion 28

    lintOptions {
        disable 'InvalidPackage'
    }

    defaultConfig {
        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
        if (!isAarLibrary) {
            applicationId "com.zhuandian.flutterapp"
        }

        minSdkVersion 16
        targetSdkVersion 28
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            // TODO: Add your own signing config for the release build.
            // Signing with the debug keys for now, so `flutter run --release` works.
            signingConfig signingConfigs.debug
        }
    }
}

flutter {
    source '../..'
}

dependencies {
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:runner:1.1.0'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
    implementation 'androidx.appcompat:appcompat:1.0.0'

    if (isAarLibrary) {
        //TODO 添加fat-aar處理flutter打包成aar中三方依賴
        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')
        }
    }

}


2.3 AndroidManifest.xml清單文件中不需要增加額外配置,原生Android端喚起flutter項(xiàng)目aar包的方式也不需要修改,整個(gè)引入fat-aar的過(guò)程只是為了確保能把flutter項(xiàng)目中的三方依賴代碼打入到flutter產(chǎn)物中去,所以關(guān)于flutter打包成aar的操作跟第一步保持一致就行,第二步的配置,只是為了確保flutter項(xiàng)目中的三方依賴能正常打包進(jìn)flutter產(chǎn)物中去

效果圖是我把本專欄的相關(guān)代碼作為一個(gè)aar集成到一個(gè)新建的原生Android項(xiàng)目中,效果圖如下:


在這里插入圖片描述

項(xiàng)目的完整代碼配置在https://github.com/xiedong11/flutter_app 中,讀者可以參考具體配置細(xì)節(jié),筆者在寫本篇博文打包aar時(shí)的flutter 環(huán)境stable版本為 flutter v1.9.1,讀者盡量用官方穩(wěn)定版的代碼做測(cè)試。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,401評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,011評(píng)論 3 413
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,263評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,543評(píng)論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,323評(píng)論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,874評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,968評(píng)論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,095評(píng)論 0 286
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,605評(píng)論 1 331
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,551評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,720評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,242評(píng)論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 43,961評(píng)論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,358評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,612評(píng)論 1 280
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,330評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,690評(píng)論 2 370

推薦閱讀更多精彩內(nèi)容