Android 앱을 처음 사용하는지 확인


112

현재 Android 앱을 개발 중입니다. 앱이 처음 실행될 때 뭔가를해야합니다. 즉, 프로그램이 처음 실행될 때만 코드가 실행됩니다.


1
처음 앱을 만들기 시작했을 때는 앱을 설치 한 후 처음 실행할 때만 생각했습니다. 나중에 업그레이드 후 첫 실행을 처리하고 차별화해야한다는 것을 나중에 깨달았습니다. 아래 @schnatterer의 대답과 여기에 내 대답 이 어떻게하는지 보여줍니다. 업그레이드를 고려하지 않는 답변에주의하십시오.
Suragch 2015

@Suragch 당신은 업그레이드를 고려하지 않는 것이 나쁜 습관처럼 행동하고 있지만 어떤 경우에는 앱 소개와 같은 경우에는 그것을 원하지 않습니다 :)
creativecreatormaybenot

@creativecreatorormaybenot, 사실입니다. 초기 설치에만 관심이 있고 후속 업그레이드에는 관심이없는 경우가 있습니다. 이러한 상황에는 간단한 부울이면 충분합니다. 그러나 나중에 최근 업데이트에서 방금 추가 한 모든 새로운 기능에 대해 현재 사용자를위한 다른 소개를 추가하려면 어떻게해야합니까? 제 생각에는 부울보다 버전 번호를 확인하는 것이 더 먼 시각입니다. 이것은 적어도 미래에 새로운 설치와 업그레이드에 대해 한 가지 방법으로 응답 할 수있는 옵션을 제공합니다.
Suragch

1
그럼 그냥이 버전을 추가하지만 yoz 얻을
creativecreatorormaybenot을

답변:


56

또 다른 아이디어는 공유 기본 설정의 설정을 사용하는 것입니다. 빈 파일을 확인하는 것과 동일한 일반적인 아이디어이지만 아무것도 저장하는 데 사용되지 않는 빈 파일이 떠 다니지 않습니다.


3
이런 종류의 접근 방식은 Android Froyo를 사용하는 Samsung Galaxy S에서 작동하지 않습니다. 그것은 SharedPreferences 저장의 버그 때문입니다. 다음은 이에 대한 SO 질문에 대한 링크입니다. stackoverflow.com/questions/7296163/… 그리고 여기에 Google 코드 티켓이 있습니다. code.google.com/p/android/issues/detail?id=14359
Francesco Rigoni

4
Android 6.0 (API 23-Marshmallow) 이상 자동 백업 ( developer.android.com/guide/topics/data/autobackup.html) 이 기본적으로 활성화되어 있습니다. 사용자가 앱을 제거한 다음 다시 설치하면 공유 기본 설정이 복구됩니다. 따라서 재설치시 이것이 문제가되는 경우 재설치 후 처음으로 실행 중인지 확인할 수 없습니다.
Alan

1
@Alan 맞습니다.이 답변은 더 이상 Android Marshmallow에서 유효하지 않습니다 .
Ioane Sharvadze

1
@Alan 당신은 내가 당신과 같은 대답을 얼마나 오랫동안 찾고 있었는지 상상할 수 없습니다. 당신은 내 하루를 만들었습니다. 감사!
Antonio

@Alan 그러나 자동 백업은 대부분의 다른 데이터도 저장합니다. 따라서 재설치 된 앱은 아마도 처음 실행되지 않은 상태 일 것으로 예상됩니다. 그리고 사용자는 이전에 이미 앱을 사용 했으므로 안내가 필요하지 않습니다. 그래서 저는 대부분의 경우 이런 일이 일어나는 것이 좋은 일이라고 주장합니다.
smdufb

112

SharedPreferences 를 사용하여 앱이 "처음 실행"되었는지 확인할 수 있습니다 . 그냥 사용 부울 변수 ( "my_first_time")를하고 해당 값을 변경 거짓 "처음"에 대한 귀하의 작업이 끝나면.

이것은 앱을 처음 열 때 잡는 코드입니다.

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

17
Google Play 스토어에서 앱이 다음 버전으로 업데이트되는시기를 처리합니까?
Shajeel Afzal 2014-06-29

4
SharedPreferences는 업그레이드 중에 유지됩니다. 따라서 PlayStore에서 업그레이드 할 때 이전 값을 사용할 수 있다고 가정합니다. 사실 파일의 존재를 확인하는 다른 방법에도 적용 할 수 있습니다. 따라서이 경우 단축키 방법은 다른 기본 설정 / 파일 이름 또는 값을 사용하는 것입니다.
Tejasvi Hegde 2014

