web-dev-qa-db-fra.com

Puis-je forcer un utilisateur d'iPhone à mettre à niveau une application?

Est-il possible de forcer l'utilisateur à mettre à niveau une fois qu'une nouvelle version de mon application est disponible sur l'iTunes Store?

Je travaille actuellement sur une application. Cependant, je souhaite forcer la mise à niveau chaque fois que je télécharge une version plus récente, car la mise à niveau comportera davantage de fonctionnalités et je souhaite supprimer la version précédente. Est-ce possible par défaut avec iPhone ou dois-je écrire ma propre implémentation pour vérifier la version actuelle et la comparer au magasin?

43
Nareshkumar

Le seul moyen utilisé par le système pour gérer les mises à jour de votre application est d'inviter l'utilisateur à la mettre à jour dans l'application AppStore standard.
En outre, une application autonome n’est pas informée des mises à jour disponibles, vous devez donc implémenter votre service Web pour que l’application puisse vérifier si la version actuelle est valide.
Et je ne suis pas sûr que cela soit conforme aux règles Apple sur les applications, comme (vous ne pouvez pas trouver de preuve-lien cependant), vous ne pouvez pas télécharger de version d'évaluation pour une application.

* EDIT * Cette réponse n'est plus vraie. Voir d'autres réponses plus votées pour la vérité actuelle.

4
Vladimir

J'ai utilisé cette fonctionnalité en obtenant la version du service Web iTunes et en la comparant avec la version actuelle. Voici mon 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];
        }

Et mettez l'identifiant de l'application dans le lien iTunes, voir le code ci-dessous.

- (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]];
    }
}

Remarque: vous avez besoin des travaux sur les cadres JSONKit et ASIHttp pour passer les appels de service Web.

34
Dilip Rajkumar

Vous pouvez détecter si l'application nécessite une mise à jour, puis entreprendre une action personnalisée, par exemple avertir l'utilisateur qu'une mise à jour est disponible. Voici un extrait de code qui détecte qu'une mise à jour est disponible. 

-(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;
}
20
datinc

Si vous devez absolument, vous pouvez lancer l'App Store pour que vos utilisateurs puissent obtenir la dernière version à partir de là. Je recommanderais de rendre cette option facultative, ou du moins de commencer par un dialogue.

// 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]];
18
BadPirate

Cette question avait été posée il y a 7 ans et, même si certaines des réponses restent pertinentes, voici une approche plus moderne. 

Je recommande https://github.com/ArtSabintsev/Siren compatible avec Swift 3 et pouvant être installé avec Cocoapods ou Carthage.

Soutien de CocoaPods, Swift 3:

pod 'Siren'

Carthage:

github "ArtSabintsev/Siren"

9

Un système pour les mises à niveau forcées devrait faire partie de chaque application dépendant de quelque chose de externe à cette application. Apple et Google affirment tous deux que si une application utilise quelque chose d'extérieur, cette API externe devrait vivre éternellement, ne jamais changer, etc., etc., mais c'est tout simplement irréaliste. Et si tel est le cas, si les services dont dépend l’application peuvent changer, alors DOIT être un moyen pour l’application de vérifier si elle doit restreindre les fonctionnalités et inviter l’utilisateur à obtenir la dernière version les choses vont simplement échouer mystérieusement.

Cela pourrait et devrait être quelque chose que Apple et Google fournissent, mais ils ne le font pas donc chaque application en dehors de quelques jeux doit construire cela, SO ...

J'ai démarré un projet open-source (Apache 2.0) basé sur Rails pour créer une solution à ce problème. Il s’appelle Application- [Ctrl], et c’est vraiment un travail en cours, mais vous êtes le bienvenu. Vous pouvez l’utiliser et toutes les contributions que je souhaite sont les bienvenues. Si je parviens à le faire fonctionner pendant mon temps libre, je le fournirai à tous les développeurs d'applications avec un niveau de service gratuit très raisonnable et, bien entendu, chaque entreprise sera toujours en mesure de mettre en place son propre déploiement.

C'est ici sur GitHub: https://github.com/SlalomDigital/ApplicationCtrl

Contribuez et aidez-moi à résoudre ce problème pour de bon! _

5
Aaron Cooley

Votre entreprise/plan de conception ne devrait jamais contenir la phrase "forcer l'utilisateur". Les gens se fâchent quand on leur fait faire quelque chose. Imaginez un utilisateur pressé qui ouvre votre petite application géniale un matin pour découvrir que vous le forcez à effectuer une mise à niveau avant de pouvoir utiliser l'application pour répondre à ses besoins. Imaginez qu'il soit coincé dans la nature en train d'utiliser Edge pour le téléchargement. Il ne sera pas heureux. 

Si vous suivez ce plan suffisamment longtemps, l’une de vos mises à niveau introduira inévitablement un bogue perceptible. Si vous forcez les utilisateurs à utiliser une version buggy, ils se rebelleront. 

L’expérience me conditionne à ne plus avoir recours à «plus de fonctionnalités» pour décrire une nouvelle version de logiciel, car cela signifie inévitablement une fonctionnalité épatante. Les concepteurs ont tendance à greffer de plus en plus de fonctionnalités sur les applications jusqu'à ce qu'une application fasse tout. Cela est particulièrement dangereux sur une plate-forme telle que l'iPhone, où une seule application modifie rapidement l'interface et la réactivité de l'application. 

