Enterprise OTA process succeeds but never shows "Loading" progress

We host an Enterprise app that we are distributing on behalf of our corporate client. Our corporate end users are not seeing the "Loading" phase when an app is installed. So it looks like the app is stuck in the "Waiting" phase, but it's really just downloading the app.

When we distribute a new beta app for testing, we use App Center. When downloading the IPA from App Center, the installation seems to go through all three phases normally:

  • "Waiting", with no progress indicator
  • "Loading", with the initial phase of a progress indicator
  • "Installing", with the last phase of the progress indicator.

This seems like the default behavior.

However, when downloading and installing the app from our deployment server directly, we only see two phases: "Waiting" (with no progress indicator), and "Installing". When the app is downloading, there is nothing to indicate that any download is taking place, it just looks frozen.

What could be causing this? Searching for a solution is difficult because lots of folks have the issue where a download is stuck in the "Waiting" phase. But this is not our problem, the install process is not stuck, it's just not showing the "Loading" phase to the end user.

And it doesn't appear to be a problem with the IPA, because the deployment process is working fine in App Center.

I thought that perhaps our server wasn't sending along a "content length" property, so the iPad wouldn't know how big the downloaded file is, but I checked and we're sending the content length property, and the content type appears to be identical between our server and App Center as well.

Any ideas on what could be causing this?

It looks like iOS sends a HEAD request for the IPA URL to determine the file size instead of just relying on the Content-Length header in the GET response. In my case, I ran into this issue because we were using pre-signed S3 URLs for our IPA files, but a pre-signed URL can only be signed for a GET or HEAD request, not both. (Which is an well-known unfortunate issue with pre-signed S3 URLs.)

I implemented a fairly hacky workaround for this. I added a new endpoint to our service and used that as the download URL within the manifest. For HEAD requests to this endpoint, I returned the correct Content-Length based on metadata from S3. For GET requests to this URL, I returned a 302 redirect to the actual pre-signed URL.

I haven't tested too thoroughly to know what the full impact of the change might be, but it seems to have fixed the loading indicator.

Long-term, we'll probably look at moving to signed CloudFront URLs, since from what I understand, you can sign a single URL for both GET and HEAD.

Enterprise OTA process succeeds but never shows "Loading" progress
 
 
Q