web-dev-qa-db-fra.com

Comment utiliser la version payante de mon application comme "clé" de la version gratuite?

Disons par exemple que j'ai une application Android qui utilise X. La version gratuite contient des publicités ou des fonctionnalités de base. Je souhaite disposer d'une version payante qui supprime les annonces et ajoute des fonctionnalités supplémentaires.

Comment utiliser l'application payante en tant que "clé de licence" pour déverrouiller les fonctionnalités de l'application gratuite?

Ainsi, l’utilisateur installerait l’application gratuite, puis l’application payante pour obtenir les fonctionnalités supplémentaires, mais il exécuterait quand même l’application gratuite (qui serait désormais déverrouillée). Quelle est la meilleure approche pour le faire?

53
Bryan Denny

Utilisez PackageManager pour vous assurer que votre paquet payé est installé. ET assurez-vous que la signature de votre paquet gratuit correspond à la signature du paquet premium installé. Sinon, quelqu'un pourrait installer une application non signée avec un nom de paquet correspondant à votre nom de paquet payé et débloquer premium de cette façon.

Cet article peut vous aider à trouver votre signature Détecter si l'application a été téléchargée à partir d'Android Market

37
Fedor

J'utilise ceci:

PackageManager manager = getPackageManager();
if (manager.checkSignatures("core.package.name", "key.package.name")
    == PackageManager.SIGNATURE_MATCH) {
    //full version
}

C'est assez simple et ça marche.

20
David Vávra

Voici une fonction simple qui vérifie la présence de la clé Pro et vérifie que la signature du paquet correspond à la version gratuite:

protected static boolean isProInstalled(Context context) {
    PackageManager manager = context.getPackageManager();
    if (manager.checkSignatures(context.getPackageName(), "com.your.pro.key")
        == PackageManager.SIGNATURE_MATCH) {
        //Pro key installed, and signatures match
        return true;
    }
    return false;
}

Le code provient de cet article du forum , basé sur la méthode décrite à yoki.org .

8
David

Comme quelqu'un l'a fait remarquer, oui, vous pouvez utiliser PackageManager pour détecter la présence de l'application "clé" payante, mais cela pose problème si quelqu'un installe uniquement la version payante, désinstalle la version gratuite, etc. Les utilisateurs peuvent être ennuyés de devoir conserver autour de deux téléchargements pour que votre application fonctionne. FWIW, je pense que DoubleTwist Air Sync le fait de cette façon. Je suis à peu près sûr que l'application Air Sync ne fait rien sauf activer la fonctionnalité de l'application gratuite DoubleTwist.

Une solution plus pratique pourrait consister à créer deux applications distinctes, puis à importer des préférences et des données de l'une à l'autre à l'aide de ContentProvider et/ou sharedUserId . Vous pouvez ensuite partager la majeure partie de votre code en utilisant un projet de bibliothèque partagée . Cependant cela signifie que les deux applications doivent utiliser un URI de contenu différent, car deux applications ne peuvent pas utiliser la même autorité, ce qui est un peu pénible, car le code de votre bibliothèque partagée ne peut pas simplement avoir une valeur statique CONTENT_URI ou Champ AUTHORITY que vous trouverez normalement dans une implémentation de ContentProvider. 

Je commence à penser que la meilleure solution consiste à utiliser deux applications distinctes avec deux bases de code plus ou moins distinctes, car copier du code entre deux projets peut s'avérer plus simple que d'essayer de maintenir une bibliothèque partagée avec toutes sortes de commutateurs pour activer ou désactiver caractéristiques entre une version gratuite et payante. 

En fait, la recommandation d’edgman concernant l’utilisation d’une seule application et de l’utilisation de licences est probablement le meilleur moyen de gérer une version gratuite et payante d’une application. Il résout tous les problèmes énumérés ci-dessus, bien que pour être juste, je n'ai pas encore utilisé de licence moi-même.

EDITLes licences ne semblent être autorisées que pour les applications payantes (minable); il est donc inutile de proposer une version gratuite. Cependant, la facturation intégrée à l'application pourrait constituer le "bon" moyen de gérer une version gratuite/payante. Peut-être que c'est Ok pour l'OP, mais je n'ai pas envie d'exiger que deux applications soient toujours installées sur le périphérique d'un utilisateur, ce qui est idéal. Si un utilisateur payant installe l'application sur un nouvel appareil, il semble possible de télécharger des transactions antérieures pour ne pas avoir à payer deux fois.

7
thom_nic

À condition que les deux applications proviennent du même développeur et soient signées par la même clé, elles devraient pouvoir partager des informations en privé. Vous pourriez probablement utiliser un fichier (stocké avec MODE_PRIVATE) , Mais je pense que la solution la plus simple consiste à utiliser SharedPreferences - définissez un indicateur dans l'application payante qui sera lu par l'application gratuite. Voir  http://developer.Android.com/guide/topics/data/data-storage.html. Aucune idée s'il serait facile de le contourner, en particulier sur les périphériques rootés ...

