Iphone – Installing a configuration profile on iPhone – programmatically

cocoa-touchconfiguration-filesios-simulatoriphone

I would like to ship a configuration profile with my iPhone application, and install it if needed.

Mind you, we're talking about a configuration profile, not a provisioning profile.

First off, such a task is possible. If you place a config profile on a Web page and click on it from Safari, it will get installed. If you e-mail a profile and click the attachment, it will install as well. "Installed" in this case means "The installation UI is invoked" – but I could not even get that far.

So I was working under the theory that initiating a profile installation involves navigating to it as a URL. I added the profile to my app bundle.

A) First, I tried [sharedApp openURL] with the file:// URL into my bundle. No such luck – nothing happens.

B) I then added an HTML page to my bundle that has a link to the profile, and loaded it into a UIWebView. Clicking on the link does nothing. Loading an identical page from a Web server in Safari, however, works fine – the link is clickable, the profile installs. I provided a UIWebViewDelegate, answering YES to every navigation request – no difference.

C) Then I tried to load the same Web page from my bundle in Safari (using [sharedApp openURL] – nothing happens. I guess, Safari cannot see files inside my app bundle.

D) Uploading the page and the profile on a Web server is doable, but a pain on the organizational level, not to mention an extra source of failures (what if no 3G coverage? etc.).

So my big question is: **how do I install a profile programmatically?

And the little questions are: what can make a link non-clickable within a UIWebView? Is it possible to load a file:// URL from my bundle in Safari? If not, is there a local location on iPhone where I can place files and Safari can find them?

EDIT on B): the problem is somehow in the fact that we're linking to a profile. I renamed it from .mobileconfig to .xml ('cause it's really XML), altered the link. And the link worked in my UIWebView. Renamed it back – same stuff. It looks as if UIWebView is reluctant to do application-wide stuff – since installation of the profile closes the app. I tried telling it that it's OK – by means of UIWebViewDelegate – but that did not convince. Same behavior for mailto: URLs within UIWebView.

For mailto: URLs the common technique is to translate them into [openURL] calls, but that doesn't quite work for my case, see scenario A.

For itms: URLs, however, UIWebView works as expected…

EDIT2: tried feeding a data URL to Safari via [openURL] – does not work, see here: iPhone Open DATA: Url In Safari

EDIT3: found a lot of info on how Safari does not support file:// URLs. UIWebView, however, very much does. Also, Safari on the simulator open them just fine. The latter bit is the most frustrating.


EDIT4: I never found a solution. Instead, I put together a two-bit Web interface where the users can order the profile e-mailed to them.

Best Answer

1) Install a local server like RoutingHTTPServer

2) Configure the custom header :

[httpServer setDefaultHeader:@"Content-Type" value:@"application/x-apple-aspen-config"];

3) Configure the local root path for the mobileconfig file (Documents):

[httpServer setDocumentRoot:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]];

4) In order to allow time for the web server to send the file, add this :

Appdelegate.h

UIBackgroundTaskIdentifier bgTask;

Appdelegate.m
- (void)applicationDidEnterBackground:(UIApplication *)application {
    NSAssert(self->bgTask == UIBackgroundTaskInvalid, nil);
    bgTask = [application beginBackgroundTaskWithExpirationHandler: ^{
        dispatch_async(dispatch_get_main_queue(), ^{
            [application endBackgroundTask:self->bgTask];
            self->bgTask = UIBackgroundTaskInvalid;
        });
    }];
}

5) In your controller, call safari with the name of the mobileconfig stored in Documents :

[[UIApplication sharedApplication] openURL:[NSURL URLWithString: @"http://localhost:12345/MyProfile.mobileconfig"]];