@ShajeelAfzal 이와 같은 것은 public void CheckAndInitAppFirstTime () {final String PREFS_NAME = "TheAppVer"; 최종 문자열 CHECK_VERSION = "1"; // 필수 버전 ... final String KEY_NAME = "CheckVersion"; SharedPreferences 설정 = getSharedPreferences (PREFS_NAME, 0); if (! settings.getString (KEY_NAME, "0"). equals (CHECK_VERSION)) {// 앱이 처음 실행 중이거나 CHECK_VERSION이 다릅니다. // ... settings.edit (). putString ( KEY_NAME, CHECK_VERSION) .commit (); }}
Tejasvi Hegde 2014

@aman verma : developer.android.com/reference/android/content/… 의 getBoolean 설명에 따라 getBoolean의 두 번째 매개 변수는 첫 번째 매개 변수가 종료되지 않는 경우 기본값이므로 "my_first_time"이 설정되지 않은 경우 표현식의 기본값은 true입니다.
user2798692

62

부울 플래그뿐만 아니라 전체 버전 코드를 저장하는 것이 좋습니다. 이렇게하면 새 버전에서 처음 시작하는 경우 처음에 쿼리 할 수도 있습니다. 예를 들어이 정보를 사용하여 "새로운 기능"대화 상자를 표시 할 수 있습니다.

다음 코드는 "컨텍스트 인"모든 Android 클래스 (활동, 서비스, ...)에서 작동해야합니다. 별도의 (POJO) 클래스에 포함하려는 경우 예를 들어 여기 에 설명 된 "정적 컨텍스트"사용을 고려할 수 있습니다 .

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

다음과 같은 활동에서 사용할 수 있습니다.

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

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

이 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));
}

조금 더 노력하면 아마도 안드로이드 관련 항목 (PackageManager 및 SharedPreferences)도 테스트 할 수 있습니다. 시험 작성에 관심이있는 사람이 있습니까? :)

위의 코드는 android:versionCodeAndroidManifest.xml에서 엉망이되지 않는 경우에만 제대로 작동합니다 .


2
이 방법을 사용하는 방법을 설명하십시오. SharedPreferences 객체를 어디에서 초기화하고 있습니까?
Shajeel Afzal 2014-06-29

1
나를 위해 작동하지 않습니다 - 그것은 항상 내 처음 튜토리얼을 시작
PZO

1
이 코드는 컨텍스트와 선호도를 다른 곳에서 선언하는 부작용없이 훨씬 더 간단합니다 public AppStart checkAppStart(Context context, SharedPreferences sharedPreferences). 훨씬 더 나은 메서드 시그니처
Will

2
여기 에이 답변의 업데이트 요점을 작성했습니다 .gist.github.com / williscool / 2a57bcd47a206e980eee 버전 번호가 첫 번째 checkAppStart블록 에서 다시 계산되지 않았기 때문에 내 연습 루프에 영원히 멈출 원래 코드에 문제가 있습니다. 그래서 난 내 업데이트 된 코드를 공유하고 누군가가 그것에 대해 제안이 있는지 결정
윌를

1
@ 당신의 의견에 감사드립니다. 당신 말이 맞습니다. 코드를 단순화하고 더 강력하게 만들 수 있습니다. 처음 답변을 게시했을 때 다른 활동에서 액세스하려는 더 복잡한 시나리오 에서 코드를 추출했습니다 AppStart. 그래서 논리를 별도의 서비스 방법에 넣었습니다. 거기에 이유의 그 context변수와 AppStart나무 등 메서드 호출을 용이하게하기 위해 정적 변수에 저장되었다.
schnatterer

4

업데이트 여부에 따라 응용 프로그램이 처음인지 아닌지 확인하기 위해 해결했습니다.

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

계산 결과 :

  • 0 : 처음 인 경우.
  • 1 : 시작되었습니다.
  • 2 : 한 번 시작되었지만 해당 버전이 아닙니다. 즉, 업데이트입니다.

3

Android SharedPreferences 를 사용할 수 있습니다 .

Android SharedPreferences를 사용하면 키-값 쌍 형식으로 비공개 기본 애플리케이션 데이터를 저장할 수 있습니다.

암호

사용자 정의 클래스 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;
    }

}

이제 활동을 열고 초기화하십시오 .

 private     SharedPreference                sharedPreferenceObj; // Declare Global

이제 OnCreate 섹션 에서 이것을 호출 하십시오.

 sharedPreferenceObj=new SharedPreference(YourActivity.this);

지금 확인 중

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
 }

2

여기에 대한 몇 가지 코드가 있습니다.

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

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

if (!exists) {
    doSomething();                                      
}
else {
    doSomethingElse();
}

1

빈 파일이 존재하지 않는지 확인한 다음 코드를 실행하고 파일을 생성하면됩니다.

예 :

