早幾天客戶發(fā)來(lái)信息,說(shuō)ios 15系統(tǒng)下載蒲公英內(nèi)部分發(fā)安裝失敗了。如下圖


一、糾其病因
第一時(shí)間百度、Google、官網(wǎng)都看了看。
參考文章如下:
- http://www.itdecent.cn/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
根據(jù)官方文檔,iOS在分發(fā)App之前需要對(duì)其簽名。當(dāng)是從iOS 15、iPadOS 15、tvOS 15和watchOS 8開始,系統(tǒng)會(huì)檢查新的、更安全的簽名格式。而還是使用之前的簽名格式的App將不會(huì)啟動(dòng)。
二、終極解決方案
當(dāng)然了,基于上面的所說(shuō)的,最好最快速最牛逼的方式當(dāng)然是升級(jí)服務(wù)器的系統(tǒng)咯。因?yàn)樵趍acOS 11以上打包就會(huì)默認(rèn)使用新的簽名格式,無(wú)需擔(dān)心新老簽名的問(wèn)題。O(∩_∩)O哈哈~
但是有得mac比較老了,升級(jí)不上去,不再升級(jí)序列,只能全量升級(jí)。那就麻煩了,還是用下面的方式簽名吧~
我們就是情況二~
三、首先,需要確定你的App是否需要新的簽名
3.1 有幾種情況是不需要重新簽名處理的
新的簽名方式不會(huì)影響大多數(shù)的App,如果你的App是通過(guò)App Store或Test Flight分發(fā)的。那么你不需要擔(dān)心,App Store Connect 首先驗(yàn)證您的簽名,然后使用 Apple 身份重新簽名應(yīng)用程序,通過(guò)這些渠道提供的應(yīng)用程序已經(jīng)具有新的簽名格式。
如果你的發(fā)布服務(wù)器macOS版本在macOS 11或更高的話,那么也不需要當(dāng)心。因?yàn)樗呀?jīng)默認(rèn)使用新的簽名格式多App進(jìn)行簽名。
3.2 需要進(jìn)行重新簽名的情況
- 發(fā)布服務(wù)器macOS版本比較低,小于11,10.14~11之間的情況就需要重視了,基本上都中招。
3.3 檢測(cè)iOS App是否需要重新簽名
- 第一步:需要將ipa包改為zip格式,然后解壓。
- 第二步:解壓后一般會(huì)得到一個(gè)Payload文件夾,在文件夾里就有一個(gè)**.app文件。
- 第三步:對(duì)*.app文件使用以下命令
codesign -dv /path/to/MyApp.app

如上圖通過(guò)命令,我們可以獲得CodeDirectory v=20400,如果該值小于20400,則表明你需要重新簽名App。
- 第四步:除了第三步,我們最好還需要再用下面這個(gè)命令測(cè)試以下
codesign -dvvvvv /path/to/MyApp.app


