Déterminer si l'application Android est utilisée pour la première fois

112

Je développe actuellement une application Android. J'ai besoin de faire quelque chose lorsque l'application est lancée pour la première fois, c'est-à-dire que le code ne s'exécute qu'au premier lancement du programme.

Boardy
la source
1
Quand j'ai commencé à créer des applications, je ne pensais qu'à la première exécution après l'installation d'une application. J'ai réalisé plus tard que je devais également gérer et différencier les premières exécutions après les mises à niveau. La réponse de @ schnatterer ci-dessous et ma réponse ici montrent comment faire cela. Méfiez-vous des réponses qui ne tiennent pas compte des mises à niveau.
Suragch
@Suragch vous agissez comme si c'était une mauvaise pratique de ne pas prendre en compte les mises à niveau, mais dans certains cas, comme avoir une introduction d'application, vous ne voulez PAS le faire :)
creativecreatorormaybenot
@creativecreatorormaybenot, c'est vrai. Il y a des moments où vous ne vous souciez que de l'installation initiale et non des mises à niveau ultérieures. Un simple booléen suffit pour ces situations. Cependant, que se passe-t-il si à un moment donné dans le futur vous souhaitez ajouter une introduction différente pour les utilisateurs actuels sur toutes les nouvelles fonctionnalités que vous venez d'ajouter dans la dernière mise à jour? À mon avis, il est plus clairvoyant de vérifier le numéro de version plutôt qu'un booléen. Cela vous donne au moins la possibilité à l'avenir de répondre d'une manière pour une nouvelle installation et d'une autre manière pour une mise à niveau.
Suragch le
1
Ensuite, vous l'ajoutez simplement pour cette version mais je reçois yoz
creativecreatorormaybenot
Vous pouvez consulter ce stackoverflow.com/a/7217834/2689076
Vaibhav

Réponses:

56

Une autre idée consiste à utiliser un paramètre dans les préférences partagées. Même idée générale que de rechercher un fichier vide, mais vous n'avez pas de fichier vide flottant, n'étant pas utilisé pour stocker quoi que ce soit

Kevin Dion
la source
3
attention, ce genre d'approche ne pourrait pas fonctionner sur un Samsung Galaxy S avec Android Froyo. C'est à cause d'un bogue dans l'enregistrement de SharedPreferences. Voici un lien vers une question SO à ce sujet: stackoverflow.com/questions/7296163/… et voici le ticket sur google code: code.google.com/p/android/issues/detail?id=14359
Francesco Rigoni
4
Attention pour Android 6.0 (API 23 - Marshmallow) ou supérieur, la sauvegarde automatique ( developer.android.com/guide/topics/data/autobackup.html) est activée par défaut. Si les utilisateurs désinstalle puis réinstalle l'application, les préférences partagées seront récupérées. Ainsi, lors des réinstallations, vous ne pouvez pas vérifier s'il est en cours d'exécution pour la première fois après la réinstallation si cela pose un problème.
Alan
1
@Alan vous avez raison, cette réponse n'est plus valable depuis Android Marshmallow.
Ioane Sharvadze
1
@Alan vous ne pouvez pas imaginer combien de temps je cherchais une réponse comme la vôtre. Tu as fait ma journée. Merci!
Antonio
@Alan Mais la sauvegarde automatique enregistre également la plupart des autres données. On s'attend donc à ce que l'application réinstallée soit dans un état de non-première exécution. Et l'utilisateur a déjà utilisé l'application auparavant, il n'y a donc pas besoin de conseils. Je dirais donc que dans la plupart des cas, c'est une bonne chose que cela se produise.
smdufb
112

Vous pouvez utiliser les SharedPreferences pour identifier si c'est la «première fois» que l'application est lancée. Utilisez simplement une variable booléenne ("my_first_time") et changez sa valeur en false lorsque votre tâche pour la "première fois" est terminée.

Voici mon code pour attraper la première fois que vous ouvrez l'application:

