flutter android动态化原理篇
基于flutter1.5.4版本
android动态化思路简介:
目前flutter在android的动态化相对简单,无非是将一个apk
作为基线文件
,然后再生成一个apk
并与基线文件
做bsdiff40
查分算法,生成一个.zip
文件作为patch包
。此时我们将patch包
放于服务器,并由客户端拉取,客户端拿到patch包
再做一次bsdiff40
的合成,最终达到动态化的目的。
android动态化源码解析:
1、android工程配置
目的:需要告知flutterSDK我们需要动态化,以及动态化的方式。一共有三个配置,具体如下:
- 1、DynamicPatching :允许flutter动态化
<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下面,否则会导致无法签名
//app中加入该buildType
dynamicRelease{
initWith release
}
然后执行:
flutter build apk --release --dynamic
中途可能出现因为java
版本问题导致失败,这里是因为flutter.gradle
中使用java 1.8
,解决方案如下:
//在defaultConfig {}中添加
jackOptions{
enabled = true
}
不出问题的话,基线文件生成成功,在build/app/outputs/apk
下面,如下:
flutter命令行生成
apk
,经过debug发现,真正的执行命令是gradlew
,上面的flutter build apk --release --dynamic
最终执行为:
/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的目录下面创建.baseline
文件夹,将app-dynamicRelease.apk
重命名为1.apk
放入.baseline
文件夹中。
- 为什么文件名为
.baseline
:flutter_tools
中build_apk.dart
文件的addDynamicBaselineFlags
方法定义的,可以按需求自我修改文件名及路径。 - 为什么重命名为
1.apk
:代表基线包的版本
3、根据基线包生成patch
文件:
flutter build apk --release --dynamic --patch
这条命令最终执行的依然是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
中我们得到答案:
和动态化的代码在如下三个文件:
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、总结:
目前的android动态化方案做的很糙:
- patch缺少签名带来安全隐患
- 版本控制
- 下载patch的方案
- 无法自定义更新方案、生效时机
功能虽然很糙,但是公司可以根据自己需求开始自定义。
flutter的广大爱好者们,我在微信创建了一个公众号,搜索flutter 干货
、或微信扫一扫下面的二维码
关注一下吧,平时会发一些flutter源码解读、技术点使用、平台化落地相关的干货,也是希望大家能把问题抛出来,让我也能研究一下,也希望能互相帮助。