美文网首页
Flutter打包所遇到的问题

Flutter打包所遇到的问题

作者: ___刘辉良 | 来源:发表于2022-05-11 11:52 被阅读0次

    前言

    如果你也在使用Flutter进行APP开发的话,下面这篇文章可能对你有一些帮助。本文主要是针对Android的编译打包上面的优化。IOS可能也存在类似的问题,目前对IOS不是特别熟悉。

    0X01 Flutter多渠道

    首先,当我们的Flutter APP正式上架的过程中。需要对不同的渠道进行统计和一些特定的操作。在Android 原生叫做多渠道打包。可以借助gradle中的productFlavors来完成。 如果使用productFlavors就必须要求开发者了解gradle的知识,这样的话跨平台的意义可能就没有那么的大。出于这一点考虑。我们尝试着从Flutter的角度来处理这个问题。

    Flutter 1.17 的时候string新增了一个方法

    external const factory String.fromEnvironment(String name,  {String defaultValue = ""});
    

    这个方法,能够接受编译时的变量。 这样就让我们在编译时期给程序传递变量有了机会。

    案例实践

    这里举个例子。我们后台会对所有的请求进行渠道上的分析。分析出哪个应用市场的用户比较多。而区分应用市场的标识都会存在与一个变量channelName上。 这就要求,我们针对不同市场需要编译出不同的包。

    华为市场 channelName huawei

    小米市场 channelName. xiaomi.

    然后我们将编译出来的这个channelName 放到httphead中。这样后台就可以进行统计了。

    上述介绍了原理,这个贴一下代码。首先你需要定一个const常量用于你放在head里面

    /// 渠道信息
    const channelName =
        String.fromEnvironment("channelName", defaultValue: "huawei");
    

    这个常量会根据你编译配置的参数变化而变化。比如你定义的参数是oppo它就是变成oppo

    flutter build apk  --dart-define=channelName=oppo
    

    当你调用如上shell,就可以传递这个channelName传递到你程序中。而如果你需要打多个apk包的话。就可以重复更改这个channelName即可。 下文还会给出完整的打包脚本。

    0X02 Flutter包体积优化所带来的问题

    当我们的项目引入了ffmpng的时候。我们应用的包体积就开始猛增。打开Android StudioAPK进行查看的时候。发现Flutter将所有的架构的so文件都打包的apk中。 这样很明显是不明智的。 于是我们在网上找到了区分架构的打包脚本

     flutter build apk  --target-platform android-arm,android-arm64 --split-per-abi
    

    这样子我们就可以将so架构进行分类。当你上传对应的应用市场的时候。你会发现。你打出来的包的版本号并不受你的控制。(我们这里pubspec.yaml里面定义d的是1.0.4+5。得出来的结论版本信息并不是我们想要的) 。

    在解决问题之间。我们还是去查看了Flutter官方对版本号的定义 。

    每个应用默认的初始版本号是 1.0.0。若要更新它,请转到 pubspec.yaml 文件并更新以下内容:

    version: 1.0.0+1

    版本号由三个点分隔的数字组成,例如上面样例中的 1.0.0。然后是可选的构建号,例如上面样例中的 1,以 + 分隔。

    版本号与构建号都可以在 Flutter 打包时分别使用 --build-name--build-number 重新指定。

    在 Android 中,build-number 被用作 versionCodebuild-name 将作为 versionName 使用。更多信息请参考 Android 文档中的 为你的应用添加版本

    在更新完 pubspec 文件中的版本号之后,在项目根目录下运行 flutter pub get,或者使用 IDE 中的 Pub get 按钮。这将会更新 local.properties 文件

    中的 versionNameversionCode,之后它会在你构建 Flutter 应用的时候更新 build.gradle

    根据上述的文档。 我们得出了结论yaml里面的version会对versionNameversionCode造成影响。 versionName是截取yaml + 前面的字符串。而versionCode是截取yaml + 后面的字符串。这个结论在没有对so进行拆分是可靠的。但是对so拆分后就不可控了。于是我们尝试着从Flutter的打包脚本上查找原因。

    问题原因 ,流程梳理

    首先FlutterAndroid上的打包脚本是通过android目录下的app目录下的build.gradle里面的

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

    而这个flutter.gradle 文件是你安装flutter目录下的一个文件。然后我们查看代码,因为我们在使用过了split-per-abi后面出了问题。所以我们直接全局查找abi就看到了flutter.gradle有关这部的逻辑。

    // flutter.gradle 810行 
    def addFlutterDeps = { variant ->
                if (shouldSplitPerAbi()) {
                    variant.outputs.each { output ->
                        def abiVersionCode = ABI_VERSION.get(output.getFilter(OutputFile.ABI))
                        if (abiVersionCode != null) {
                            output.versionCodeOverride =
                                abiVersionCode * 1000 + variant.versionCode
                        }
                    }
                }
    

    可以看到,Flutter打包脚本里面会判断是否使用了split-per-abi命令。如果使用了split-per-abi的话。它就是用ABI_VERSION里面取一个版本。然后*1000在加上本身的版本号。为什么这样做呢? 官方解释

    默认情况下,当 Gradle 生成多个 APK 时,每个 APK 都有相同的版本信息,该信息在模块级 build.gradle 文件中指定。由于 Google Play 商店不允许同一个应用的多个 APK 全都具有相同的版本信息,因此在上传到 Play 商店之前,您需要确保每个 APK 都有自己唯一的 versionCode

    您可以配置模块级 build.gradle 文件以替换每个 APK 的 versionCode。通过创建一种映射关系来为您配置了多 APK 构建的每种 ABI 和密度分配一个唯一的数值,您可以将输出版本代码替换为一个将在 defaultConfigproductFlavors 代码块中定义的版本代码与分配给相应密度或 ABI 的数值组合在一起的值。

    在以下示例中,x86 ABI 的 APK 的 versionCode 将为 2004,x86_64 ABI 的 APK 的版本代码将为 3004。如果以较大的增量(如 1000)分配版本代码,那么当您以后需要更新应用时,就可以分配唯一的版本代码。例如,如果 defaultConfig.versionCode 在后续更新中迭代到 5,那么 Gradle 为 x86 APK 分配的 versionCode 将为 2005,为 x86_64 APK 分配的版本代码将为 3005。

    而这种版本控制。在我们国内市场似乎没有效果。目前上传腾讯应用市场。要求其版本号必须一致。所以我们将jenkins上的ABI_VERSION的对应版本改成一致。这样versionCode就可控制了。

      private static final Map ABI_VERSION = [
            (ARCH_ARM32)        : 3,
            (ARCH_ARM64)        : 3,
            (ARCH_X86)          : 3,
            (ARCH_X86_64)       : 3,
      ]
    

    0X03 Flutter打包签名的问题

    当我们使用build apk --release的时候。 有一些市场可以正常识别出签名信息。但是某些市场并没有办法识别出签名信息。于是我们重新按照官方文档进行证书的配置。

    1. 首先要一个证书文件。
    2. 然后要把证书文件里面的信息写到一个文件中,这个文件最好放在[project]/android/key.properties
    3. 最后把这个key.properties中的字段读出来。配置到signingConfigs里面

    这里只是介绍了大概。 具体如何配置可以查看 打包配置,在反复确认我们的配置并没出现问题。而且某些渠道也可以正常识别后。我们怀疑可能是市场的识别方式不同导致的。 所以我们打算对APK进行重新签名。签名相关

    apksigner sign --ks $keysFile --ks-pass pass:123456 --ks-pass pass:123456 $saveDir/$1/app-arm64-v8a-release.apk
    

    重新签名后。 我们就可以正常上传到应用市场了。

    0X04 Flutter 打包脚本

    当我们解决了上述所说的一些问题了。 我们尝试的编写一个脚本用来一键解决打包问问题。 具体脚本如下 Github

    ### 保存的路径
    saveDir="/Users/alex/Desktop/ee";
    ### 签名文件
    keysFile="/Users/alex/Documents/cc/flutter/dd/android/app/key/aa.jks"
    
    
    ### 如果文件夹不存在的话,创建
    createDirWhenNotFound(){
      dirname=$1
      if [ ! -d $dirname  ];then
        mkdir $dirname
        echo "创建文件夹:$dirname}"
      else
        echo "文件夹已经存在~"
      fi
    }
    
    
    ### 编译APK数据
    buildReleaseApk(){
      # 创建父文件夹
      createDirWhenNotFound $saveDir
      # 调用 Flutter 命令编译APK
      flutter build apk --release \
                        --dart-define=channelName=$1 \
                        --dart-define=requestUrl=$2 \
                        --target-platform android-arm,android-arm64 --split-per-abi \
                        --no-tree-shake-icons \
                        --build-name '1.0.5' \
                        --build-number '5' \
      # 切换到 Flutter 编译出来的文件夹中
      cd build/app/outputs/flutter-apk/
      # 创建渠道文件夹
      createDirWhenNotFound $saveDir/$1
      # 拷贝编译后的文件夹到对应的目录
      cp app-*.apk $saveDir/$1
      # 重新APK签名信息
      apksigner sign --ks $keysFile --ks-pass pass:123456 --ks-pass pass:123456 $saveDir/$1/app-arm64-v8a-release.apk
      apksigner sign --ks $keysFile --ks-pass pass:123456 --ks-pass pass:123456 $saveDir/$1/app-armeabi-v7a-release.apk
      
    }
    
    
    ### 编译Android安装包
    buildAndroid(){
      flutter clean
      buildReleaseApk oppo http://www.baidu1.com
      buildReleaseApk xiaomi http://www.baidu2.com
      buildReleaseApk huawei http://www.baidu3.com
      buildReleaseApk yingyongbao http://www.baidu3.com
    }
    
    buildAndroid
    
    
    

    相关文章

      网友评论

          本文标题:Flutter打包所遇到的问题

          本文链接:https://www.haomeiwen.com/subject/uhydurtx.html