Can I force an iPhone user to upgrade an application?

IphoneApp Store-Connect

Iphone Problem Overview


Is it possible to force the user to upgrade once there is a new version of my application available in the iTunes Store?

I am presently working on an application. However, I want to force the upgrade whenever I upload a newer version, because the upgrade will have more features and I want to discard the previous version. Is this possible by default with iPhone or do I have to write my own implementation to check the current version and compare it to the store?

Iphone Solutions


Solution 1 - Iphone

I have done this feature by getting version from itunes webservice and comparing with the current version.. Following is my code

        NSString *version = @"";
        NSURL *url = [NSURL URLWithString:@"http://itunes.apple.com/lookup?id=<Your app ID>"];
        versionRequest = [ASIFormDataRequest requestWithURL:url];
        [versionRequest setRequestMethod:@"GET"];
        [versionRequest setDelegate:self];
        [versionRequest setTimeOutSeconds:150];
        [versionRequest addRequestHeader:@"Content-Type" value:@"application/json"]; 
        [versionRequest startSynchronous];
        
        //Response string of our REST call
        NSString* jsonResponseString = [versionRequest responseString];
        
        NSDictionary *loginAuthenticationResponse = [jsonResponseString objectFromJSONString];
        
        NSArray *configData = [loginAuthenticationResponse valueForKey:@"results"];
        
        for (id config in configData) 
        {
            version = [config valueForKey:@"version"];
        }
   //Check your version with the version in app store
        if (![version isEqualToString:[itsUserDefaults objectForKey:@"version"]]) 
        {
            ProAlertView *createUserResponseAlert = [[ProAlertView alloc] initWithTitle:@"New Version!!" message: @"A new version of app is available to download" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles: @"Download", nil];
        [createUserResponseAlert show]; 
        [createUserResponseAlert release];
        }

And put the app id in the itunes link see the code below..

- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
    // the user clicked one of the OK/Cancel buttons
    if (buttonIndex == 1)
    {
        NSString *iTunesLink = @"itms-apps://phobos.apple.com/WebObjects/MZStore.woa/wa/viewSoftwareUpdate?id=<appid>&mt=8";
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:iTunesLink]];
    }
}

Note : You need JSONKit frame work and ASIHttp frame work to make the webservice calls..

Solution 2 - Iphone

You can detect if the app needs an update then take some custom action like alert the user an update is available. Here is a code snippet that detects that an update is available.

-(BOOL) needsUpdate{
    NSDictionary* infoDictionary = [[NSBundle mainBundle] infoDictionary];
    NSString* appID = infoDictionary[@"CFBundleIdentifier"];
    NSURL* url = [NSURL URLWithString:[NSString stringWithFormat:@"http://itunes.apple.com/lookup?bundleId=%@", appID]];
    NSData* data = [NSData dataWithContentsOfURL:url];
    NSDictionary* lookup = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
    
    if ([lookup[@"resultCount"] integerValue] == 1){
        NSString* appStoreVersion = lookup[@"results"][0][@"version"];
        NSString* currentVersion = infoDictionary[@"CFBundleShortVersionString"];
        if (![appStoreVersion isEqualToString:currentVersion]){
            NSLog(@"Need to update [%@ != %@]", appStoreVersion, currentVersion);
            return YES;
        }
    }
    return NO;
}

Solution 3 - Iphone

If you absolutely have to, you can launch the App Store so that your users can get the latest version from there. I would recommend making this optional, or at least presenting a dialogue first.

// iTunesLink should be your applications link
NSString *iTunesLink = @"http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=284417350&mt=8";


[[UIApplication sharedApplication] openURL:[NSURL URLWithString:iTunesLink]];

Solution 4 - Iphone

This question was originally posted 7 years ago, and while some of the answers remain relevant, here is a more up-to-date approach.

I recommend https://github.com/ArtSabintsev/Siren which is Swift 3 compatible and can be installed with Cocoapods or Carthage.

