当前位置 : 主页 > 手机开发 > android >

Android与iOS包体优化及一键自动打包脚本

来源:互联网 收集:自由互联 发布时间:2023-02-01
目录 系统信息 介绍 安卓APK优化包体大小 一、原理与介绍 二、Flutter代码配置 三、Android代码配置 四、多渠道调试与打包指令 安卓一键打包脚本 一、简单介绍 二、项目路径结构 三、脚
目录
  • 系统信息
    • 介绍
  • 安卓APK优化包体大小
    • 一、原理与介绍
    • 二、Flutter代码配置
    • 三、Android代码配置
    • 四、多渠道调试与打包指令
  • 安卓一键打包脚本
    • 一、简单介绍
    • 二、项目路径结构
    • 三、脚本内容
    • 四、脚本使用步骤
  • 苹果优化包体大小
    • 一、常规优化(分发到 App Store 或者 打Ad hoc 测试包)
    • 二、非常规优化
      • 1、Flutter导出IPA(共4步)
      • 2、第一次优化包体大小(共5步)
      • 3、第二次优化包体大小(共6步)
      • 4、一些说明
  • 苹果一键打包脚本
    • 一、简单介绍
      • 二、项目路径结构
        • 三、脚本内容
          • 四、plist文件
            • 五、脚本使用步骤

            系统信息

            • System version: MacOS 12
            • Flutter version: 1.22.5
            • Dart version: 2.10.4
            • Android Studio version: 4.1.1

            介绍

            • APK优化包体大小
            • APK多渠道打包
            • APK一键打包脚本
            • IPA优化包体大小
            • IPA无签名打包
            • IPA一键打包脚本

            脚本地址

            github脚本地址

            安卓APK优化包体大小

            • 优化图片等资源大小,删除无用资源
            • 只选择保留必要的so库。第三方SDK也尽量只里保留必要的so库,优化后的包体至少减少几十兆

            参考修改android/app/build.gradle 文件

                buildTypes {
                    release {
                        ndk{
                            //"armeabi","armeabi-v7a","arm64-v8a","x86_64","x86"  //x86是兼容模拟器的
                            abiFilters "armeabi","armeabi-v7a","arm64-v8a"  //手机没什么x86框架的,只包含arm32和arm64即可
                        }
                    }
                }
            

            安卓多渠道配置与打包

            一、原理与介绍

            • 从 Flutter v1.17 开始,Flutter 命令工具增加了自定义参数的功能 --dart-define,我们可以用这个命令参数在打包或运行 App 时设置参数。这样我们就能在Flutter代码和原生代码中获取传过来的参数,从而实现多渠道功能。
            • 假设我们设置5个渠道 1、应用宝, 2、华为商店, 3、小米商店,4、OPPO商店 5、VIVO商店

            二、Flutter代码配置

            1、获取参数

            配置文件路径:lib/main.dart

            /// 这里定义环境变量配置
            class EnvironmentConfig {
              static const CHANNEL = String.fromEnvironment('CHANNEL');
              //DEBUG = Y 是调试模式,其他为生产模式
              static const DEBUG = String.fromEnvironment('DEBUG');
            }
            

            2、任意的地方使用参数

            #获取CHANNEL 参数值
            String appMarket = EnvironmentConfig.CHANNEL;
            #获取DEBUG 参数值
            String debug = EnvironmentConfig.DEBUG;
            

            三、Android代码配置

            1、获取参数

            配置文件路径:android/app/build.gradle

            /// 获取渠道参数使用,这里设置一下默认值
            def dartEnvironmentVariables = [
                    CHANNEL: 'YYB',
                    DEBUG: '',
            ]
            if (project.hasProperty('dart-defines')) {
                dartEnvironmentVariables = dartEnvironmentVariables + project.property('dart-defines')
                        .split(',')
                        .collectEntries { entry ->
                            def pair = URLDecoder.decode(entry).split('=')
                            [(pair.first()): pair.last()]
                        }
            }
            

            2、使用

            配置文件路径:android/app/build.gradle

            //例子:打包APK时修改文件名带上渠道参数,还有一些SDK也可以通过这种方式设置参数
            //dartEnvironmentVariables.CHANNEL 使用参数
            android{
               android.applicationVariants.all {
                    variant ->
                        variant.outputs.all {
                            output ->
                                def outputFile = output.outputFile
                                if (outputFile.name.contains("release")) {
                                    outputFileName = "APP_${getDateTime()}_${dartEnvironmentVariables.CHANNEL}.apk"
                                }
                        }
                }
            }
            

            四、多渠道调试与打包指令

            # 调试例子1:设置渠道为应用宝。
            flutter run --dart-define=CHANNEL=YYB
            # 调试例子2:设置渠道为应用宝。DEBUG参数是Y
            flutter run --dart-define=CHANNEL=YYB --dart-define=DEBUG=Y
            #打包例子1:打包应用宝渠道包
            flutter build apk --dart-define=CHANNEL=YYB
            #打包例子2:打包应用宝渠道包,DEBUG参数是Y
            flutter build apk --dart-define=CHANNEL=YYB --dart-define=DEBUG=Y
            

            安卓一键打包脚本

            一、简单介绍

            通过上面的配置和优化后我们就能开始执行脚本打包了,本脚本主要实现了以下功能

            • 可控制是否执行 flutter clean 清理指令(回车或者5秒无指令输入默认不清理)
            • 可控制只打某个渠道包或者全部渠道包(回车或者5秒无指令输入默认打全部包)
            • 可设置渠道种类数组,可无限扩展
            • 成功打包后自动打开文件夹
            • 实现无人值守打包

            二、项目路径结构

            1、shell 目录存放脚本文件 ,papk.sh 是安卓脚本

            2、prod 目录导出打包文件

            三、脚本内容

            #!/bin/sh
            #---------------------必须修改:渠道数组----------------#
            channels=(YYB HUAWEI MI OPPO VIVO)
            #当前工程绝对路径
            project_path=$(pwd)
            #安卓包product文件夹路径
            prod_path=${project_path}/prod/apk/
            #Flutter打包生成的最初地址
            release_path=${project_path}/build/app/outputs/apk/release/
            clean_tips="执行flutter clean(默认:n) [ y/n ]"
            echo $clean_tips
            read  -t 5 is_clean
            if [  ! -n "${is_clean}" ];then
                is_clean="n"
            fi
            while([[ $is_clean != "y" ]] && [[ $is_clean != "n" ]])
            do
              echo "错误!只能输入[ y/n ] !!!"
              echo $clean_tips
              read is_clean
            done
            tips="请输入选择渠道(默认:0) [ ALL: 0 "
            c_length=${#channels[@]};
            for(( i=0; i<$c_length; i++)) do
              if (($i < $c_length-1 )); then
                tips="${tips}${channels[i]}: $((i+1)) "
              else
                tips="${tips}${channels[i]}: $((i+1)) ]"
              fi
            done;
            echo $tips
            read  -t 5 number
            if [  ! -n "${number}" ];then
                number=0
            fi
            while(( $number < "0" || $number > $c_length ))
            do
              echo "错误!只能输入0到${c_length} !!!"
              echo $tips
              read number
            done
            #如果有product/apk文件夹则删除,然后再创建一个空文件夹
            if [ -d ${prod_path} ]; then
              rm -rf ${prod_path}
            fi
            #创建目录
            mkdir -p ${prod_path}
            if [ ${is_clean} = "y" ];then
              echo "=============== 开始清理 ==============="
                flutter clean
            fi
            if (($number == 0 )); then
              echo "=============== 开始构建:全部渠道包 ==============="
              for(( i=0;i<${c_length};i++)) do
                echo "正在构建:${channels[$i]} 渠道包"
                flutter build apk --no-shrink --dart-define=CHANNEL=${channels[$i]}
                cp -R ${release_path}*.apk ${prod_path}
              done;
            else
              echo "=============== 正在构建:${channels[$((number-1))]} 渠道包 ==============="
              flutter build apk --no-shrink --dart-define=CHANNEL=${channels[$((number-1))]}
              cp -R ${release_path}*.apk ${prod_path}
            fi
            #判断apk目录下是否有文件
            if [ "$(ls -A $prod_path)" ]; then
              echo "=============== APK包已导出:$prod_path ==============="
              open $prod_path
            else
              echo '=============== APK包导出失败 ==============='
              exit 1
            fi
            exit 0
            

            四、脚本使用步骤

            • 1、在项目根目录创建一个shell文件夹
            • 2、在shell目录创建papk.sh文件,并粘贴脚本内容。修改channels渠道数组变量值为自己的,然后保存脚本
            • 3、项目根目录执行命令添加执行权限: chmod u+x shell/papk.sh
            • 4、项目根目录执行命令:./shell/papk.sh

            苹果优化包体大小

            一、常规优化(分发到 App Store 或者 打Ad hoc 测试包)

            • 优化图片等资源大小,删除无用资源,比较简单,而且对于一般的app来说优化效果不大,这里就不详细说明了。
            • 只选择保留必要的指令集类型。xcode 12以上默认是包含armv7和arm64位两种指令集。我们打Release包时可以排除armv7指令集。只保留arm64指令集就可以了 看图操作:

            ** 如果担心兼容性的,下面再附一张指令集对应手机型号的图 **

            二、非常规优化

            一般情况下我们使用xcode分发的时候,xcode还会帮我们优化一次代码大小的,包体大概能减少一半以上。然鹅,如果需要自己导出一个无签名的IPA包时我们应该怎么优化包体大小?下面是我总结的操作步骤

            1、Flutter导出IPA(共4步)

            • 执行flutter build ios --release 生成Runner.app文件
            • 在Runner.app目录下新建一个Payload文件夹, 并将该 app 拖进去
            • 右键->压缩"Payload"为Payload.zip
            • 将生成的 Payload.zip 文件更名为 xxx.ipa 即可得到 ipa 安装包

            2、第一次优化包体大小(共5步)

            上面生成的ipa大的离谱。动不动就几百兆。所以,我们需要利用Xcode来帮忙优化一下Runner.app。总体步骤比上面的打包多了一步。

            • 执行flutter build ios --release 生成Runner.app文件
            • ✅ 使用xcode打开项目,然后点击product->build。成功后生成一个新的Runner.app。
            • 在Runner.app目录下新建一个Payload文件夹, 并将该 app 拖进去
            • 右键->压缩"Payload"为Payload.zip
            • 将生成的 Payload.zip 文件更名为 xxx.ipa 即可得到 ipa 安装包

            一顿操作后,包体大概能减少几十或者上百兆。看着很可观,但是由于原来的包实在太大,即使减了这么多,可能最终还有一百来兆。

            3、第二次优化包体大小(共6步)

            • 执行flutter build ios --release 生成Runner.app文件
            • ✅ 使用xcode打开项目,然后点击product->build。成功后生成一个新的Runner.app。
            • ✅ Runner.app目录下执行指令: xcrun bitcode_strip Runner.app/Frameworks/Flutter.framework/Flutter -r -o Runner.app/Frameworks/Flutter.framework/Flutter
            • 在Runner.app目录下新建一个Payload文件夹, 并将该 app 拖进去
            • 右键->压缩"Payload"为Payload.zip
            • 将生成的 Payload.zip 文件更名为 xxx.ipa 即可得到 ipa 安装包

            再一顿操作下来后,包体大概又能减少几十或者上百兆。终于基本优化到一百兆以内,接近用Ad hoc分发的ipa包的大小

            4、一些说明

            1、 Flutter生成Runner.app比较大的原因

            ios的Flutter二进制文件增加了对bitcode的支持,从而导致体积增大

            2、 如何优化

            执行 xcrun bitcode_strip 指令就能去掉bitcode

            xcrun bitcode_strip 指令大家可以自行网上搜索。详细的使用我就不细说了

            苹果一键打包脚本

            一、简单介绍

            通过上面的”常规优化“后我们就能开始执行脚本打包了,本脚本主要实现了以下功能

            • 可控制是否执行 flutter clean 清理指令(回车或者5秒无指令输入默认不清理)
            • 可控制选择打无签名包还是Ad hoc测试包(回车或者5秒无指令输入默认无签名包)
            • 成功打包后自动打开文件夹
            • 实现无人值守打包
            • 如果要导出无签名包,脚本中添加了”非常规的优化“相关的操作

            二、项目路径结构

            1、shell 目录存放脚本和plist文件, pipa.sh 是苹果脚本,

            2、prod 目录导出打包文件

            三、脚本内容

            #!/bin/sh
            #当前工程绝对路径
            project_path=$(pwd)
            #xCode build 出来的APP文件有所优化,比Flutter build ios 的Runner.app要小
            #------------------必须修改:XCODE工程导出路径----------------#
            runner_path=~/Library/Developer/Xcode/DerivedData/Runner-bsrdqyyshhsictbeoknvquvcxcsm/Build/Products/Release-iphoneos/Runner.app
            #-------------------可选:自己的plist配置路径------------------#
            export_plist_path=${project_path}/shell/scriptTest.plist
            #-------------------可选:修改为自己的APP名称------------------#
            app_name="APP名称"
            #----------------可选:将Runner替换成自己的工程名---------------#
            project_name=Runner
            #----------------可选:将Runner替换成自己的sheme名--------------#
            scheme_name=Runner
            #打包模式 Debug/Release
            development_mode=Release
            #导出.ipa文件所在路径
            ipa_path=${project_path}/prod/ipa/
            #导出签名.ipa文件所在路径
            sign_path=${ipa_path}/sign
            #导出未签名.ipa文件所在路径
            unsign_path=${ipa_path}/unsign
            #导出未签名.Payload文件所在路径
            payload_path=${unsign_path}/Payload
            clean_tips="执行flutter clean(默认:n) [ y/n ]"
            echo $clean_tips
            read  -t 5 is_clean
            if [  ! -n "${is_clean}" ];then
                is_clean="n"
            fi
            while([[ $is_clean != "y" ]] && [[ $is_clean != "n" ]])
            do
              echo "错误!只能输入[ y/n ] !!!"
              echo $clean_tips
              read is_clean
            done
            echo "请输入选择模式(默认:0) [ UnSign: 0 AdHoc: 1 ] "
            read  -t 5 number
            if [  ! -n "${number}" ];then
                number=0
            fi
            while([[ $number != 0 ]] && [[ $number != 1 ]])
            do
              echo "错误!只能输入0或者1!!!"
              echo "请输入选择模式? [ UnSign: 0 AdHoc: 1 ] "
              read number
            done
            if [ ${is_clean} = "y" ];then
              echo "=============== 开始清理 ==============="
                flutter clean
            fi
            echo "=============== 构建FLUTTER_IOS工程 ==============="
            if [ $number == 0 ];then
              flutter build ios --release --no-codesign
            else
              flutter build ios
            fi
            #flutter build ios --release --no-codesign --obfuscate --split-debug-info=./symbols
            #如果有product/ipa文件夹则删除,然后再创建一个空文件夹
            if [ -d ${ipa_path} ]; then
              rm -rf ${ipa_path}
            fi
            #创建目录
            mkdir -p ${ipa_path}
            #rm -rf ${ipa_path}
            if [ $number == 0 ];then
              #无签名打包
              echo "=============== 正在编译XCODE工程:${development_mode} ==============="
              xcodebuild build -workspace ios/${project_name}.xcworkspace -scheme ${scheme_name} -configuration ${development_mode}
              mkdir -p ${payload_path}
              cp -r ${runner_path} ${payload_path}
              cd ${unsign_path}
              echo "=============== 读取APP信息 ==============="
              #info.plist路径
              info_plist="Payload/Runner.app/info.plist"
              version=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "$info_plist")
              build=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$info_plist")
              time=$(date "+%Y%m%d_%H%M")
              appName="$app_name""_v$version""_b$build""_$time.ipa"
              echo "=============== 优化Framework大小 ==============="
              xcrun bitcode_strip ${payload_path}/Runner.app/Frameworks/Flutter.framework/Flutter -r -o ${payload_path}/Runner.app/Frameworks/Flutter.framework/Flutter
              xcrun bitcode_strip ${payload_path}/Runner.app/Frameworks/AgoraRtcKit.framework/AgoraRtcKit -r -o ${payload_path}/Runner.app/Frameworks/AgoraRtcKit.framework/AgoraRtcKit
              xcrun bitcode_strip ${payload_path}/Runner.app/Frameworks/App.framework/App -r -o ${payload_path}/Runner.app/Frameworks/App.framework/App
              echo "=============== 生成IPA(压缩Payload文件并修改文件名为IPA) ==============="
              zip -r ${appName} *
              if [ -e $unsign_path/$appName ]; then
                echo "=============== IPA包已导出:$unsign_path/$appName ==============="
                open $unsign_path
              else
                echo '=============== IPA包导出失败 ==============='
                exit 1
              fi
            else
              #Ad hoc 打包
              echo "=============== 正在编译工程:${development_mode} ==============="
              xcodebuild \
              archive -workspace ${project_path}/ios/${project_name}.xcworkspace \
              -scheme ${scheme_name} \
              -configuration ${development_mode} \
              -archivePath ${ipa_path}/${project_name}.xcarchive  -quiet  || exit
              echo ''
              echo '=============== 开始IPA打包 ==============='
              xcodebuild -exportArchive -archivePath ${ipa_path}/${project_name}.xcarchive \
              -configuration ${development_mode} \
              -exportPath ${sign_path} \
              -exportOptionsPlist ${export_plist_path} \
              -quiet || exit
              if [ -e $sign_path/$app_name.ipa ]; then
                echo "=============== IPA包已导出:$sign_path/$app_name.ipa ==============="
                open $sign_path
              else
                echo '=============== IPA包导出失败 ==============='
                exit 1
              fi
            fi
            exit 0
            

            四、plist文件

            <?xml version="1.0" encoding="UTF-8"?>
            <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
            <plist version="1.0">
            <dict>
                <key>compileBitcode</key>
                <true/>
                <key>destination</key>
                <string>export</string>
                <key>method</key>
                <string>ad-hoc</string>
                <key>signingCertificate</key>
                <string>XXXXXXXX</string>
                <key>signingStyle</key>
                <string>automatic</string>
                <key>stripSwiftSymbols</key>
                <true/>
                <key>teamID</key>
                <string>XXXXXX</string>
                <key>thinning</key>
                <string>&lt;none&gt;</string>
            </dict>
            </plist>
            

            五、脚本使用步骤

            • 1、在项目根目录创建一个shell文件夹
            • 2、在shell目录创建papk.sh文件,并粘贴脚本内容。修改runner_path变量值为自己xcode导出Runner.app的路径,然后保存并关闭
            • 3、在shell目录创建scriptTest.plist文件,并粘贴plist文件内容。修改自己的signingCertificate和teamID的值,然后保存并关闭
            • 4、项目根目录执行命令添加执行权限: chmod u+x shell/pipa.sh
            • 5、项目根目录执行命令:./shell/papk.sh

            以上就是安卓与iOS包体优化及一键自动打包脚本的详细内容,更多关于安卓 iOS打包脚本的资料请关注自由互联其它相关文章!

            上一篇:为什么不要在 Flutter 中使用全局变量
            下一篇:没有了
            网友评论