flutter android动态化原理篇

基于flutter1.5.4版本

android动态化思路简介:

目前flutter在android的动态化相对简单,无非是将一个apk作为基线文件,然后再生成一个apk并与基线文件bsdiff40查分算法,生成一个.zip文件作为patch包。此时我们将patch包放于服务器,并由客户端拉取,客户端拿到patch包再做一次bsdiff40的合成,最终达到动态化的目的。

android动态化源码解析:

1、android工程配置

目的:需要告知flutterSDK我们需要动态化,以及动态化的方式。一共有三个配置,具体如下:

  • 1、DynamicPatching :允许flutter动态化

    

  • 2、PatchDownloadMode :下载patch的时机

// 可选:PatchDownloadMode = ON_RESTART(0,表示冷启)、ON_RESUME(1,表示热启)、默认为ON_RESTART 
    

  • 3、PatchInstallMode :patch的生效时机

// 可选:PatchInstallMode = ON_NEXT_RESTART(0,表示下次)、IMMEDIATE(1,表示立刻)、默认为ON_NEXT_RESTART 
    

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 android动态化原理篇_第1张图片
image.png

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文件夹中。

  • 为什么文件名为.baselineflutter_toolsbuild_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目录下面:

flutter android动态化原理篇_第2张图片
image.png

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源码解读、技术点使用、平台化落地相关的干货,也是希望大家能把问题抛出来,让我也能研究一下,也希望能互相帮助。

flutter android动态化原理篇_第3张图片
WechatIMG10.jpeg

你可能感兴趣的:(flutter android动态化原理篇)