CocoaPods, Swift 3 support:

Carthage:

Solution 5 - Iphone

There's no automated way to do it, you would have to write something manually.

Solution 6 - Iphone

The only way system handles updates of your application is prompting user that update is available in standard AppStore application.
Also, standalone application is not aware of available updates so you'll need to implement your web service where application can check if the current version is valid.
And I'm not sure if this conforms with Apple rules on applications, like (can't find proof-link though) you cannot upload trial versions for an application.

*** EDIT *** This answer is no longer true. See other upvoted answers for current truth.

Solution 7 - Iphone

A system for forced upgrades should be part of every application that has a dependance on something external to that application. Both Apple and Google claim that if an app uses something external then that external API should live forever, never change, etc., etc., but that's simply unrealistic. And if that's the case, if the services that the app depends on can change then there MUST be a way for the app to check and see if it should restrict functionality and prompt the user to get the latest version or things will simply mysteriously fail.

This could and should be something that Apple and Google provide, but they don't so every app outside of a few games needs to build this, SO...

I've started a rails based open-source (Apache 2.0) project to create a solution to this problem. It's called Application-[Ctrl], and it's very much a work in progress, but you are welcome to use it and I welcome contributions of any kind. If I can get this up and running in my spare time I'll provide this to all app developers with some very reasonable level of free service and of course every company will always be able to spin up it's own deployment.

It's here on GitHub: https://github.com/SlalomDigital/ApplicationCtrl

Contribute and help me solve this problem for good!

Solution 8 - Iphone

My app update to the App store was just rejected exactly for this reason. We added a feature to check the installed version against the current release and if it's not a supported version, we force them to update.

Apple rejected this.

So back to the design board!

Solution 9 - Iphone

Your business/design plan should never contain the phrase "force the user". People get angry when you make them do something. Imagine a user in a hurry who opens your nifty little app one morning only to discover you are forcing him to upgrade before he can use the app for what he needs. Imagine he's stuck out in the wilds having to use Edge to download. He won't be happy.

If you follow this plan long enough, one of your upgrades will inevitably introduce a noticeable bug. If you force users to use a buggy version they will rebel.

I have been conditioned by experience to cringe whenever I see "more features" used to describe a new version of software because this inevitably means feature bloat. Designers tend to keep grafting more and more features onto apps until one app does everything. This is particularly dangerous on a platform like the iPhone where making one app do to many things rapidly overwhelms the interface and the responsiveness of the app.

Edit01: My comment here https://stackoverflow.com/questions/2219734/how-to-update-an-application-after-users-pay-for-upgrade/2221999#2221999 might also be relevant to your plans. If your upgrade design cuts Apple out of the revenue loop, its a non-starter.

Update:

Just to clarify based on a comment below: Yes, sometimes you do have to require users to upgrade. However, that is much different from designing the app from the start to force users to upgrade every time the developer releases a new version.

Such a design is intended to make the developer's life easy and not the user's. Every time a user has to spend time upgrading for a benefit they did not ask for and perhaps do not want, you've taken time and resources from the customer. Design that offload time and effort from the developer to the user are bad designs because people ultimately buy software for their own benefit. When you decrease that benefit, you decrease the softwares ultimate profitability.

So, no designer should design software that forces the users to do something the user does not wish to unless it is an absolute technical necessity. This is of course a rule of thumb but it is a very good one.

Solution 10 - Iphone

The other answers indicate that one has to implement the forced updating functionality oneself. It's a shame really, I wish it wasn't so. My very first update to an iOS Application is to be released tomorrow, and fortunately it won't be problem, as we have only made changes to the app. However when we will eventually change the structure of our webservices, it would be really useful to be able to force updates, so that our server doesn't have to support each and every app version.