如上兩圖,該命令可以獲得哈希列表,如果-5包含值,而-7沒(méi)有或者包含0值的話,則需要重新簽名。簽名完成后,再使用命令得出的會(huì)是第二個(gè)正確的哈希列表。含有-7,且不為0。
- 第五步:然后用下面的命令重新簽名
Your Codesign Identity:就是你的發(fā)布證書,在鑰匙串里可以找到
codesign -s "Your Codesign Identity" -f --preserve-metadata --generate-entitlement-der /path/to/MyApp.app
簽完之后,重新用“codesign -dvvvvv /path/to/MyApp.app"再次查看哈希列表,確認(rèn)已經(jīng)有-7的值。
- 第六步:壓縮Payload文件,并將其重命名為*.ipa文件(ipa后綴)
至此,重新簽名搞定。
四、將以上步驟寫成腳本
因?yàn)槲覀兛赡苡玫匠掷m(xù)集成,用到了比如說(shuō)Jenkins之類的,我們就需要把上面的流程寫成腳本
//1. cd到ipa包的目錄下面
project_path="${WORKSPACE}/build/ios/ipa"
cd ${project_path}
//2. 將ipa包重命名為zip包
mv "MyApp.ipa" MyApp.zip
//3. 將zip包進(jìn)行解壓
unzip -q -o MyApp.zip
//4. 解壓之后,并對(duì)Payload/*.app文件重新簽名
codesign -s "Your Codesign Identity" -f --preserve-metadata --generate-entitlement-der Payload/MyApp.app
//5. 再將Payload文件夾進(jìn)行壓縮為zip包
zip -q -r -m Payload.zip Payload
//6. 重命名zip包圍*.ipa包
mv Payload.zip MyApp.ipa
//7. 刪除zip包
rm -f MyApp.zip
五、Flutter項(xiàng)目中iOS重新簽名時(shí)遇到的問(wèn)題
如果是原生iOS應(yīng)用,或者用fastline、xcode archive打出的ipa,重簽名,沒(méi)問(wèn)題,妥妥的。
而在我的實(shí)踐中,我們是純Flutter項(xiàng)目,用的Jenkins,flutter build ios命令打包出來(lái)的,重新簽名后,哈希值啥的都是有-7,正常的。但是安裝后打開還是出問(wèn)題了。
安裝打開后,如圖:

5.1 因?yàn)槲覀冎癴lutter命令打包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的文件,然后在進(jìn)行壓縮和重命令ipa的。
但是這種方式打出來(lái)的ipa,重新簽名后在發(fā)布到蒲公英,下載后安裝打開就會(huì)出現(xiàn)上面那種狀況。說(shuō)“無(wú)法安裝此App,無(wú)法驗(yàn)證其完整性”。
這讓我百思不得其姐~
5.2 開始一步一步錨定問(wèn)題
- 首先,我使用xcode的archive打出一個(gè)ipa包,對(duì)它進(jìn)行重簽名,發(fā)現(xiàn)可以安裝,沒(méi)報(bào)問(wèn)題。
- 那我們確定了是flutter build ios這種打包命令有問(wèn)題
- 然后我去官網(wǎng)找到了另一個(gè)命令"flutter build ipa",它可以直接打出一個(gè)ipa的包來(lái)。 Build and release an iOS app
flutter build ipa --export-options-plist=path/to/ExportOptions.plist
但是它需要提前配置一個(gè)ExportOptions.plist的plist文件,這個(gè)文件你可以使用你的xcode archive打包導(dǎo)出ipa的時(shí)候,它也會(huì)生成ExportOptions.plist這樣的文件。你也可以直接使用它。
該文件可以放置工程目錄或者你指定的地方,只要你執(zhí)行腳本時(shí)找得到就行。
ExportOptions.plist文件內(nèi)容:
<?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>發(fā)布證書ID</string>
</dict>
</plist>
使用"flutter build ipa",也配置了ExportOptions.plist文件后,發(fā)現(xiàn)它確實(shí)可以打出xcarchive文件來(lái),但是始終沒(méi)有打出ipa包來(lái)。
然后試了下,用生成的xcarchive文件,在xcode上簽名,發(fā)現(xiàn)可以導(dǎo)出ipa來(lái),驗(yàn)證了xcarchive文件是沒(méi)啥問(wèn)題的。
然后我去找了用xcodebuild命令將archive打包成ipa
xcodebuild -exportArchive -archivePath /Path/To/Output/YourApp.xcarchive -exportPath /Path/To/ipa/Output/Folder -exportOptionsPlist /Path/To/ExportOptions.plist
發(fā)現(xiàn)也不成功,老是報(bào)錯(cuò):

然后,搜了下日志和網(wǎng)頁(yè)發(fā)現(xiàn)是sqlite3沒(méi)有安裝的問(wèn)題:xcode 腳本打包報(bào)錯(cuò) error: exportArchive: The data couldn’t be read because it isn’t in the correct format
安裝了sqlite3之后,重啟電腦,在使用flutter build ipa命令就可以直接打出ipa的包來(lái)了
在進(jìn)行重簽名步驟,上傳蒲公英,下載安裝就妥妥滴了~