final String PREFS_NAME = "MyPrefsFile";

SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);

if (settings.getBoolean("my_first_time", true)) {
    //the app is being launched for first time, do something        
    Log.d("Comments", "First time");

             // first time task

    // record the fact that the app has been started at least once
    settings.edit().putBoolean("my_first_time", false).commit(); 
}
harrakiss
la source
17
Sera-t-il géré lorsque l'application sera mise à jour vers la prochaine version sur le Google Play Store?
Shajeel Afzal
4
Les préférences partagées sont conservées pendant la mise à niveau. Donc, je suppose que lors de sa mise à niveau à partir de PlayStore, l'ancienne valeur est disponible. En fait, il est applicable pour d'autres méthodes, c'est-à-dire vérifier l'existence d'un fichier aussi. Ainsi, la méthode de raccourci dans ce cas consiste à utiliser une préférence / un nom de fichier ou une valeur différents.
Tejasvi Hegde
@ShajeelAfzal quelque chose comme ça peut vous aider public void CheckAndInitAppFirstTime () {final String PREFS_NAME = "TheAppVer"; chaîne finale CHECK_VERSION = "1"; // Requis ver ... final String KEY_NAME = "CheckVersion"; Paramètres SharedPreferences = getSharedPreferences (PREFS_NAME, 0); if (! settings.getString (KEY_NAME, "0"). equals (CHECK_VERSION)) {// l'application est lancée pour la première fois, faites quelque chose ou CHECK_VERSION est différent // ... settings.edit (). putString ( KEY_NAME, CHECK_VERSION) .commit (); }}
Tejasvi Hegde
@aman verma: selon la description getBoolean sur developer.android.com/reference/android/content/… Le deuxième paramètre de getBoolean est la valeur par défaut si le premier paramètre ne se ferme pas, donc si "my_first_time" n'a pas été défini l'expression par défaut est true.
user2798692
63

Je suggère de stocker non seulement un drapeau booléen, mais le code de version complet. De cette façon, vous pouvez également demander au début s'il s'agit du premier démarrage d'une nouvelle version. Vous pouvez utiliser ces informations pour afficher une boîte de dialogue "Quoi de neuf", par exemple.

Le code suivant doit fonctionner à partir de n'importe quelle classe Android qui "est un contexte" (activités, services, ...). Si vous préférez l'avoir dans une classe distincte (POJO), vous pouvez envisager d'utiliser un "contexte statique", comme décrit ici par exemple.

/**
 * Distinguishes different kinds of app starts: <li>
 * <ul>
 * First start ever ({@link #FIRST_TIME})
 * </ul>
 * <ul>
 * First start in this version ({@link #FIRST_TIME_VERSION})
 * </ul>
 * <ul>
 * Normal app start ({@link #NORMAL})
 * </ul>
 * 
 * @author schnatterer
 * 
 */
public enum AppStart {
    FIRST_TIME, FIRST_TIME_VERSION, NORMAL;
}

/**
 * The app version code (not the version name!) that was used on the last
 * start of the app.
 */
private static final String LAST_APP_VERSION = "last_app_version";

/**
 * Finds out started for the first time (ever or in the current version).<br/>
 * <br/>
 * Note: This method is <b>not idempotent</b> only the first call will
 * determine the proper result. Any subsequent calls will only return
 * {@link AppStart#NORMAL} until the app is started again. So you might want
 * to consider caching the result!
 * 
 * @return the type of app start
 */
public AppStart checkAppStart() {
    PackageInfo pInfo;
    SharedPreferences sharedPreferences = PreferenceManager
            .getDefaultSharedPreferences(this);
    AppStart appStart = AppStart.NORMAL;
    try {
        pInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
        int lastVersionCode = sharedPreferences
                .getInt(LAST_APP_VERSION, -1);
        int currentVersionCode = pInfo.versionCode;
        appStart = checkAppStart(currentVersionCode, lastVersionCode);
        // Update version in preferences
        sharedPreferences.edit()
                .putInt(LAST_APP_VERSION, currentVersionCode).commit();
    } catch (NameNotFoundException e) {
        Log.w(Constants.LOG,
                "Unable to determine current app version from pacakge manager. Defenisvely assuming normal app start.");
    }
    return appStart;
}

public AppStart checkAppStart(int currentVersionCode, int lastVersionCode) {
    if (lastVersionCode == -1) {
        return AppStart.FIRST_TIME;
    } else if (lastVersionCode < currentVersionCode) {
        return AppStart.FIRST_TIME_VERSION;
    } else if (lastVersionCode > currentVersionCode) {
        Log.w(Constants.LOG, "Current version code (" + currentVersionCode
                + ") is less then the one recognized on last startup ("
                + lastVersionCode
                + "). Defenisvely assuming normal app start.");
        return AppStart.NORMAL;
    } else {
        return AppStart.NORMAL;
    }
}

Il pourrait être utilisé à partir d'une activité comme celle-ci:

public class MainActivity extends Activity {        
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        switch (checkAppStart()) {
        case NORMAL:
            // We don't want to get on the user's nerves
            break;
        case FIRST_TIME_VERSION:
            // TODO show what's new
            break;
        case FIRST_TIME:
            // TODO show a tutorial
            break;
        default:
            break;
        }

        // ...
    }
    // ...
}