There is an alternative to forced updates however, which seems to be unmentioned in this thread. You could have every webservice call that produces data attach a schema to the data, which tells the app how that data should be deserialised in your app. This enables you to change the structure of data produced by get-requests without breaking deserialisation in the app. Of course this assumes that the interpreter that you write, will not itself change, but that is a somewhat reasonable assumption to make when it has matured.

Post requests could be "schema-fied" through interaction. With this I mean that before every post-request you make, you ask for instructions on how to call the up to date webservice. You process the instructions using an attached schema for that, and then you make the actual call to the webservice. Essentially this means that every post request requires 2 requests, but that can be okay.

However, no matter if you implement forced updating or schema interpretation the functionality has to be present in the app from day 1 when it hits the App Store. Otherwise you're in the same mess. All of this complexity would be unnecessary if Apple implemented forced updating for us developers. Schema interpretation would still be a usability improvement if forced updating existed though. But it bugs me a little that Apple doesn't have forced updating, because at least with it, one could introduce one's own anti-break updating measures after the app was released.

Solution 11 - Iphone

Hello for anyone in the future I found this tutorial which should help anyone, it helped me.

http://codewithchris.com/tutorial-how-to-implement-in-app-update-functionality-in-your-iphoneipad-app/

Edit (your code will look something similar to what's below):

// Try to get version 
NSString *versionNumber = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
 
NSURL *updateUrl = [NSURL URLWithString:@"http://yourdomain.com/yourupdatefile.xml"];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:updateUrl
                                            cachePolicy:NSURLCacheStorageNotAllowed
                                        timeoutInterval:20.0];
NSURLResponse *response = nil;
NSError *error = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:urlRequest
                                     returningResponse:&response
                                                 error:&error];
// Check no error, then parse data
if (error == nil)
{
    // Parse response into a dictionary
    NSPropertyListFormat format;
    NSString *errorStr = nil;
    NSDictionary *dictionary = [NSPropertyListSerialization propertyListFromData:data
                                                                mutabilityOption:NSPropertyListImmutable
                                                                          format:&format
                                                                errorDescription:&errorStr];        
    if (errorStr == nil)
    {
        @try {
            
            // Try to see if the current app version exists in the update xml
            NSString *itunesUrl = [dictionary objectForKey:versionNumber];
            
            if (itunesUrl)
            {
                // Show dialog to ask user to update!
            }
            else {
                // Version not in XML
            }
        } @catch (NSException *e) {
            // Error with retrieving the key
        }
    }
    else {
        // Error with parsing data into dictionary
    }
}

However, upon further research i've found this to be a great solution for if you aren't using a server.

-(BOOL) needsUpdate{
    NSDictionary* infoDictionary = [[NSBundle mainBundle] infoDictionary];
    NSString* appID = infoDictionary[@"CFBundleIdentifier"];
    NSURL* url = [NSURL URLWithString:[NSString stringWithFormat:@"http://itunes.apple.com/lookup?bundleId=%@", appID]];
    NSData* data = [NSData dataWithContentsOfURL:url];
    NSDictionary* lookup = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];

    if ([lookup[@"resultCount"] integerValue] == 1){
        NSString* appStoreVersion = lookup[@"results"][0][@"version"];
        NSString* currentVersion = infoDictionary[@"CFBundleShortVersionString"];
        if (![appStoreVersion isEqualToString:currentVersion]){
            NSLog(@"Need to update [%@ != %@]", appStoreVersion, currentVersion);
            return YES;
        }
    }
    return NO;
}

In the:

if (![appStoreVersion isEqualToString:currentVersion]){
                NSLog(@"Need to update [%@ != %@]", appStoreVersion, currentVersion);
                return YES;
            }

Portion of the code you set what you want to do if it's not equal, this is where you send the user to the app store to download the latest version.

Solution 12 - Iphone