if(File.Exists("emptyfile"){
    //Your code here
    File.Create("emptyfile");
}

나는 더 나은 방법이 있어야하고 생각했지만, 생각
Boardy

나는 아무것도 모르지만 그로 인해받는 자원이 부족한 것은 무엇입니까? 파일 용으로 4 바이트, 시작 부분에 하나의 "if". 시스템 루틴은 똑같은 일을 할 것입니다. 그들은 정확히 똑같은 일을하거나 이미 실행 된 애플리케이션으로 테이블을 만들 것입니다
MechMK1

비슷한 방식으로 sharedpreferences를 사용할 수 있는데, 존재하지 않으면 스플래시 화면 등을 표시하고 프로그램이 처음 실행될 때 생성합니다 (확인 후 obv). 위의 Kevin의 답변 참조
stealthcopter 2011 년

1

코드가 처음 / n 번 실행되는지 확인하는 간단한 클래스를 만들었습니다!

고유 한 선호도 만들기

FirstTimePreference prefFirstTime = new FirstTimePreference(getApplicationContext());

runTheFirstTime을 사용하고 이벤트를 확인할 키를 선택하세요.

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

runTheFirstNTimes 사용, 키 선택 및 실행 횟수 선택

if(prefFirstTime.runTheFirstNTimes("anotherKey" , 5)) {
    Toast.makeText(this, "ciccia Test coutdown: "+ prefFirstTime.getCountDown("anotherKey"),
                   Toast.LENGTH_LONG).show();
}
  • getCountDown ()을 사용하여 코드를 더 잘 처리하십시오.

FirstTimePreference.java


1

지원 라이브러리 개정판 23.3.0 (v4에서는 Android 1.6으로의 호환성을 의미 함)에서 이에 대한 지원이 있습니다.

런처 활동에서 먼저 다음을 호출하십시오.

AppLaunchChecker.onActivityCreate(activity);

그런 다음 전화 :

AppLaunchChecker.hasStartedFromLauncher(activity);

앱이 처음 실행 된 경우 반환됩니다.


이러한 호출의 순서를 반대로해야합니다. AppLaunchChecker.onActivityCreate ()가 호출되면 AppLaunchChecker.hasStartedFromLauncher ()가 true를 반환합니다.
Gary Kipnis

이것은 오해의 소지가 있습니다. 앱이 "출시 된 적이 없는지"는 말하지 않습니다. 오히려 앱이 "런처에서 사용자에 의해 실행 된 적이 있는지"여부를 나타냅니다. 따라서 다른 앱이나 딥 링크가 이미 앱을 시작했을 가능성이 있습니다.
Farid

1

간단한 방법을 찾고 있다면 여기에 있습니다.

이와 같은 유틸리티 클래스를 만듭니다.

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

}

주요 활동에서 onCreate ()

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

1

코 틀린

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

}

Kotlin
MMG에서

0

데이터베이스 도우미를 사용하지 않는 이유는 무엇입니까? 이것은 앱이 처음 시작될 때만 호출되는 멋진 onCreate를 가질 것입니다. 이렇게하면 추적없이 초기 앱을 설치 한 후이를 추적하려는 사람들에게 도움이됩니다.


데이터베이스가 생성됩니까? 실제 데이터베이스를 만들지 않고 DatabaseHelper를 사용하는 방법은 무엇입니까? 그리고 나는 onCreate()모든 새로운 버전에 대해 호출됩니다. 또한 불필요한 것으로 간주되거나 의도하지 않은 목적으로 사용되지 않습니까?
ADTC

onCreate는 앱이 처음 설치 될 때만 트리거됩니다. db 버전이 증가하면 onUpdated가 트리거됩니다.
슬로

너무 가혹한 단어입니다 :)-옵션이 있다면. 앱이 아직 라이브 상태가 아닌 다음 SharedPrefs 플래그를 설정하고이를 사용하여 첫 번째 부팅인지 여부를 확인합니다. 나는 앱이 한동안 야생에 있었던 경우가 있었고 우리는 DB를 사용했기 때문에 onCreate가 나에게 완벽하게 일치했습니다.
slott

0

내 공유 환경 설정에 "업데이트 횟수"가있는 것을 좋아합니다. 이것이 없으면 (또는 기본값 0 값) 내 앱의 "처음 사용"입니다.

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);

이제 사용자가 알아야 할 앱 업데이트가있을 때마다 UPDATE_COUNT 개를 늘립니다.


-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);

-2

안녕하세요 여러분 저는 이런 일을하고 있습니다. 그리고 나를위한 작품

공유 환경 설정에서 Boolean 필드를 만듭니다. 처음으로 false로 설정 한 후 기본값은 true {isFirstTime : true}입니다. 안드로이드 시스템에서 이것보다 간단하고 신뢰할 수있는 것은 없습니다.


어, 그렇게 경로를 하드 코딩하지 마세요! 당신은 단순히 할 경우 Context.getSharedPreferences()이 같은 장소에서 끝날 것, 그것은 어디에서나 작동 제외시켰다
Takhion

동의합니다 :)
DropAndTrap
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.