La logique de base peut être vérifiée à l'aide de ce test JUnit:

public void testCheckAppStart() {
    // First start
    int oldVersion = -1;
    int newVersion = 1;
    assertEquals("Unexpected result", AppStart.FIRST_TIME,
            service.checkAppStart(newVersion, oldVersion));

    // First start this version
    oldVersion = 1;
    newVersion = 2;
    assertEquals("Unexpected result", AppStart.FIRST_TIME_VERSION,
            service.checkAppStart(newVersion, oldVersion));

    // Normal start
    oldVersion = 2;
    newVersion = 2;
    assertEquals("Unexpected result", AppStart.NORMAL,
            service.checkAppStart(newVersion, oldVersion));
}

Avec un peu plus d'effort, vous pourrez probablement tester également les éléments liés à Android (PackageManager et SharedPreferences). Quelqu'un intéressé à écrire le test? :)

Notez que le code ci-dessus ne fonctionnera correctement que si vous ne android:versionCodeplaisantez pas avec votre dans AndroidManifest.xml!

schnatterer
la source
2
Veuillez expliquer comment utiliser cette méthode. Où vous initialisez l'objet SharedPreferences?
Shajeel Afzal
1
ne fonctionne pas pour moi - il lance toujours mon premier tutoriel
pzo
1
ce code est beaucoup plus simple sans les effets secondaires de la déclaration du contexte et des préférences ailleurs public AppStart checkAppStart(Context context, SharedPreferences sharedPreferences)est une bien meilleure signature de méthode
Will
2
Faites une mise à jour de cette réponse ici gist.github.com/williscool/2a57bcd47a206e980eee J'ai eu un problème avec le code original où il restait bloqué dans ma boucle de visite virtuelle pour toujours car le numéro de version n'était jamais recalculé dans le premier checkAppStartbloc. J'ai donc décidé de partager mon code mis à jour et de voir si quelqu'un a des suggestions à ce sujet
Will
1
@Will merci pour votre contribution. Vous avez raison, le code pourrait être simplifié et rendu plus robuste. Lorsque j'ai publié la réponse pour la première fois, j'ai extrait le code d' un scénario plus complexe , auquel je voulais accéder à AppStartpartir de différentes activités. J'ai donc mis la logique dans une méthode de service distincte. C'est pourquoi il y avait une contextvariable et AppStartétait stockée dans une variable statique pour faciliter les appels de méthode idempotente.
schnatterer
4

J'ai résolu de déterminer si l'application est votre première fois ou non, selon qu'il s'agit d'une mise à jour.