func appUpdateAvailable() -> (Bool,String?) {
        
        guard let info = Bundle.main.infoDictionary,
              let identifier = info["CFBundleIdentifier"] as? String else {
            return (false,nil)
        }
        
//        let storeInfoURL: String = "http://itunes.apple.com/lookup?bundleId=\(identifier)&country=IN"
        let storeInfoURL:String = "https://itunes.apple.com/in/lookup?bundleId=\(identifier)"
        var upgradeAvailable = false
        var versionAvailable = ""
        // Get the main bundle of the app so that we can determine the app's version number
        let bundle = Bundle.main
        if let infoDictionary = bundle.infoDictionary {
            // The URL for this app on the iTunes store uses the Apple ID for the  This never changes, so it is a constant
            let urlOnAppStore = NSURL(string: storeInfoURL)
            if let dataInJSON = NSData(contentsOf: urlOnAppStore! as URL) {
                // Try to deserialize the JSON that we got
                if let dict: NSDictionary = try? JSONSerialization.jsonObject(with: dataInJSON as Data, options: JSONSerialization.ReadingOptions.allowFragments) as! [String: AnyObject] as NSDictionary? {
                    if let results:NSArray = dict["results"] as? NSArray {
                        if let version = (results[0] as! [String:Any])["version"] as? String {
                            // Get the version number of the current version installed on device
                            if let currentVersion = infoDictionary["CFBundleShortVersionString"] as? String {
                                // Check if they are the same. If not, an upgrade is available.
                                print("\(version)")
                                if version != currentVersion {
                                    upgradeAvailable = true
                                    versionAvailable = version
                                }
                            }
                        }
                    }
                }
            }
        }
        return (upgradeAvailable,versionAvailable)
    }

Solution 13 - Iphone

You can use below url to get the information of any app You just know your Apple ID of your app.

You can get this Apple ID in the itunesconnect.com>your app>app information page

GET: http://itunes.apple.com/lookup?id=<your apple ID>

Solution 14 - Iphone

You can check application build number with

> Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String

Then Compare with your force update version and if you want open Appstore.

if let url = URL(string: "https://apps.apple.com/tr/app/--id--") {
    UIApplication.shared.open(url)
}

Solution 15 - Iphone

Apple does not provide any automated way to do it, you would have to write manually.

option 1. Can use the iTunes API to check the latest version for that particular App id. and show the pop-up to update the app. option 2: you can use your own server to check the latest version. but you have to update your server whenever any update went to the apple app store.

Solution 16 - Iphone

Of course there is no way. The user should make the decision if he wants to download a newer version of your application or not.

The AppStore will display if there arenew versions, so I also do not think that Apple will allow this. Also I do not know how you would do this? You could check it via an internet connection, but that's not the way Apple likes and so you won't have a chance to do this.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNareshkumarView Question on Stackoverflow
Solution 1 - IphoneDilip RajkumarView Answer on Stackoverflow
Solution 2 - IphonedatincView Answer on Stackoverflow
Solution 3 - IphoneBadPirateView Answer on Stackoverflow
Solution 4 - IphoneJuan Carlos MéndezView Answer on Stackoverflow
Solution 5 - IphonekubiView Answer on Stackoverflow
Solution 6 - IphoneVladimirView Answer on Stackoverflow
Solution 7 - IphoneAaron CooleyView Answer on Stackoverflow
Solution 8 - IphoneSteigView Answer on Stackoverflow
Solution 9 - IphoneTechZenView Answer on Stackoverflow
Solution 10 - IphoneEmil Sørensen RaisView Answer on Stackoverflow
Solution 11 - IphoneC-H-E-FView Answer on Stackoverflow
Solution 12 - IphoneSahil OmerView Answer on Stackoverflow
Solution 13 - IphoneRuchin SomalView Answer on Stackoverflow
Solution 14 - IphoneEmircan UZELView Answer on Stackoverflow
Solution 15 - IphoneDivesh singhView Answer on Stackoverflow
Solution 16 - IphoneTimView Answer on Stackoverflow