早几天客户发来信息,说ios 15系统下载蒲公英内部分发安装失败了。如下图
一、纠其病因
第一时间百度、Google、官网都看了看。
参考文章如下:
- https://www.jianshu.com/p/07cdff01f297
- https://stackoverflow.com/questions/68149213/observing-app-needs-to-be-updated-message-when-launching-app-on-ios-15
- https://developer.apple.com/documentation/xcode/using-the-latest-code-signature-format
根据官方文档,iOS在分发App之前需要对其签名。当是从iOS 15、iPadOS 15、tvOS 15和watchOS 8开始,系统会检查新的、更安全的签名格式。而还是使用之前的签名格式的App将不会启动。
二、终极解决方案
当然了,基于上面的所说的,最好最快速最牛逼的方式当然是升级服务器的系统咯。因为在macOS 11以上打包就会默认使用新的签名格式,无需担心新老签名的问题。O(∩_∩)O哈哈~
但是有得mac比较老了,升级不上去,不再升级序列,只能全量升级。那就麻烦了,还是用下面的方式签名吧~
我们就是情况二~
三、首先,需要确定你的App是否需要新的签名
3.1 有几种情况是不需要重新签名处理的
新的签名方式不会影响大多数的App,如果你的App是通过App Store或Test Flight分发的。那么你不需要担心,App Store Connect 首先验证您的签名,然后使用 Apple 身份重新签名应用程序,通过这些渠道提供的应用程序已经具有新的签名格式。
如果你的发布服务器macOS版本在macOS 11或更高的话,那么也不需要当心。因为它已经默认使用新的签名格式多App进行签名。
3.2 需要进行重新签名的情况
- 发布服务器macOS版本比较低,小于11,10.14~11之间的情况就需要重视了,基本上都中招。
3.3 检测iOS App是否需要重新签名
- 第一步:需要将ipa包改为zip格式,然后解压。
- 第二步:解压后一般会得到一个Payload文件夹,在文件夹里就有一个**.app文件。
- 第三步:对*.app文件使用以下命令
codesign -dv /path/to/MyApp.app
如上图通过命令,我们可以获得CodeDirectory v=20400,如果该值小于20400,则表明你需要重新签名App。
- 第四步:除了第三步,我们最好还需要再用下面这个命令测试以下
codesign -dvvvvv /path/to/MyApp.app
如上两图,该命令可以获得哈希列表,如果-5包含值,而-7没有或者包含0值的话,则需要重新签名。签名完成后,再使用命令得出的会是第二个正确的哈希列表。含有-7,且不为0。
- 第五步:然后用下面的命令重新签名
Your Codesign Identity:就是你的发布证书,在钥匙串里可以找到
codesign -s "Your Codesign Identity" -f --preserve-metadata --generate-entitlement-der /path/to/MyApp.app
签完之后,重新用“codesign -dvvvvv /path/to/MyApp.app"再次查看哈希列表,确认已经有-7的值。
- 第六步:压缩Payload文件,并将其重命名为*.ipa文件(ipa后缀)
至此,重新签名搞定。
四、将以上步骤写成脚本
因为我们可能用到持续集成,用到了比如说Jenkins之类的,我们就需要把上面的流程写成脚本
//1. cd到ipa包的目录下面
project_path="${WORKSPACE}/build/ios/ipa"
cd ${project_path}
//2. 将ipa包重命名为zip包
mv "MyApp.ipa" MyApp.zip
//3. 将zip包进行解压
unzip -q -o MyApp.zip
//4. 解压之后,并对Payload/*.app文件重新签名
codesign -s "Your Codesign Identity" -f --preserve-metadata --generate-entitlement-der Payload/MyApp.app
//5. 再将Payload文件夹进行压缩为zip包
zip -q -r -m Payload.zip Payload
//6. 重命名zip包围*.ipa包
mv Payload.zip MyApp.ipa
//7. 删除zip包
rm -f MyApp.zip
五、Flutter项目中iOS重新签名时遇到的问题
如果是原生iOS应用,或者用fastline、xcode archive打出的ipa,重签名,没问题,妥妥的。
而在我的实践中,我们是纯Flutter项目,用的Jenkins,flutter build ios命令打包出来的,重新签名后,哈希值啥的都是有-7,正常的。但是安装后打开还是出问题了。
安装打开后,如图:
5.1 因为我们之前flutter命令打包ios的方式如下:
flutter doctor -v
flutter clean
flutter pub get
flutter pub upgrade
flutter pub run build_runner build --delete-conflicting-outputs
flutter build ios --release --flavor dev -t lib/main.dart
if [ -d "build/ios/iphoneos/Runner.app" ]
then
mkdir -p build/app/Payload
cp -r "build/ios/iphoneos/Runner.app" build/app/Payload
cd build/app
zip -r -m MyApp.ipa Payload
cd ..
echo "打包成功"
open app
else
echo "打包失败"
fi
是使用的flutter build ios命令打包*.app的文件,然后在进行压缩和重命令ipa的。
但是这种方式打出来的ipa,重新签名后在发布到蒲公英,下载后安装打开就会出现上面那种状况。说“无法安装此App,无法验证其完整性”。
这让我百思不得其姐~
5.2 开始一步一步锚定问题
- 首先,我使用xcode的archive打出一个ipa包,对它进行重签名,发现可以安装,没报问题。
- 那我们确定了是flutter build ios这种打包命令有问题
- 然后我去官网找到了另一个命令"flutter build ipa",它可以直接打出一个ipa的包来。 Build and release an iOS app
flutter build ipa --export-options-plist=path/to/ExportOptions.plist
但是它需要提前配置一个ExportOptions.plist的plist文件,这个文件你可以使用你的xcode archive打包导出ipa的时候,它也会生成ExportOptions.plist这样的文件。你也可以直接使用它。
该文件可以放置工程目录或者你指定的地方,只要你执行脚本时找得到就行。
ExportOptions.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>method</key>
<string>ad-hoc</string>
<key>teamID</key>
<string>发布证书ID</string>
</dict>
</plist>
使用"flutter build ipa",也配置了ExportOptions.plist文件后,发现它确实可以打出xcarchive文件来,但是始终没有打出ipa包来。
然后试了下,用生成的xcarchive文件,在xcode上签名,发现可以导出ipa来,验证了xcarchive文件是没啥问题的。
然后我去找了用xcodebuild命令将archive打包成ipa
xcodebuild -exportArchive -archivePath /Path/To/Output/YourApp.xcarchive -exportPath /Path/To/ipa/Output/Folder -exportOptionsPlist /Path/To/ExportOptions.plist
发现也不成功,老是报错:
然后,搜了下日志和网页发现是sqlite3没有安装的问题:xcode 脚本打包报错 error: exportArchive: The data couldn’t be read because it isn’t in the correct format
安装了sqlite3之后,重启电脑,在使用flutter build ipa命令就可以直接打出ipa的包来了
在进行重签名步骤,上传蒲公英,下载安装就妥妥滴了~