众所周知,渠道包是国内 Android 应用市场中常用的分发方式。渠道包中会包含不同的渠道信息,方便我们后续统计 App 在各分发渠道的下载量、用户量、留存率等,有针对地调整应用内容或是推广方案等。随着国内 iOS 应用上架越来越难,衍生出了很多企业包,为了方便采集数据,也会用多渠道的方案。

另外,项目进展过程中,可能会出现一些临时新增渠道的需求,这时回到工程中重新打包是比较费时的,有没有办法加快打包速度呢?下文中分享了一些方案。

iOS 多渠道打包方案

iOS 打渠道包目前想到的就只有两种方式,一种是通过多 target 方式,另一种是修改 plist 文件方式。

多 target 方式

点击项目中的 target,右键选择 Duplicate。可以修改下图标红框的三处:target 名称、plist 名称和 scheme 名称。

判断当前是哪个 target,可以通过添加宏定义实现,方式就是在 Build Settings 找到 Preprocessor Macros,填入宏定义名。

代码中这样判断:

#ifdef  TARGET1MACROS    // target1#elif defined TARGET2MACROS    // target2#endif

具体打包脚本就不介绍了,读者可以自行网上搜索,这种方式的缺点是一个渠道打一次,效率较低。下面着重分享修改 plist 的批量打包方式。

修改 plist 方式

下面用一个简单的 Demo 演示一下:

第一步:创建工程名为 MultiChannelDemo 的项目,并在项目中新建一个 Channel.plist 文件,plist 中设置 Channel 字段,值为 channel01。然后在页面上设置一个 label 标签用于显示当前的渠道名称,渠道名可以通过下面的代码获取到:

NSDictionary *channelDic = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Channel" ofType:@"plist"]];NSString *channel = channelDic[@"Channel"];

第二步:把这个项目用可用的证书正常打一个母包,解压这个 ipa 包可以获得一个名为 Payload 的文件夹,里面是一个 .app 文件,右键显示其包内容,内容如下:

├── Base.lproj├── Channel.plist├── Info.plist├── MultiChannelDemo├── PkgInfo├── _CodeSignature└── embedded.mobileprovision

可以看到,里面的 Channel.plist 也就是在前面工程中新建的存储渠道信息的 plist,我们会修改里面的 Channel 再生成新的渠道包。

第三步:提取描述文件用于重签名,上一步中 Payload 的文件夹里有一个 embedded.mobileprovision 文件,这就是我们需要的文件。

第四步:新建一个纯文本,里面输入你要新增的渠道号,如:

第五步:写一个脚本文件,内容如下:

ChannelPackage.sh#!/bin/bash# 输入的包名name="MultiChannelDemo"echo "----------SDK 渠道包----------"appName="${name}.app"plistBuddy="/usr/libexec/PlistBuddy"configName="Payload/${appName}/Channel.plist"ipa="${name}.ipa"# 输出的新包所在的文件夹名outUpdateAppDir="ChannelPackages"# entitlements.plist 路径entitlementsDir="entitlements.plist"# 切换到当前目录currDir=${PWD}cd ${currDir}echo "-----${currDir}"rm -rf Payload# 解压缩-o:覆盖文件 -q:不显示解压过程unzip -o -q ${ipa}# 删除旧的文件夹,重新生成rm -rf ${outUpdateAppDir}mkdir ${outUpdateAppDir}# 删除旧的 entitlements.plist,重新生成rm -rf ${entitlementsDir}/usr/libexec/PlistBuddy -x -c "print :Entitlements " /dev/stdin <<< $(security cms -D -i Payload/${appName}/embedded.mobileprovision) > entitlements.plistecho "------------------------开始打包程序------------------------"# 渠道列表文件开始打包for line in $(cat ChannelList.txt)# 循环数组,修改渠道信息do# 修改 plist 中的 Channel 值$plistBuddy -c "Set :Channel $line" ${configName}# app 重签名rm -rf Payload/${appName}/_CodeSignaturecp embedded.mobileprovision "Payload/${appName}/embedded.mobileprovision"# 填入可用的证书 IDcodesign -f -s "iPhone Distribution: XXXXXX." Payload/${appName}  --entitlements ${entitlementsDir}# 若输出 Payload/MultiChannelDemo.app: replacing existing signature 说明重签名完成# 压缩 -r:递归处理,将指定目录下的所有文件和子目录一并处理 -q:不显示处理过程zip -rq "${outUpdateAppDir}/$line.ipa" Payloadecho "----------渠道${line}打包已完成----------"done

