错误分析
开发环境如下:
- 操作系统:Mac OS X 10.10.5
- IDE:Xcode: Version 7.0(7A220)
刚开始,各种猜测,一一验证:
- 经过交叉对比的方法,看看是不是编译 APP 的时候,哪个地方的配置有问题。但是重新核对了之后,也没有发现不一样的地方;
- 发现不能安装的这两个 APP 和别的 APP 之间的差别:这两个不能在 iOS 9 上安装的 APP 下载的过程中没有图标显示,然后去后台manifest文件中添加了 display-image,结果发现下载过程中可以显示图标,但是还是不能安装成功;
- 怀疑服务器上的发布配置有问题,但是又找不到哪里错误;
- …
突然灵机一动,觉得可以通过了解安装失败的具体原因来分析,其实如果这个事情发生在 Android 上面的话,第一反应就应该是去查看日志,因为做了这么久的 Android 开发,已经很熟悉套路了。但是刚接触 iOS 开发,很多时候,容易收到思维的限制,潜意识认为 iOS 设备很多事情不可以做。
抓取安装过程中的 itunesstored 进程产生的日志:
20:40:09 flygoly itunesstored → <Warning>: [Download]: Download task did finish: 8 for download: 2325728577585828282
20:40:09 flygoly itunesstored → <Warning>: [ApplicationWorkspace] Installing download: 2325728577585828282 with step(s): Install
20:40:09 flygoly itunesstored → <Warning>: [ApplicationWorkspace]: Installing software package with bundleID: com.***.***: bundleVersion: 1.01 path: /var/mobile/Media/Downloads/2325728577585828282/-1925357977307433048
20:40:09 flygoly itunesstored → <Warning>: BundleValidator: Failed bundleIdentifier: com.***.**** does not match expected bundleIdentifier: com.***.*********
20:40:09 flygoly itunesstored → <Warning>: [ApplicationWorkspace]: Bundle validated for bundleIdentifier: com.****.******success: 0
20:40:09 flygoly itunesstored → <Warning>: LaunchServices: Uninstalling placeholder for app <LSApplicationProxy: 0x12677be70> com.****.*******(Placeholder) <file:///private/var/mobile/Containers/Bundle/Application/B62D8EA3-2052-4393-8A7E-3FD27228BFC2/2325728577585828282.app>
20:40:09 flygoly itunesstored → <Warning>: LaunchServices: Uninstalling app <LSApplicationProxy: 0x12677be70> com.****.*****(Placeholder) <file:///private/var/mobile/Containers/Bundle/Application/B62D8EA3-2052-4393-8A7E-3FD27228BFC2/2325728577585828282.app>
我们注意到有以下内容:
20:40:09 flygoly itunesstored → <Warning>: BundleValidator: Failed bundleIdentifier: com.***.**** does not match expected bundleIdentifier: com.***.*********
这说明 .ipa 文件的 Bundle ID 和 manifest 文件中配置的:bundle-identifier 不匹配。然后一核对,就发现果然是这个问题,修改成正确的 bundle-identifier 值之后,问题得到解决。
解决方法
解决这个问题的关键点:就是去查看安装过程中的日志,它会告诉你安装过程出错的原因。同时要注意的就是:iOS 9 对于企业版的APP下载安装的过程,更加严格的校验 manifest 文件。
以下内容引用自:The iOS 5 Developer’s Cookbook: Building Your First Project:
Over-the-Air Ad Hoc Distribution
You can distribute ad hoc ipa files over the air by creating links to a simple webpage. The itms-services: URL scheme, when pointing to an application manifest property list allows your users to install apps wirelessly. You provide the ipa and the manifest on the website. Here’s how you might link to the manifest.
<a href="itms-services://?action=download-manifest&
url=http://example.com/manifest.plist">Install App</a>
Make sure your website is configured to support the following two MIME types.
application/octet-stream ipa
text/xml plist
Building a Manifest
The manifest is an XML-based property list. It must contain six key/value pairs:
- URL
- a fully- qualified URL pointing to the ipa file
- display-image
- fully-qualified URL pointing to a 57×57-pixel PNG icon used during download and installation
- full-size-image
- a fully-qualified URL pointing to a 512×512-pixel PNG (not JPEG!) image that represents the iTunes app
- bundle-identifier
- the app’s standard application identifier string, as specified in the app’s Info.plist file
bundle-version— the app’s current bundle version string, as specified in the app’s Info.plist file
title— a human-readable application nam
- the app’s standard application identifier string, as specified in the app’s Info.plist file
In addition to these required keys, you can specify an optional md5 hash for file elements. Listing 3-3 shows a sample manifest provided by Apple.
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- array of downloads. -->
<key>items</key>
<array>
<dict>
<!-- an array of assets to download -->
<key>assets</key>
<array>
<!-- software-package: the ipa to install. -->
<dict>
<!-- required. the asset kind. -->
<key>kind</key>
<string>software-package</string>
<!-- optional. md5 every n bytes. -->
<!-- will restart a chunk if md5 fails. -->
<key>md5-size</key>
<integer>10485760</integer>
<!-- optional. array of md5 hashes -->
<key>md5s</key>
<array>
<string>41fa64bb7a7cae5a46bfb45821ac8bba</string>
<string>51fa64bb7a7cae5a46bfb45821ac8bba</string>
</array>
<!-- required. the URL of the file to download. -->
<key>url</key>
<string>http://www.example.com/apps/foo.ipa</string>
</dict>
<!-- display-image: the icon to display during download. -->
<dict>
<key>kind</key>
<string>display-image</string>
<!-- optional. icon needs shine effect applied. -->
<key>needs-shine</key>
<true/>
<key>url</key>
<string>http://www.example.com/image.57×57.png</string>
</dict>
<!-- full-size-image: the large 512×512 icon used by iTunes. -->
<dict>
<key>kind</key>
<string>full-size-image</string>
<!-- optional. one md5 hash for the entire file. -->
<key>md5</key>
<string>61fa64bb7a7cae5a46bfb45821ac8bba</string>
<key>needs-shine</key>
<true/>
<key>url</key>
<string>http://www.example.com/image.512×512.jpg</string>
</dict>
</array><key>metadata</key>
<dict>
<!-- required -->
<key>bundle-identifier</key>
<string>com.example.fooapp</string>
<!-- optional (software only) -->
<key>bundle-version</key>
<string>1.0</string>
<!-- required. the download kind. -->
<key>kind</key>
<string>software</string>
<!-- optional. displayed during download; -->
<!-- typically company name -->
<key>subtitle</key>
<string>Apple</string>
<!-- required. the title to display during the download. -->
<key>title</key>
<string>Example Corporate App</string>
</dict>
</dict>
</array>
</dict>
</plist>
如果觉得文章对你有帮助,欢迎赞赏支持
