I'm having trouble with over the air (OTA) distribution for my Ad-Hoc builds. Building a universal iPhone/iPad app with base SDK 6.1, deployment target 5.0, architectures armv7 and armv7s. The very same ad-hoc build installs OTA on iOS 6 devices (3 different iPhone5, one iPhone4 and iPad2), but fails to install OTA on iOS 5 devices (iPhone4S and iPad1).
The OTA happens via IIS with all MIME types set properly (otherwise it would fail for iOS 6).
On iOS 5 devices it starts installation showin app icon with progress bar, first title is "Waiting...", then changes to app name, then alert view shows up saying
Unable to Download Application
could not be downloaded at this time.
Done/Retry
Connected device to Xcode to see logs in organizer. Console has the following:
apsd[48] : : Stream error occurred for : Error Domain=NSPOSIXErrorDomain Code=61 "The operation couldn’-t -b-e -c-o-m-p-l-e-t-e-d-. -C-o-n-n-e-c-t-i-o-n -r-e-f-u-s-e-d-" -U-s-e-r-I-n-f-o-=-0-x-1-4-7-0-8-0 -{-}
Exactly like that, including "-" characters.
Installing same ad-hoc build on same iOS 5 devices via iTunes sync works as expected, no errors.
Account type is a "plain" developer account, not Enterprise.
I already tried to create all provisioning profiles from scratch. Didn't try to delete and create new certificates yet, hope it's not required.
App does not use iCloud or Pushes, or anything. No Entitlements.plist is included into the bundle.
Might be important to mention the fact that app is build with CocoaPods - a bunch of 3rd party libraries built as Pods target.
Well, you will sure be surprised to find out what an actual reason is.
I ended up revoking all certificates, removing profiles, going all the way from CSR to setting up a build environment. I did experiment with entitlements and 'get-task-allow' and other stuff. But none of that did the trick.
At some point I decided to have another look at IIS server and plist file used for distribution.
So here it goes, the problem was with plist file.
The iTunes artwork image file was named "iTunesArtwork.png", the url in plist file was http://hostname/Mobile/iOS/iTunesArtwork
.
So I renamed the file to "iTunesArtwork" (removed extension), that didn't fix the problem, but I could now see the installation progress bar getting almost to the end and status message changing from "Downloading" to "Installing". Before that it failed at the very beginning, right after saying "Wait".
Finally, I put all that stuff in order, named the file "iTunesArtwork.png" and fixed url to be http://hostname/Mobile/iOS/iTunesArtwork.png
And that's when it worked.
I could only come up with the following explanation:
Before an installation starts, iOS is checking if all urls in plist point to valid resources. If any of that fails, iOS 5 aborts installation, while iOS 6 can at least tolerate invalid artwork url.
During an installation, iOS first fetches app icon to display it on the screen, then downloads the ipa file, and in the end fetches artwork. Here, again, iOS 5 has stricter validation rules, it won't like names like 'iTunesArtwork', I think it just doesn't like file name with no extension. If fetching artwork fails the whole installation on iOS 5 is aborted. iOS 6 seems to ignore errors at this stage.
I personally think that iOS 5 does it the right way. It is a good thing to validate that all urls are valid and all files have proper extension. If both iOS versions did it the same way, I would stumble upon the problem at the very beginning.
UPD
Just tried with apache web server setup running on Mac OS X 10.8. Can tell for sure, unlike IIS, with apache iOS 5 tolerates missing extensions quite well, so it's not just iOS 5, but a mix of iOS 5 and IIS that causes all the trouble.
However, if I put stuff like http://hostname/Mobile/iOS/NoSuchFile
in plist in place of artwork, then iOS 5 will fail to install OTA, while iOS 6 won't even notice a thing and proceed with installation.