Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Programmatically tap on HTML href in order to update app

I'm planning updates for an enterprise app with ad-hoc distribution.

For updates, Apple recommends having the user visit an HTML page and tap on a link:

href="itms-services://?action=download-manifest&url=http://example.com/
manifest.plist"

See http://help.apple.com/iosdeployment-apps/#app43ad871e

I don't want to do this. I want the app to programmatically check for updates on launch and alert the user with a UIAlertView that an update is available.

Here's what I have so far in application didFinishLaunching. The complicated plist parsing comes from the structure of an example plist found here: http://help.apple.com/iosdeployment-apps/#app43ad78b3

NSLog(@"checking for update");
NSData *plistData = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://example.com/MyApp.plist"]];
if (plistData) {
    NSLog(@"finished checking for update");
    NSError *error;
    NSPropertyListFormat format;
    NSDictionary *plist = [NSPropertyListSerialization propertyListWithData:plistData options:NSPropertyListImmutable format:&format error:&error];
    if (plist) {
        NSArray *items = [plist valueForKey:@"items"];
        NSDictionary *dictionary;
        if ([items count] > 0) {
            dictionary = [items objectAtIndex:0];
        }
        NSDictionary *metaData = [dictionary objectForKey:@"metadata"];

        float currentVersion = [[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"] floatValue];
        float newVersion = [[metaData objectForKey:@"bundle-version"] floatValue];
        NSLog(@"newVersion: %f, currentVersion: %f", newVersion, currentVersion);
        if (newVersion > currentVersion) {
            NSLog(@"A new update is available");
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Update available" message:@"A new update is available." delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"UPDATE", nil];
            [alert show];
        }       
    }
}

Then I have my UIAlertView delegate method:

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (buttonIndex == 1) {
        NSLog(@"downloading full update");
        UIWebView *webView = [[UIWebView alloc] init];
        [webView loadRequest:[[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"itms-services://?action=download-manifest&url=http://example.com/MyApp.plist"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10.0]];
    }
}

A few things:

  • I know [alert show] shouldn't be called in application didFinish, but I'll change it later.
  • I don't know how quickly plistData will be downloaded and how this download affects the app.
  • More importantly, my alert view delegate method doesn't work, and the update doesn't download. Even when I introduce webView with @property (nonatomic, strong) UIWebView *webView, the method doesn't do anything.
  • I think Dropbox has the MIME configured properly because I can download the .ipa through google Chrome.

So what I really need is a way using NSURLConnection (NSURLRequest etc.) to replicate the act of a user tapping on an HTML href. After that I think the full update will occur.

like image 243
David Braun Avatar asked Feb 03 '12 22:02

David Braun


1 Answers

You can open a URL automatically using

[[UIApplication sharedApplication] openURL:...];

I don't know if it works for itms-services: urls, but it works for other bespoke URL schemes like tel:, fb: etc. so it should do unless Apple have specifically blocked it.

like image 58
Nick Lockwood Avatar answered Oct 12 '22 01:10

Nick Lockwood