基于flutter1.5.4版本
android動態(tài)化思路簡介:
目前flutter在android的動態(tài)化相對簡單恨胚,無非是將一個apk
作為基線文件
撞羽,然后再生成一個apk
并與基線文件
做bsdiff40
查分算法估脆,生成一個.zip
文件作為patch包
伺糠。此時我們將patch包
放于服務(wù)器枕荞,并由客戶端拉取造烁,客戶端拿到patch包
再做一次bsdiff40
的合成,最終達到動態(tài)化的目的汽摹。
android動態(tài)化源碼解析:
1李丰、android工程配置
目的:需要告知flutterSDK我們需要動態(tài)化,以及動態(tài)化的方式逼泣。一共有三個配置趴泌,具體如下:
- 1、DynamicPatching :允許flutter動態(tài)化
<application>
<meta-data
android:name="DynamicPatching"
android:value="true" />
</application>
- 2拉庶、PatchDownloadMode :下載
patch
的時機
<application>
// 可選:PatchDownloadMode = ON_RESTART(0,表示冷啟)嗜憔、ON_RESUME(1,表示熱啟)氏仗、默認為ON_RESTART
<meta-data
android:name="PatchDownloadMode"
android:value=0|1 />
</application>
- 3痹筛、PatchInstallMode :
patch
的生效時機
<application>
// 可選:PatchInstallMode = ON_NEXT_RESTART(0,表示下次)、IMMEDIATE(1,表示立刻)帚稠、默認為ON_NEXT_RESTART
<meta-data
android:name="PatchInstallMode"
android:value=0|1 />
</application>
2谣旁、生成patch
文件
1、首先生成基線文件
首先需要添加如下配置:需要注意的是dynamicRelease需要寫在release下面滋早,否則會導(dǎo)致無法簽名
//app中加入該buildType
dynamicRelease{
initWith release
}
然后執(zhí)行:
flutter build apk --release --dynamic
中途可能出現(xiàn)因為java
版本問題導(dǎo)致失敗榄审,這里是因為flutter.gradle
中使用java 1.8
,解決方案如下:
//在defaultConfig {}中添加
jackOptions{
enabled = true
}
不出問題的話杆麸,基線文件生成成功搁进,在build/app/outputs/apk
下面,如下:
flutter命令行生成
apk
昔头,經(jīng)過debug發(fā)現(xiàn)饼问,真正的執(zhí)行命令是gradlew
,上面的flutter build apk --release --dynamic
最終執(zhí)行為:
/Users/zhuyaning/Desktop/flutterDemo/abd/android/gradlew -q -Ptarget=lib/main.dart -Ptrack-widget-creation=false -Pcompilation-trace-file=compilation.txt -Ptarget-platform=android-arm assembleDynamicRelease
assembleDynamicRelease
也反證了剛剛為什么要在build.gradle
添加dynamicRelease
。
2揭斧、基線文件放置在指定目錄下面莱革,詳情如下:
在flutter主工程目錄下面,也就是同時包含ios和android的目錄下面創(chuàng)建.baseline
文件夾讹开,將app-dynamicRelease.apk
重命名為1.apk
放入.baseline
文件夾中盅视。
- 為什么文件名為
.baseline
:flutter_tools
中build_apk.dart
文件的addDynamicBaselineFlags
方法定義的,可以按需求自我修改文件名及路徑旦万。 - 為什么重命名為
1.apk
:代表基線包的版本
3闹击、根據(jù)基線包生成patch
文件:
flutter build apk --release --dynamic --patch
這條命令最終執(zhí)行的依然是gradlew
:
/Users/zhuyaning/Desktop/flutterDemo/abd/android/gradlew -q -Ptarget=lib/main.dart -Ptrack-widget-creation=false -Pcompilation-trace-file=compilation.txt -Ppatch=true -Ptarget-platform=android-arm assembleDynamicRelease
注:此命令依然是生成一個新的apk
,然后與1.apk
做的bsdiff
算法,源碼在flutter_tool
工程下搜索_buildGradleProjectV2
成艘,所以我們可以安裝自己公司的算法自己修改此處代碼赏半。
最終patch
被輸出到Project/public
目錄下面:
3、patch的使用:
我們得到patch
生成之后淆两,客戶端是如何使用的断箫?在flutter engine
中我們得到答案:
和動態(tài)化的代碼在如下三個文件:
FlutterMain.java
ResourceExtractor.java
ResourceUpdater.java
入口在FlutterMain.startInitialization(context)
中:
if (metaData != null && metaData.getBoolean("DynamicPatching")) {
sResourceUpdater = new ResourceUpdater(context);
// Also checking for ON_RESUME here since it's more efficient than waiting for actual
// onResume. Even though actual onResume is imminent when the app has just restarted,
// it's better to start downloading now, in parallel with the rest of initialization,
// and avoid a second application restart a bit later when actual onResume happens.
if (sResourceUpdater.getDownloadMode() == ResourceUpdater.DownloadMode.ON_RESTART ||
sResourceUpdater.getDownloadMode() == ResourceUpdater.DownloadMode.ON_RESUME) {
sResourceUpdater.startUpdateDownloadOnce();
if (sResourceUpdater.getInstallMode() == ResourceUpdater.InstallMode.IMMEDIATE) {
sResourceUpdater.waitForDownloadCompletion();
}
}
整體替換及更新思路,大家看完這三個文件就會明白琼腔。
4、總結(jié):
目前的android動態(tài)化方案做的很糙:
- patch缺少簽名帶來安全隱患
- 版本控制
- 下載patch的方案
- 無法自定義更新方案踱葛、生效時機
功能雖然很糙丹莲,但是公司可以根據(jù)自己需求開始自定義。
flutter的廣大愛好者們尸诽,我在微信創(chuàng)建了一個公眾號甥材,搜索flutter 干貨
、或微信掃一掃下面的二維碼
關(guān)注一下吧性含,平時會發(fā)一些flutter源碼解讀洲赵、技術(shù)點使用、平臺化落地相關(guān)的干貨,也是希望大家能把問題拋出來叠萍,讓我也能研究一下芝发,也希望能互相幫助。