private int appGetFirstTimeRun() {
    //Check if App Start First Time
    SharedPreferences appPreferences = getSharedPreferences("MyAPP", 0);
    int appCurrentBuildVersion = BuildConfig.VERSION_CODE;
    int appLastBuildVersion = appPreferences.getInt("app_first_time", 0);

    //Log.d("appPreferences", "app_first_time = " + appLastBuildVersion);

    if (appLastBuildVersion == appCurrentBuildVersion ) {
        return 1; //ya has iniciado la appp alguna vez

    } else {
        appPreferences.edit().putInt("app_first_time",
                appCurrentBuildVersion).apply();
        if (appLastBuildVersion == 0) {
            return 0; //es la primera vez
        } else {
            return 2; //es una versión nueva
        }
    }
}

Calculer les résultats:

  • 0: si c'est la première fois.
  • 1: Cela n'a jamais commencé.
  • 2: Il a démarré une fois, mais pas cette version, c'est à dire qu'il s'agit d'une mise à jour.
Webserveis
la source
3

Vous pouvez utiliser Android SharedPreferences .

Android SharedPreferences nous permet de stocker des données d'application primitives privées sous la forme d'une paire clé-valeur.

CODE

Créer une classe personnalisée SharedPreference

 public class SharedPreference {

    android.content.SharedPreferences pref;
    android.content.SharedPreferences.Editor editor;
    Context _context;
    private static final String PREF_NAME = "testing";

    // All Shared Preferences Keys Declare as #public
    public static final String KEY_SET_APP_RUN_FIRST_TIME       =        "KEY_SET_APP_RUN_FIRST_TIME";


    public SharedPreference(Context context) // Constructor
    {
        this._context = context;
        pref = _context.getSharedPreferences(PREF_NAME, 0);
        editor = pref.edit();

    }

    /*
    *  Set Method Generally Store Data;
    *  Get Method Generally Retrieve Data ;
    * */


    public void setApp_runFirst(String App_runFirst)
    {
        editor.remove(KEY_SET_APP_RUN_FIRST_TIME);
        editor.putString(KEY_SET_APP_RUN_FIRST_TIME, App_runFirst);
        editor.apply();
    }

    public String getApp_runFirst()
    {
        String  App_runFirst= pref.getString(KEY_SET_APP_RUN_FIRST_TIME, "FIRST");
        return  App_runFirst;
    }

}

Ouvrez maintenant votre activité et initialisez .

 private     SharedPreference                sharedPreferenceObj; // Declare Global

Appelez maintenant ceci dans la section OnCreate

 sharedPreferenceObj=new SharedPreference(YourActivity.this);

Vérification en cours

if(sharedPreferenceObj.getApp_runFirst().equals("FIRST"))
 {
   // That's mean First Time Launch
   // After your Work , SET Status NO
   sharedPreferenceObj.setApp_runFirst("NO");
 }
else
 { 
   // App is not First Time Launch
 }
IntelliJ Amiya
la source
2

Voici un code pour cela -

String path = Environment.getExternalStorageDirectory().getAbsolutePath() +
                    "/Android/data/myapp/files/myfile.txt";

boolean exists = (new File(path)).exists(); 

if (!exists) {
    doSomething();                                      
}
else {
    doSomethingElse();
}
Arunabh Das
la source
1

Vous pouvez simplement vérifier l'existence d'un fichier vide, s'il n'existe pas, puis exécuter votre code et créer le fichier.

par exemple

