Pergunta

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.

Foi útil?

Solução

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.

Outras dicas

Add an entitlements file to your project, and set its "get-task-allow" to "NO". I have had similar problems until I did that; OTA would sometimes work, and sometimes not. Even though Apple says that it should work without entitlements file, that does not seem to be the case anymore.

Make sure you set the "get-task-allow" back to "YES" for normal development/debugging.

For reference, here is the contents of the entitlements file:

<?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>keychain-access-groups</key>
    <array>
        <string>$(AppIdentifierPrefix)com.yourCompany.yourAppname</string>
    </array>
    <key>get-task-allow</key>
    <false/>
</dict>
</plist>

of course, you need to replace the "yourCompany.yourAppname" stuff with your app identifier.

I met this problem with diawi or testflight. Once it start not working, you should erase the partially downloaded app on the device.

Have you tried to send and install the certificates before the ipa ?

From my experience, there are a few steps to take care of this issue which many of us have experienced;

  1. Make sure your device UDID's are registered in the provisioning portal and linked to the provisioning profile you're signing with.

  2. Prior to signing the app (while compiling it using the "Archive" option), Refresh to the latest profiles available, possibly by erasing the old ones shown in the organizer and pressing "refresh" on the bottom, and logging in to your developer account.

  3. Set the signing identity to "Distribution" (Ad hoc). This will at least help if you compile it using "Build" and upload to a service like Diawi.  If you do use a service like Diawi, upload the mobile provisioning profile you signed with (the Ad-Hoc one), and have your users install it prior to installing the application, via the interface Diawi provides.

  4. Sign the app with a Ad-Hoc "Distribution" profile and not a "Development" profile - this is crucial!

Best of luck!

Try This select all third party libraries excluding your project in xcode and in the build settings set skip install to yes.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top