Edit01: Mon commentaire ici Comment mettre à jour une application après que les utilisateurs ont payé pour la mise à niveau pourrait également être pertinent pour vos plans. Si la conception de votre mise à niveau exclut Apple de la boucle des revenus, il ne s'agit pas d'un démarreur. 

Mettre à jour:

Juste pour clarifier basé sur un commentaire ci-dessous: Oui, parfois vous devez obliger les utilisateurs à mettre à jour. Cependant, cela diffère beaucoup de conception de l'application depuis le début _ pour obliger les utilisateurs à effectuer la mise à niveau chaque fois que le développeur publie une nouvelle version. 

Une telle conception est destinée à faciliter la vie du développeur et non à l'utilisateur. Chaque fois qu'un utilisateur doit consacrer du temps à la mise à niveau pour obtenir un avantage qu'il n'a pas demandé et qu'il ne souhaite peut-être pas, le client prend du temps et des ressources. Concevoir le temps et les efforts consacrés du développeur à l'utilisateur est une mauvaise conception car les utilisateurs finissent par acheter des logiciels pour leur propre bénéfice. Lorsque vous diminuez cet avantage, vous diminuez la rentabilité finale des logiciels. 

Ainsi, aucun concepteur ne devrait concevoir un logiciel qui oblige les utilisateurs à faire quelque chose qu'ils ne souhaitent pas, sauf s'il s'agit d'une nécessité technique absolue. C’est bien sûr une règle de base mais c’est une très bonne règle. 

4
TechZen

Ma mise à jour de l'application sur l'App Store a été rejetée pour cette raison. Nous avons ajouté une fonctionnalité permettant de vérifier la version installée par rapport à la version actuelle. Si ce n'est pas une version prise en charge, nous les forçons à mettre à jour. 

Apple a rejeté cela.

Revenons donc au tableau de conception!

4
Steig

Les autres réponses indiquent qu'il faut implémenter soi-même la fonctionnalité de mise à jour forcée ... C'est vraiment dommage, j'aimerais bien que ce ne soit pas le cas ... ... Ma toute première mise à jour d'une application iOS doit être publiée demain, et heureusement. ce ne sera pas un problème, car nous n’avons apporté que des modifications à l’application . Cependant, lorsque nous modifierons en fin de compte la structure de nos services Web, il serait très utile debe pouvoir forcer les mises à jour, de sorte que notre serveur n'a pas à supporter chaque version de l'application.

Il existe cependant une alternative aux mises à jour forcées, qui semble ne pas être mentionnée dans ce fil de discussion . Chaque appel de service Web produisant des données peut associer un schéma aux données, , Qui indique à l'application comment désérialiser ces données. dans votre application . Cela vous permet de modifier la structure des données générées par get-request sans interrompre la désérialisation dans l'application . Bien entendu, cela suppose que l'interprète que vous écrivez ne changera pas, mais une hypothèse assez raisonnable à faire à l’échéance.

Les demandes de publication peuvent être "schématisées" par interaction . Cela signifie qu'avant chaque demande ultérieure, vous demandez des instructions sur la façon d'appeler le service Web à jour . Vous traitez les instructions à l'aide de un schéma attaché pour cela, puis vous effectuez l'appel réel vers le service Web . Cela signifie essentiellement que chaque demande de publication nécessite 2 demandes, mais cela peut convenir.

Toutefois, peu importe si vous implémentez une mise à jour forcée ou une interprétation de schéma, la fonctionnalité doit être présente dans l'application dès le premier jour lorsque celle-ci se connecte à l'App Store ..__ Sinon, vous êtes dans le même pétrin. Toute cette complexité serait inutile si Apple implémentait la mise à jour forcée pour nous, les développeurs . L'interprétation des schémas serait encore une amélioration de la facilité d'utilisation si la mise à jour forcée existait bien . , car au moins avec cela, on pourrait introduire ses propres mesures de mise à jour anti-rupture après la sortie de l'application.

3

Il n'y a pas de moyen automatisé de le faire, il faudrait écrire quelque chose manuellement.

3
kubi

Bonjour à tout le monde à l'avenir, j'ai trouvé ce tutoriel qui devrait aider n'importe qui, il m'a aidé. 

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

Modifier (votre code ressemblera à ce qui est ci-dessous):

// 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
    }
}

Cependant, après des recherches plus poussées, j'ai trouvé que c'était une excellente solution pour ceux qui n'utilisent pas de serveur. 

-(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;
}

Dans le:

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

Partie du code que vous définissez ce que vous voulez faire si ce n'est pas égal, c'est ici que vous envoyez l'utilisateur sur l'App Store pour télécharger la dernière version.

1
C-H-E-F

Vous pouvez utiliser l'URL ci-dessous pour obtenir les informations relatives à n'importe quelle application.

Vous pouvez obtenir cet identifiant Apple dans la page d'informations itunesconnect.com> votre application>

GET: http://iTunes.Apple.com/lookup?id=

0
Ruchin Somal