if(File.Exists("emptyfile"){
    //Your code here
    File.Create("emptyfile");
}
MechMK1
la source
Je pensais faire ça mais je pensais qu'il devait y avoir une meilleure façon
Boardy
Je n'en connais pas, mais quel est le manque de ressources que vous recevez par là? 4 octets pour le fichier et un "si" au début. Les routines système feraient la même chose, elles feraient exactement la même chose ou
créeraient
De la même manière, vous pouvez utiliser des préférences partagées qui, si elles n'existent pas, afficheront un écran de démarrage, etc. Voir la réponse de Kevin ci
Stealthcopter
1

J'ai fait une classe simple pour vérifier si votre code s'exécute pour la première fois / n fois!

Exemple

Créez des préférences uniques

FirstTimePreference prefFirstTime = new FirstTimePreference(getApplicationContext());

Utilisez runTheFirstTime, choisissez une clé pour vérifier votre événement

if (prefFirstTime.runTheFirstTime("myKey")) {
    Toast.makeText(this, "Test myKey & coutdown: " + prefFirstTime.getCountDown("myKey"),
                   Toast.LENGTH_LONG).show();
}

Utilisez runTheFirstNTimes, choisissez une clé et combien de fois exécuter

if(prefFirstTime.runTheFirstNTimes("anotherKey" , 5)) {
    Toast.makeText(this, "ciccia Test coutdown: "+ prefFirstTime.getCountDown("anotherKey"),
                   Toast.LENGTH_LONG).show();
}
  • Utilisez getCountDown () pour mieux gérer votre code

FirstTimePreference.java

Alu84
la source
1

Il y a un support pour cela dans la révision 23.3.0 de la bibliothèque de support (dans la v4, ce qui signifie la compatibilité avec Android 1.6).

Dans votre activité Launcher, appelez d'abord:

AppLaunchChecker.onActivityCreate(activity);

Puis appelez:

AppLaunchChecker.hasStartedFromLauncher(activity);

Ce qui reviendra si c'était la première fois que l'application était lancée.

Lucas Arrefelt
la source
L'ordre de ces appels doit être inversé, une fois AppLaunchChecker.onActivityCreate () appelé, AppLaunchChecker.hasStartedFromLauncher () retournera true.
Gary Kipnis
C'est assez trompeur. Il ne dit pas si l'application est "jamais lancée"; il indique plutôt si l'application "a déjà été lancée par un utilisateur depuis le lanceur". Il est donc possible que d'autres applications ou liens profonds aient déjà lancé l'application.
Farid
1

Si vous cherchez un moyen simple, le voici.

Créez une classe utilitaire comme celle-ci,

public class ApplicationUtils {

  /**
  * Sets the boolean preference value
  *
  * @param context the current context
  * @param key     the preference key
  * @param value   the value to be set
  */
 public static void setBooleanPreferenceValue(Context context, String key, boolean value) {
     SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
     sp.edit().putBoolean(key, value).apply();
 }

 /**
  * Get the boolean preference value from the SharedPreference
  *
  * @param context the current context
  * @param key     the preference key
  * @return the the preference value
  */
 public static boolean getBooleanPreferenceValue(Context context, String key) {
     SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
     return sp.getBoolean(key, false);
 }

}

Dans votre activité principale, onCreate ()

if(!ApplicationUtils.getBooleanPreferenceValue(this,"isFirstTimeExecution")){
Log.d(TAG, "First time Execution");
ApplicationUtils.setBooleanPreferenceValue(this,"isFirstTimeExecution",true);
// do your first time execution stuff here,
}
Hardian
la source
1

pour kotlin

    fun checkFirstRun() {

    var prefs_name = "MyPrefsFile"
    var pref_version_code_key = "version_code"
    var doesnt_exist: Int = -1;

    // Get current version code
    var currentVersionCode = BuildConfig.VERSION_CODE

    // Get saved version code
    var prefs: SharedPreferences = getSharedPreferences(prefs_name, MODE_PRIVATE)
    var savedVersionCode: Int = prefs.getInt(pref_version_code_key, doesnt_exist)

    // Check for first run or upgrade
    if (currentVersionCode == savedVersionCode) {

        // This is just a normal run
        return;

    } else if (savedVersionCode == doesnt_exist) {

        // TODO This is a new install (or the user cleared the shared preferences)


    } else if (currentVersionCode > savedVersionCode) {

        // TODO This is an upgrade
    }

    // Update the shared preferences with the current version code
    prefs.edit().putInt(pref_version_code_key, currentVersionCode).apply();

}
K.Hayoev
la source
Merci beaucoup d'avoir répondu à Kotlin
MMG
0

Pourquoi ne pas utiliser l'Assistant de base de données? Cela aura un joli onCreate qui n'est appelé que la première fois que l'application est démarrée. Cela aidera les personnes qui souhaitent suivre cela après l'installation de l'application initiale sans suivi.

slott
la source
Cela crée-t-il une base de données? Comment utiliser DatabaseHelper sans créer une base de données réelle? Et je pense, onCreate()est appelé pour chaque nouvelle version. Aussi, ne serait-il pas considéré comme superflu ou utiliser quelque chose à des fins non intentionnelles?
ADTC
onCreate n'est déclenché que lorsque l'application est installée pour la première fois. Lorsque la version de la base de données est incrémentée, onUpdated est déclenché.
slott
Eh bien superflu est un mot si dur :) - Si vous avez l'option ie. votre application n'est pas encore en ligne, configurez un indicateur SharedPrefs et utilisez-le pour déterminer s'il s'agit du premier démarrage ou non. J'ai eu un cas où l'application était dans la nature depuis un certain temps et nous utilisions une base de données, donc onCreate était un match parfait pour moi.
slott
0