脚本里的信息请根据你实际情况修改。到这里准备工作都完成了,需要的文件如下:

├── ChannelList.txt├── ChannelPackage.sh├── MultiChannelDemo.ipa└── embedded.mobileprovision

第六步:在当前目录下执行脚本文件:

sh ChannelPackage.sh

打包完成后生成的 ChannelPackages 文件夹下,就是我们需要的渠道包:

├── ChannelList.txt├── ChannelPackage.sh├── ChannelPackages│   ├── channel02.ipa│   ├── channel03.ipa│   └── channel04.ipa├── MultiChannelDemo.ipa├── Payload│   └── MultiChannelDemo.app├── embedded.mobileprovision└── entitlements.plist

这种自动化打包的方式,可以规避掉 Xcode 本身打包编译的部分时间,快速出包。

Android 多渠道打包方案

下文介绍的是美团技术团队开源的 Walle,它有 Gradle 插件和命令行两种使用方式,前者快速集成,后者满足自定义需求。

Gladle 插件方式

配置 build.gradle

在项目根目录下的 build.gradle 文件中添加 Walle 插件依赖:

buildscript {    dependencies {        classpath 'com.meituan.android.walle:plugin:1.1.6'    }}

在 app 目录下的 build.gradle 文件中 apply 插件:

apply plugin: 'walle'dependencies {    compile 'com.meituan.android.walle:library:1.1.6'}

配置插件

在 app 目录下的 build.gradle 文件中进行渠道配置:

walle {    // 指定渠道包的输出路径    apkOutputFolder = new File("${project.buildDir}/outputs/channels");    // 定制渠道包的APK的文件名称    apkFileNameFormat = '${appName}_v${versionName}_${channel}.apk';    // 渠道配置文件    channelFile = new File("${project.getProjectDir()}/channel")}

渠道配置文件里的内容格式详见:渠道配置文件示例。

如何获取渠道信息

在需要填写渠道信息的地方引用这段代码:

String channel = WalleChannelReader.getChannel(this.getApplicationContext());

如何生成渠道包

用 assemble${variantName}Channels 指令,导出 apk 包。

命令行方式

通过命令行方式,可以不打开 IDE,直接导出新渠道的 apk。步骤如下:

首先,新建一个文件夹,取用一个上面步骤导出的 apk 包,再下载 walle-cli-all.jar,两者都放置在这个文件夹目录下。

然后,在文件夹目录下执行命令:

java -jar walle-cli-all.jar put -c ${channelName} ${apkName}.apk

若上面的命令执行成功,会在当前目录下生成新的渠道包,名称为 ${apkName}_${channelName}.apk

如果要批量写入渠道,可以这样,渠道之间用逗号隔开:

java -jar walle-cli-all.jar batch -c ${channelName0},${channelName1},${channelName2} ${apkName}.apk

或者指定渠道配置文件:

java -jar walle-cli-all.jar batch -c ${channelFile} ${apkName}.apk

如果要写入额外信息,参考官方文档。

如果要检查/显示渠道,命令为:

java -jar walle-cli-all.jar show ${apkName}.apk

Walle 现在既能满足新应用签名方案对安全性的要求,也能满足对渠道包打包时间的要求,有需要的可以尝试。

- end -

更多相关文章

  1. Android中利用ZipEntry漏洞实现免root写恶意文件到应用的沙盒中
  2. Android(安卓)Studio初使用之百度地图初使用(一)--配置
  3. 【Android7.1.2源码解析系列】Android编译系统翻译------Android
  4. Android(安卓)Studio中布局文件(如activity_main.xml)设计视图&代
  5. 关于Android(安卓)项目从svn中检出无R.java文件问题
  6. Android(安卓)Patcher应用增量更新(App补丁式更新,无需下载整个ap
  7. Android(安卓)studio 百度地图开发(9)只显示网格不显示地图或者只
  8. Qt android 设置系统状态栏为全透明,半透明、全屏,设置状态栏颜色,
  9. android 更换皮肤的实现

随机推荐

  1. 构造函数、dom元素的基础
  2. 大型团队 Jenkins 实践分享
  3. 何勉:第一性原理和精益敏捷的规模化实施
  4. 预生产环境数量的统计和分析
  5. CONUTIF函数经典用法,全了
  6. 一看就会,一用就废?八个实用技巧请拿好
  7. 五个常用公式,效率提高一点点
  8. 五分钟,学会一对多、多对多查询经典公式
  9. DevSecOps 三问:Why?What?How?
  10. 一对多、多对多查询,最简单的方法请拿好