Sprawdź, czy aplikacja na Androida jest używana po raz pierwszy
112
Obecnie pracuję nad aplikacją na Androida. Muszę coś zrobić, gdy aplikacja jest uruchamiana po raz pierwszy, tj. Kod działa tylko przy pierwszym uruchomieniu programu.
Kiedy zaczynałem tworzyć aplikacje, myślałem tylko o pierwszym uruchomieniu po zainstalowaniu aplikacji. Później zdałem sobie sprawę, że muszę również obsługiwać i różnicować pierwsze przebiegi po aktualizacjach. Odpowiedź @schnatterer poniżej i moja odpowiedź tutaj pokazują, jak to zrobić. Uważaj na odpowiedzi, które nie uwzględniają aktualizacji.
Suragch
@Suragch zachowujesz się tak, jakby nie branie pod uwagę uaktualnień jest złą praktyką, ale w niektórych przypadkach, na przykład wprowadzenie aplikacji, NIE CHCESZ tego robić :)
creativecreatorormaybenot
@creativecreatorormaybenot, to prawda. Są chwile, kiedy zależy Ci tylko na początkowej instalacji, a nie na kolejnych aktualizacjach. W takich sytuacjach wystarczy zwykła wartość logiczna. A co, jeśli w przyszłości zechcesz dodać inne wprowadzenie dla obecnych użytkowników, dotyczące wszystkich nowych funkcji, które właśnie dodałeś w ostatniej aktualizacji? Moim zdaniem bardziej dalekowzroczne jest sprawdzenie numeru wersji niż wartości logicznej. To przynajmniej daje Ci w przyszłości możliwość zareagowania w jeden sposób na nową instalację i inny sposób na aktualizację.
Suragch
1
Potem po prostu dodajesz to dla tej wersji, ale dostaję yoz
Innym pomysłem jest użycie ustawienia w Preferencjach wspólnych. Taka sama ogólna idea, jak sprawdzanie pustego pliku, ale wtedy nie masz pustego pliku, który nie jest używany do przechowywania niczego
Uwaga na Androida 6.0 (API 23 - Marshmallow) lub nowszego, automatyczne tworzenie kopii zapasowych ( developer.android.com/guide/topics/data/autobackup.html) jest domyślnie włączone. Jeśli użytkownicy odinstalują, a następnie ponownie zainstalują aplikację, udostępnione preferencje zostaną przywrócone. Tak więc przy ponownych instalacjach nie można sprawdzić, czy działa po raz pierwszy po ponownej instalacji, jeśli ma to jakiekolwiek znaczenie.
Alan
1
@Alan, masz rację, ta odpowiedź nie dotyczy już Androida Marshmallow.
Ioane Sharvadze
1
@Alan, nie możesz sobie wyobrazić, jak długo szukałem odpowiedzi takiej jak Twoja. Uczyniłeś mój dzień. Dzięki!
Antonio,
@Alan Ale automatyczne tworzenie kopii zapasowych zapisuje również większość innych danych. Dlatego prawdopodobnie ponownie zainstalowana aplikacja będzie w stanie innym niż pierwsze uruchomienie. Użytkownik korzystał już z aplikacji już wcześniej, więc nie ma potrzeby udzielania wskazówek. Dlatego argumentowałbym, że w większości przypadków to dobrze.
smdufb
112
Możesz użyć SharedPreferences, aby określić, czy jest to „pierwsze uruchomienie” aplikacji. Po prostu użyj zmiennej Boolean („my_first_time”) i zmień jej wartość na false, gdy Twoje zadanie „pierwszy raz” się zakończy.
Oto mój kod do złapania przy pierwszym uruchomieniu aplikacji:
finalString 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();}
Czy poradzi sobie, gdy aplikacja zostanie zaktualizowana do następnej wersji w sklepie Google Play?
Shajeel Afzal
4
SharedPreferences są zachowywane podczas aktualizacji. Zakładam więc, że po aktualizacji z PlayStore dostępna jest stara wartość. W rzeczywistości ma zastosowanie także do innych metod, np. Sprawdzania istnienia pliku. Tak więc metodą skrótu w tym przypadku jest użycie innej preferencji / nazwy pliku lub wartości.
Tejasvi Hegde
@ShajeelAfzal coś takiego może pomóc w publicznym void CheckAndInitAppFirstTime () {final String PREFS_NAME = "TheAppVer"; końcowy ciąg CHECK_VERSION = "1"; // Wymagana wersja ... final String KEY_NAME = "CheckVersion"; SharedPreferences settings = getSharedPreferences (PREFS_NAME, 0); if (! settings.getString (KEY_NAME, "0"). equals (CHECK_VERSION)) {// aplikacja jest uruchamiana po raz pierwszy, zrób coś lub CHECK_VERSION jest inna // ... settings.edit (). putString ( KEY_NAME, CHECK_VERSION) .commit (); }}
Tejasvi Hegde
@aman verma: zgodnie z opisem getBoolean na developer.android.com/reference/android/content/ ... Drugi parametr getBoolean jest wartością domyślną, jeśli pierwszy parametr nie wychodzi, więc jeśli „my_first_time” nie został ustawiony wyrażenie domyślnie ma wartość true.
user2798692
63
Proponuję nie tylko przechowywać flagę logiczną, ale także cały kod wersji. W ten sposób możesz również zapytać na początku, czy jest to pierwszy start w nowej wersji. Możesz użyć tych informacji, aby na przykład wyświetlić okno dialogowe „Co nowego”.
Poniższy kod powinien działać z każdą klasą systemu Android, która „jest kontekstem” (działania, usługi, ...). Jeśli wolisz mieć go w oddzielnej klasie (POJO), możesz rozważyć użycie „kontekstu statycznego”, jak opisano na przykład tutaj .
/**
* 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
*
*/publicenumAppStart{
FIRST_TIME, FIRST_TIME_VERSION, NORMAL;}/**
* The app version code (not the version name!) that was used on the last
* start of the app.
*/privatestaticfinalString 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
*/publicAppStart 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;}publicAppStart checkAppStart(int currentVersionCode,int lastVersionCode){if(lastVersionCode ==-1){returnAppStart.FIRST_TIME;}elseif(lastVersionCode < currentVersionCode){returnAppStart.FIRST_TIME_VERSION;}elseif(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.");returnAppStart.NORMAL;}else{returnAppStart.NORMAL;}}
Można go użyć z takiej czynności:
publicclassMainActivityextendsActivity{@Overrideprotectedvoid onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);switch(checkAppStart()){case NORMAL:// We don't want to get on the user's nervesbreak;case FIRST_TIME_VERSION:// TODO show what's newbreak;case FIRST_TIME:// TODO show a tutorialbreak;default:break;}// ...}// ...}
Podstawową logikę można zweryfikować za pomocą tego testu JUnit:
publicvoid testCheckAppStart(){// First startint 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));}
Przy odrobinie wysiłku możesz prawdopodobnie przetestować również rzeczy związane z Androidem (PackageManager i SharedPreferences). Czy ktoś jest zainteresowany napisaniem testu? :)
Zwróć uwagę, że powyższy kod będzie działał poprawnie tylko wtedy, gdy nie będziesz bałaganić android:versionCodew pliku AndroidManifest.xml!
Proszę wyjaśnić, jak korzystać z tej metody. Gdzie inicjalizujesz obiekt SharedPreferences?
Shajeel Afzal
1
nie działa dla mnie - zawsze uruchamia mój samouczek po raz pierwszy
pzo
1
ten kod jest o wiele prostszy bez skutków ubocznych deklarowania kontekstu i preferencji w innym miejscu public AppStart checkAppStart(Context context, SharedPreferences sharedPreferences)jest znacznie lepszą sygnaturą metody
Will
2
Tutaj zaktualizowałem sedno tej odpowiedzi gist.github.com/williscool/2a57bcd47a206e980eee Miałem problem z oryginalnym kodem, w wyniku którego utknąłby w mojej pętli instruktażowej, ponieważ numer wersji nigdy nie był ponownie obliczany w pierwszym checkAppStartbloku. więc postanowiłem udostępnić mój zaktualizowany kod i sprawdzić, czy ktoś ma jakieś sugestie na ten temat
Will
1
@ Będziemy wdzięczni za Twój wkład. Masz rację, kod można uprościć i uczynić solidniejszym. Kiedy po raz pierwszy opublikowałem odpowiedź, wyodrębniłem kod z bardziej złożonego scenariusza , w którym chciałem uzyskać dostęp AppStartz różnych działań. Więc umieściłem logikę w oddzielnej metodzie obsługi. Dlatego istniała contextzmienna i AppStartbyła przechowywana w zmiennej statycznej, aby ułatwić idempotentne wywołania metod.
schnatterer
4
Rozwiązałem, aby ustalić, czy aplikacja jest Twoja pierwsza, czy nie, w zależności od tego, czy jest to aktualizacja.
privateint appGetFirstTimeRun(){//Check if App Start First TimeSharedPreferences 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 ){return1;//ya has iniciado la appp alguna vez}else{
appPreferences.edit().putInt("app_first_time",
appCurrentBuildVersion).apply();if(appLastBuildVersion ==0){return0;//es la primera vez}else{return2;//es una versión nueva}}}
Oblicz wyniki:
0: Jeśli to pierwszy raz.
1: Zaczęło się kiedykolwiek.
2: Uruchomiono raz, ale nie tę wersję, tj. Jest to aktualizacja.
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}
Myślałem o tym, ale pomyślałem, że musi być lepszy sposób
Boardy
Nie znam żadnych, ale jaki jest brak środków, które otrzymujesz dzięki temu? 4 bajty na plik i jedno „if” na początku. Procedury systemowe zrobiłyby to samo, zrobiłyby dokładnie to samo lub
utworzyłyby
W podobny sposób możesz użyć wspólnych preferencji, które jeśli nie istnieją, pokazujesz ekran powitalny itp ... i po prostu utworzysz go przy pierwszym uruchomieniu programu (obv po sprawdzeniu). Zobacz odpowiedź Kevina powyżej
stealthcopter
1
Zrobiłem prostą klasę, aby sprawdzić, czy Twój kod działa po raz pierwszy / n-razy!
Użyj runTheFirstNTimes, wybierz klucz i ile razy wykonaj
if(prefFirstTime.runTheFirstNTimes("anotherKey",5)){Toast.makeText(this,"ciccia Test coutdown: "+ prefFirstTime.getCountDown("anotherKey"),Toast.LENGTH_LONG).show();}
Użyj metody getCountDown (), aby lepiej obsługiwać swój kod
Kolejność tych wywołań musi zostać odwrócona, po wywołaniu AppLaunchChecker.onActivityCreate () AppLaunchChecker.hasStartedFromLauncher () zwróci wartość true.
Gary Kipnis
To jest dość mylące. Nie mówi, czy aplikacja jest „kiedykolwiek uruchomiona”; mówi raczej, czy aplikacja „kiedykolwiek została uruchomiona przez użytkownika z programu uruchamiającego”. Istnieje więc możliwość, że inne aplikacje lub głębokie linki mogły już uruchomić aplikację.
Farid
1
Jeśli szukasz prostego sposobu, oto on.
Utwórz taką klasę użytkową,
publicclassApplicationUtils{/**
* Sets the boolean preference value
*
* @param context the current context
* @param key the preference key
* @param value the value to be set
*/publicstaticvoid setBooleanPreferenceValue(Context context,String key,booleanvalue){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
*/publicstaticboolean getBooleanPreferenceValue(Context context,String key){SharedPreferences sp =PreferenceManager.getDefaultSharedPreferences(context);return sp.getBoolean(key,false);}}
W Twojej głównej aktywności onCreate ()
if(!ApplicationUtils.getBooleanPreferenceValue(this,"isFirstTimeExecution")){Log.d(TAG,"First time Execution");ApplicationUtils.setBooleanPreferenceValue(this,"isFirstTimeExecution",true);// do your first time execution stuff here,}
fun checkFirstRun(){var prefs_name ="MyPrefsFile"var pref_version_code_key ="version_code"var doesnt_exist:Int=-1;// Get current version codevar currentVersionCode =BuildConfig.VERSION_CODE
// Get saved version codevar prefs:SharedPreferences= getSharedPreferences(prefs_name, MODE_PRIVATE)var savedVersionCode:Int= prefs.getInt(pref_version_code_key, doesnt_exist)// Check for first run or upgradeif(currentVersionCode == savedVersionCode){// This is just a normal runreturn;}elseif(savedVersionCode == doesnt_exist){// TODO This is a new install (or the user cleared the shared preferences)}elseif(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();}
Bardzo dziękuję za udzielenie odpowiedzi w Kotlinie
MMG
0
Dlaczego nie skorzystać z pomocnika bazy danych? Będzie to przyjemne narzędzie onCreate, które jest wywoływane tylko przy pierwszym uruchomieniu aplikacji. Pomoże to tym osobom, które chcą to śledzić po zainstalowaniu pierwszej aplikacji bez śledzenia.
Czy to tworzy bazę danych? Jak używać DatabaseHelper bez tworzenia rzeczywistej bazy danych? I myślę, że onCreate()jest wymagana dla każdej nowej wersji. Czy nie byłoby to uważane za zbyteczne lub używanie czegoś w niezamierzonym celu?
ADTC
onCreate jest uruchamiane tylko wtedy, gdy aplikacja jest instalowana po raz pierwszy. Gdy wersja bazy danych jest zwiększana, wyzwalany jest onUpdated.
slott
Cóż, zbędne jest takie ostre słowo :) - jeśli masz taką możliwość tj. Twoja aplikacja nie jest jeszcze aktywna, ustaw flagę SharedPrefs i użyj jej, aby określić, czy jest to pierwsze uruchomienie, czy nie. Miałem przypadek, w którym aplikacja była przez jakiś czas na wolności i używaliśmy DB, więc onCreate był dla mnie idealnym rozwiązaniem.
slott
0
Lubię mieć „liczbę aktualizacji” w moich wspólnych preferencjach. Jeśli go tam nie ma (lub domyślna wartość zerowa), oznacza to „pierwsze użycie” mojej aplikacji.
privatestaticfinalint UPDATE_COUNT =1;// Increment this on major change...if(sp.getInt("updateCount",0)==0){// first use}elseif(sp.getInt("updateCount",0)< UPDATE_COUNT){// Pop up dialog telling user about new features}...
sp.edit().putInt("updateCount", UPDATE_COUNT);
Dlatego teraz, gdy pojawia się aktualizacja aplikacji, o której użytkownicy powinni wiedzieć, zwiększam UPDATE_COUNT
utwórz pole Boolean we wspólnych preferencjach. Wartość domyślna to true {isFirstTime: true} po pierwszym razem ustaw ją na false. Nic nie może być proste i niezawodne niż to w systemie Android.
Uh, nie zakoduj na stałe ścieżki w ten sposób! Jeśli po prostu zrobić Context.getSharedPreferences()to kończy się w tym samym miejscu, z wyjątkiem będzie pracować wszędzie
Odpowiedzi:
Innym pomysłem jest użycie ustawienia w Preferencjach wspólnych. Taka sama ogólna idea, jak sprawdzanie pustego pliku, ale wtedy nie masz pustego pliku, który nie jest używany do przechowywania niczego
źródło
Możesz użyć SharedPreferences, aby określić, czy jest to „pierwsze uruchomienie” aplikacji. Po prostu użyj zmiennej Boolean („my_first_time”) i zmień jej wartość na false, gdy Twoje zadanie „pierwszy raz” się zakończy.
Oto mój kod do złapania przy pierwszym uruchomieniu aplikacji:
źródło
Proponuję nie tylko przechowywać flagę logiczną, ale także cały kod wersji. W ten sposób możesz również zapytać na początku, czy jest to pierwszy start w nowej wersji. Możesz użyć tych informacji, aby na przykład wyświetlić okno dialogowe „Co nowego”.
Poniższy kod powinien działać z każdą klasą systemu Android, która „jest kontekstem” (działania, usługi, ...). Jeśli wolisz mieć go w oddzielnej klasie (POJO), możesz rozważyć użycie „kontekstu statycznego”, jak opisano na przykład tutaj .
Można go użyć z takiej czynności:
Podstawową logikę można zweryfikować za pomocą tego testu JUnit:
Przy odrobinie wysiłku możesz prawdopodobnie przetestować również rzeczy związane z Androidem (PackageManager i SharedPreferences). Czy ktoś jest zainteresowany napisaniem testu? :)
Zwróć uwagę, że powyższy kod będzie działał poprawnie tylko wtedy, gdy nie będziesz bałaganić
android:versionCode
w pliku AndroidManifest.xml!źródło
public AppStart checkAppStart(Context context, SharedPreferences sharedPreferences)
jest znacznie lepszą sygnaturą metodycheckAppStart
bloku. więc postanowiłem udostępnić mój zaktualizowany kod i sprawdzić, czy ktoś ma jakieś sugestie na ten tematAppStart
z różnych działań. Więc umieściłem logikę w oddzielnej metodzie obsługi. Dlatego istniałacontext
zmienna iAppStart
była przechowywana w zmiennej statycznej, aby ułatwić idempotentne wywołania metod.Rozwiązałem, aby ustalić, czy aplikacja jest Twoja pierwsza, czy nie, w zależności od tego, czy jest to aktualizacja.
Oblicz wyniki:
źródło
Możesz użyć wspólnych preferencji Androida .
KOD
Utwórz niestandardową klasę SharedPreference
Teraz otwórz swoją aktywność i zainicjuj .
Teraz nazwij to w sekcji OnCreate
Teraz sprawdzam
źródło
Oto kod do tego -
źródło
Możesz po prostu sprawdzić, czy istnieje pusty plik, jeśli nie istnieje, a następnie wykonać kod i utworzyć plik.
na przykład
źródło
Zrobiłem prostą klasę, aby sprawdzić, czy Twój kod działa po raz pierwszy / n-razy!
Przykład
Stwórz unikalne preferencje
Użyj runTheFirstTime, wybierz klucz, aby sprawdzić wydarzenie
Użyj runTheFirstNTimes, wybierz klucz i ile razy wykonaj
FirstTimePreference.java
źródło
Jest to obsługiwane w wersji 23.3.0 biblioteki obsługi (w wersji 4, co oznacza kompatybilność z powrotem do Androida 1.6).
Podczas działania programu uruchamiającego pierwsze połączenie:
Wtedy zadzwoń:
Który powróci, jeśli będzie to pierwsze uruchomienie aplikacji.
źródło
Jeśli szukasz prostego sposobu, oto on.
Utwórz taką klasę użytkową,
W Twojej głównej aktywności onCreate ()
źródło
dla kotlin
źródło
Dlaczego nie skorzystać z pomocnika bazy danych? Będzie to przyjemne narzędzie onCreate, które jest wywoływane tylko przy pierwszym uruchomieniu aplikacji. Pomoże to tym osobom, które chcą to śledzić po zainstalowaniu pierwszej aplikacji bez śledzenia.
źródło
onCreate()
jest wymagana dla każdej nowej wersji. Czy nie byłoby to uważane za zbyteczne lub używanie czegoś w niezamierzonym celu?Lubię mieć „liczbę aktualizacji” w moich wspólnych preferencjach. Jeśli go tam nie ma (lub domyślna wartość zerowa), oznacza to „pierwsze użycie” mojej aplikacji.
Dlatego teraz, gdy pojawia się aktualizacja aplikacji, o której użytkownicy powinni wiedzieć, zwiększam UPDATE_COUNT
źródło
źródło
Cześć, robię coś takiego. I to działa na mnie
utwórz pole Boolean we wspólnych preferencjach. Wartość domyślna to true {isFirstTime: true} po pierwszym razem ustaw ją na false. Nic nie może być proste i niezawodne niż to w systemie Android.
źródło
Context.getSharedPreferences()
to kończy się w tym samym miejscu, z wyjątkiem będzie pracować wszędzie