views:

1621

answers:

6

Hi all,

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: http://stackoverflow.com/questions/641461/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.

A: 

This page explains how to use images from your bundle in a UIWebView.

Perhaps the same would work for a configuration profile as well.

Jon-Eric
Nope. And the funny part is, it's somehow the specifics of the profile. When I provide a text file with a link to it, the UIWebView navigates to it as expected.
Seva Alekseyev
A: 

Did you ever found a solution to this? i am trying to do the same thing

Sefi
Save for option D (upload to a public website), no.
Seva Alekseyev
I built a two-bit Web interface where the user can order the profile mailed to self. Same poop, really.
Seva Alekseyev
A: 

Have you tried just having the app mail the user the config profile the first time it starts up?

-(IBAction)mailConfigProfile {
     MFMailComposeViewController *email = [[MFMailComposeViewController alloc] init];
     email.mailComposeDelegate = self;

     [email setSubject:@"My App's Configuration Profile"];

     NSString *filePath = [[NSBundle mainBundle] pathForResource:@"MyAppConfig" ofType:@"mobileconfig"];  
     NSData *configData = [NSData dataWithContentsOfFile:filePath]; 
     [email addAttachmentData:configData mimeType:@"application/x-apple-aspen-config" fileName:@"MyAppConfig.mobileconfig"];

     NSString *emailBody = @"Please tap the attachment to install the configuration profile for My App.";
     [email setMessageBody:emailBody isHTML:YES];

     [self presentModalViewController:email animated:YES];
     [email release];
}

I made it an IBAction in case you want to tie it to a button so the user can re-send it to themselves at any time. Note that I may not have the correct MIME type in the example above, you should verify that.

smountcastle
Will give it a try. I'm not sure that an e-mail attachment in the process of mail composition is openable. Besides, instructing the users will be a pain. Has "desperate workaround" written all over it...
Seva Alekseyev
The user wouldn't open the attachment while composing. The work-flow would be launch your app, it realizes that the config profile isn't installed, it does the above to initiate the mail composition, the user types in their email address and hits send. Then they open Mail app and download the email, clicking on the attachment to install it.I agree that it seems like a desperate workaround. Alternatively you can figure out how Mail is dispatching the application/x-apple-aspen-config file and just do that (though it might be a private API, I don't know).
smountcastle
A: 

I've though of another way in which it might work (unfortunately I don't have a configuration profile to test out with):

// Create a UIViewController which contains a UIWebView
- (void)viewDidLoad {
    [super viewDidLoad];
    // Tells the webView to load the config profile
    [self.webView loadRequest:[NSURLRequest requestWithURL:self.cpUrl]];
}

// Then in your code when you see that the profile hasn't been installed:
ConfigProfileViewController *cpVC = 
        [[ConfigProfileViewController alloc] initWithNibName:@"MobileConfigView"
                                                      bundle:nil];
NSString *cpPath = [[NSBundle mainBundle] pathForResource:@"configProfileName"
                                                   ofType:@".mobileconfig"];
cpVC.cpURL = [NSURL URLWithString:cpPath];
// Then if your app has a nav controller you can just push the view 
// on and it will load your mobile config (which should install it).
[self.navigationController pushViewController:controller animated:YES];
[cpVC release];
smountcastle
That's a slight rephrasing of option B - instead of HTML, then link to profile, link to the profile straight away. I think I've tried this, unsuccessfully, along the way.
Seva Alekseyev
+1  A: 

I think what you are looking for is "Over the Air Enrollment" using the Simple Certificate Enrollment Protocol (SCEP). Have a look at the OTA Enrollment Guide and the SCEP Payload section of the Enterprise Deployment Guide.

According to the Device Config Overview you only have four options:

  • Desktop installation via USB
  • Email (attachment)
  • Website (via Safari)
  • Over-the-Air Enrollment and Distribution
slf
Looks like a fancier version of my option D :) Good find, though.
Seva Alekseyev
A: 

Question on the comment of smountcastle. The user wouldn't open the attachment while composing. The work-flow would be launch your app, it realizes that the config profile isn't installed, it does the above to initiate the mail composition, the user types in their email address and hits send. Then they open Mail app and download the email, clicking on the attachment to install it. I agree that it seems like a desperate workaround. Alternatively you can figure out how Mail is dispatching the application/x-apple-aspen-config file and just do that (though it might be a private API, I don't know). – smountcastle Apr 22 at 13:22

how would the app know/"realize" that the config profile isn't installed??

mamel
By the magic of asking the user if the VPN is available. :)
Seva Alekseyev