Une autre solution consiste à vérifier si l'application payante est installée, par exemple en vérifiant si elle accepte une intention spécifique. Voir aussi: http://developer.Android.com/resources/articles/can-i-use-this-intent.html ; dans cet exemple, ils vérifient si le lecteur de codes à barres de ZXing est disponible de cette façon.

Dans tous les cas, une autre tournure sur l'idée serait que vous pouvez "activer" plusieurs applications avec un seul payant, si vous le souhaitez. Votre application payante serait un simple "soutien à ce développeur" qui supprimerait les publicités de toutes vos applications. C'est un modèle payant intéressant à mon humble avis.

3
Joubarc

Voici un exemple de la façon dont cela peut être fait:

Intent unlockerAppPresence = null;
APP_LITE_VERSION = false;
try 
{
    unlockerAppPresence = context.getPackageManager().getLaunchIntentForPackage("nameofthepackagethatunlockyoursoftware");
} 
catch (Exception e1) 
{
    APP_LITE_VERSION  = true;
}
if (unlockerAppPresence == null)
    APP_LITE_VERSION  = true;

Combinez cela avec la vérification de la signature du développeur de l'application (comme noté par @Fedor) et vous devriez être prêt à partir.

1
Bryan Denny

Qu'est-ce que absolut distribuant seulement une application gratuite/démo et mettre en œuvre in-app pour le rendre pro? Par conséquent, il ne restera plus qu’un seul utilisateur à installer, il pourra tester les fonctions de base et un bouton du type "passer à 1,99 €" pour appeler l’achat intégré à l’application. 

1
almisoft

Apparemment, je ne peux pas commenter sans 50 réputation, je vais donc mettre cela dans sa propre réponse.

La méthode PackageManager, citée par d’autres, semble être une solution simple et agréable, mais comme le mentionne hackbod, avoir deux applications installées est gênant (et un peu déroutant) pour l’utilisateur.

Cependant - et je n’ai pas essayé cela, car je n’ai pas encore publié mon application - il semble que vous puissiez conserver une variable qui commence par false, puis se mettre à true si la version Pro est installée. La variable ne redeviendrait pas false simplement parce que la version Pro n'y est pas. Ensuite, vous pouvez indiquer aux utilisateurs, dans les deux versions, qu'ils doivent installer Pro, puis ouvrir la version d'évaluation et cliquer sur Déverrouiller. Une fois que cela est fait, la version d'évaluation devient une version complète et vous informe (si elle trouve la version Pro installée) que vous pouvez maintenant désinstaller la version Pro et que vous aurez toujours un accès complet.

Quelque chose un peu comme ça:

String msg = "";
boolean sigMatch = isProInstalled(context);
if (unlocked)
{
    // If you get here by clicking a button that goes away once the app is unlocked, then you may never see this.  Still, better safe than sorry.
    msg += "Thanks!  You already have access to the full game.";
}
else
{
    if (sigMatch)
    {
        unlocked = true;
        saveData(); // I assume you already know how to store variables.
        msg += "Unlock successful.  You now have access to the full game."
    }
    else
    {
        msg += "You are using a Trial version of this game.  (blah, blah).  To unlock the full version, please purchase XYZ Pro.  Install the application and then start this application again and go into this screen again.  You should get a message letting you know that the app has been successfully unlocked, after which you may uninstall the Pro version.  You do not have to keep it on your device after unlocking the game.";
    }
}
if (sigMatch)
{
    msg += "  If you like, you may now uninstall the Pro application.  You will continue to have full access to XYZ.";
}

À présent, cela ne peut pas vous dire si l'utilisateur a payé pour la version Pro et l'a ensuite renvoyée dans les 24 heures, hackbod également mentionné est possible **, mais il semble que ce scénario ne se produise peut-être pas très souvent. Si quelqu'un paye et le retourne (surtout si vous ne chargez pas beaucoup), alors il a probablement décidé de ne plus utiliser l'application ... ou il essaie de la voler, auquel cas il existe d'autres moyens de le faire. Si cette possibilité vous concerne, la facturation intégrée peut être votre meilleur choix. Mais si vous recherchez uniquement une mesure simple permettant de garder les utilisateurs occasionnels et que vous ne voulez pas les forcer à conserver deux applications installées pour toujours, cette option est peut-être envisageable.

** Je suppose que vous pouvez conserver un horodatage avec une autre variable et demander à l'utilisateur de conserver la version Pro installée quelques heures après cet horodatage, ALORS lui permettre de désinstaller ...

0
parmeisan