在完成基础的自动包打包流程过后, 随即也出现了日常中常见的问题, 比如我们每次需要打出不同网络环境和不同证书的ipa, 由于开发者可以添加的设备只有100个, 而公司的几个项目都是用的一个账号, 各项目组都是独立的, 再加上期间加入设备的员工的离职, 真正能参与测试的设备寥寥无几。
所以我司一般测试都是使用企业证书, 这样不同的项目都可以公用同一个证书, 不仅管理起来方面, 而且还摆脱了设备数量限制的烦恼, 但另一方面, 对于需要测试内购等功能的时候, 仍然需要使用adhoc证书的包来进行测试。
我们原先的打包策略是通过执行脚本时输入的参数来打对应的包, 这样对于不同测试并行测试, 一次就要打出好几个, 以我司作为打包服务器 Mac Mini 来说, archive + export 一个包的时间约为20min, 对于不同证书不同环境的包随机组合, 一次打出4个不同的包的时间就要花费约1h20min, 而且在打包的时候, 如果其他同事修改了新的bug, 也无法打包。
因此, 我们寻思能不能通过重签名的方式, 只编译一次, 对其重签名, 打出不同的包。
本文主要介绍我在此过程中的一些探索, 旨在提高不同证书不同环境的打包效率。
对ipa进行重签名
起初, 我在网上查阅了相关资料, 按照相关教程, 却最终以失败告终。 如果有同学直接对ipa进行重签名成功的, 希望不吝赐教。
我估摸着是不是内部做了什么验证, 导致对ipa重签名无法成功。所以, 我想可不可以不到ipa这步, 更早地对其进行信息的修改以及重签名, 权当一次尝试, 即使失败也能在探索中学到新知识。最终, 成功将原来打4个包需要1h20min的时间压缩到30min不到。
不等导出ipa, 修改.xcarchive文件
.xcarchive文件是对项目进行手动archive, 或执行以下脚本:
xcodebuild archive -workspace ${work_space} -scheme ${scheme} -configuration ${configurationDistribution} -archivePath ${archivePath}
复制代码
如果对打包命令不是很了解的, 可以查看我的上一篇文章文章:关于iOS自动化打包的一些分享
首先, 我们进入到 .xcarchive 文件目录, 发现里面一个 Info.plist 文件, 打开如下显示:
我们可以看到里面有一些App必需的属性。
1. 修改 .xcarchive 的 Info.plist
此处, 如果项目 Bundle Identifier 需要发生改变, 则修改 CFBundleIdentifier 对应的值, 并将 SigningIdentity 改成 Bundle Identifier 对应的证书, 关于此处SigningIdentity的值, 可在钥匙串中找到对应的证书, 查看其信息, 即为下图中(英文系统)的 Common Name 。
2. 修改 App Extension 相关信息
此步是对于项目 target 中如 notification extension 等从属 target, 如果没有 App Extension , 直接可以跳过此步, 查看下一步 修改主target相关信息 。
通过文件夹打开 YourAppName.xcarchive/Products/Applications/YourAppName.app/PlugIns/YourAppNameNotificationServiceExtension.appex , 这里不是标准文件夹, open 命令似乎不起作用, 观察其目录结构:
2.1 修改 Info.plist 相关信息
App Extension 的 Bundle Identifier 是 App 的 Bundle Identifier 加上其对应后缀, 如 notificationserviceextension 。
修改 Bundle Identifier 为对应的值, 这里对应的值是指之前修改 .xcarchive 目录中 Info.plist 的 Bundle Identifier 对应, 如 com.test.www , 这里便是 com.test.www.notificationserviceextension。
2.2 替换 Provisioning Profile
将对应的 Provisioning Profile 拷贝到该目录下替换原来的 Provisioning Profile , 改成相同的文件名 embedded.mobileprovision 。
2.3 修改 archived-expanded-entitlements.xcent
我们通过xcode打开archived-expanded-entitlements.xcent, 其本质就是plist文件, 格式是 teamId.bundle identifier 。
修改图中遮盖的两项值, 依旧是要和.xcarchive的Info.plist值对应。
2.4 重签名
用对应的证书对 App Extension 重新签名, 这里的 YourCetificateName 依旧是修改 .xcarchive的Info.plist 里的证书名。
codesign -f -s "YourCetificateName" YourAppNameNotificationServiceExtension.appex
复制代码
3. 修改主target相关信息
与上一步修改 App Extension 步骤基本相同, 只是少一步, 不用修改 archived-expanded-entitlements.xcent 。
3.1 修改Info.plist的相关信息
进入.app目录, 修改Info.plist的Bundle Identifier, 使其与.xcarchive文件对应。
你也可以修改其他一些值, 如网络环境, 是测试环境, 还是生产环境, 这里只是抛砖引玉。事实上, 修改网络环境有方便的方法, 如通过读取粘贴板的文本来切换, 或者写一个辅助程序来打开我们的App, 从而通知切换环境。
3.2 替换Provisioning Profile
将对应的 Provisioning Profile 拷贝到该目录下替换原来的 Provisioning Profile , 改成相同的文件名 embedded.mobileprovision 。
3.3 重签名
用对应的证书对 .app文件 重新签名, 这里的 YourCetificateName 依旧是修改 .xcarchive的Info.plist 里的证书名。
codesign -f -s "YourCetificateName" YourAppName.app
复制代码
4. 导出包
xcodebuild -exportArchive -archivePath YourAppName.xcarchive -exportPath $(pwd) -exportOptionsPlist YourExportOptionsPlistPath
复制代码
成功后, 命令台输出:
如果对于 exportOptionsPlist 不了解的, 也可以看我的上篇文章:关于iOS自动化打包的一些分享 。
注意点
上述修改的每一步, 无论是Bundler Identifer, 还是Provisioning Profile, 还是重签名用的证书, 都是需要相对应的, 如果有一步错了, ipa包是导不出来的。
我的表述可能不是那么清楚, 相信大家操作一次, 一步一步来, 修改需要修改的值, 其实基本是一目了然的。 大家如果有类似需求, 建议先操作一次, 成功后再写脚本实现自动化。
总结
经过上述操作, 实质上只进行了一次编译, 然后修改相关信息, 导出对应不同的证书的包, 只是多做了几次导出操作, 大大地节省了打包时间。大家如果有什么想法或更好的办法, 欢迎一起讨论讨论。