J'aime avoir un "nombre de mises à jour" dans mes préférences partagées. Si ce n'est pas là (ou valeur zéro par défaut), il s'agit de la "première utilisation" de mon application.

private static final int UPDATE_COUNT = 1;    // Increment this on major change
...
if (sp.getInt("updateCount", 0) == 0) {
    // first use
} else if (sp.getInt("updateCount", 0) < UPDATE_COUNT) {
    // Pop up dialog telling user about new features
}
...
sp.edit().putInt("updateCount", UPDATE_COUNT);

Alors maintenant, chaque fois qu'il y a une mise à jour de l'application que les utilisateurs devraient connaître, j'incrémente UPDATE_COUNT

Edward Falk
la source
-1
    /**
     * @author ALGO
     */
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.RandomAccessFile;
    import java.util.UUID;

    import android.content.Context;

    public class Util {
        // ===========================================================
        //
        // ===========================================================

        private static final String INSTALLATION = "INSTALLATION";

        public synchronized static boolean isFirstLaunch(Context context) {
            String sID = null;
            boolean launchFlag = false;
            if (sID == null) {
                File installation = new File(context.getFilesDir(), INSTALLATION);
                try {
                    if (!installation.exists()) {

                        writeInstallationFile(installation);
                    }
                    sID = readInstallationFile(installation);
launchFlag = true;
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
            return launchFlag;
        }

        private static String readInstallationFile(File installation) throws IOException {
            RandomAccessFile f = new RandomAccessFile(installation, "r");// read only mode
            byte[] bytes = new byte[(int) f.length()];
            f.readFully(bytes);
            f.close();

            return new String(bytes);
        }

        private static void writeInstallationFile(File installation) throws IOException {
            FileOutputStream out = new FileOutputStream(installation);
            String id = UUID.randomUUID().toString();
            out.write(id.getBytes());
            out.close();
        }
    }

> Usage (in class extending android.app.Activity)

Util.isFirstLaunch(this);
AZ_
la source
-2

Salut les gars, je fais quelque chose comme ça. Et ça marche pour moi

créer un champ booléen dans la préférence partagée. La valeur par défaut est true {isFirstTime: true} après la première fois, définissez-la sur false. Rien ne peut être simple et fiable que cela dans le système Android.

DropAndTrap
la source
Euh, ne codez pas le chemin comme ça! Si vous le faites simplement, Context.getSharedPreferences()cela se retrouvera au même endroit, sauf que cela fonctionnera partout
Takhion
d'accord avec vous :)
DropAndTrap