web-dev-qa-db-ja.com

アプリケーションの起動ごとに1回だけ実行するにはどうすればよいですか?

アプリケーションに更新チェッカーを実装したいのですが、アプリケーションを起動したときに一度だけ表示されるようにする必要があるのは明らかです。 onCreate()またはonStart()メソッドで呼び出しを行うと、アクティビティが作成されるたびに表示されますが、これは実行可能なソリューションではありません。

だから私の質問は:アプリケーションの開始/起動ごとに一度だけ、更新の確認などの何かを行う方法はありますか?

少しわかりづらいので申し訳ありませんが、これについて説明するのに苦労しています。

29
Michell Bak

SharedPreferencesは私にとって醜い解決策のようです。このような目的でアプリケーションコンストラクターを使用すると、はるかに便利です。

必要なのは、デフォルトではなく、独自のApplicationクラスを使用することだけです。

public class MyApp extends Application {

    public MyApp() {
        // this method fires only once per application start. 
        // getApplicationContext returns null here

        Log.i("main", "Constructor fired");
    }

    @Override
    public void onCreate() {
        super.onCreate();    

        // this method fires once as well as constructor 
        // but also application has context here

        Log.i("main", "onCreate fired"); 
    }
}

次に、このクラスをAndroidManifest.xml内のアプリケーションクラスとして登録する必要があります。

<application Android:label="@string/app_name" Android:name=".MyApp"> <------- here
    <activity Android:name="MyActivity"
              Android:label="@string/app_name">
        <intent-filter>
            <action Android:name="Android.intent.action.MAIN"/>
            <category Android:name="Android.intent.category.LAUNCHER"/>
        </intent-filter>
    </activity>
</application>

戻るボタンを押すこともできるので、アプリケーションはバックグラウンドになり、プロセッサリソースを無駄にせず、メモリリソースのみを無駄にしません。その後、再度起動しても、アプリケーションがまだ終了していないため、コンストラクタは起動しません。

タスクマネージャでメモリをクリアして、すべてのアプリケーションを閉じてから、アプリケーションを再起動して、初​​期化コードが再び実行されることを確認できます。

52

あなたはこのようなことをしなければならないかもしれないように見えます

PackageInfo info = getPackageManager().getPackageInfo(PACKAGE_NAME, 0);

      int currentVersion = info.versionCode;
      this.versionName = info.versionName;
      SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
      int lastVersion = prefs.getInt("version_code", 0);
      if (currentVersion > lastVersion) {
        prefs.edit().putInt("version_code", currentVersion).commit();
       //  do the activity that u would like to do once here.
   }

毎回これを実行して、アプリがアップグレードされているかどうかを確認できるため、アプリのアップグレード時に1回だけ実行されます

4
Yashwanth Kumar

共有設定のアプローチは面倒で、アプリケーションクラスはアクティビティにアクセスできません。

私が使用したもう1つの代替方法は、フラグメントインスタンスを保持することです。そのインスタンス内では、特にメインアクティビティUIにアクセスする必要がある場合、さらに多くのことができます。

この例では、保持されたフラグメント内でasynctaskを使用しました。私のAsyncTaskには、親アクティビティへのコールバックがあります。同じアクティビティが破棄、再作成されてもフラグメントは破棄、再作成されないため、アプリケーションごとに1回だけ実行されることが保証されています。これは保持されたフラグメントです。

public class StartupTaskFragment extends Fragment {

public interface Callbacks {
    void onPreExecute();
    void onProgressUpdate(int percent);
    void onCancelled();
    void onPostExecute();
}

public static final String TAG = "startup_task_fragment";
private Callbacks mCallbacks;
private StartupTask mTask;

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    mCallbacks = (Callbacks) activity;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setRetainInstance(true); // this keeps fragment in memory even if parent activity is destroyed

    mTask = new StartupTask();
    mTask.execute();
}

@Override
public void onDetach() {
    super.onDetach();
    mCallbacks = null;
}

private class StartupTask extends AsyncTask<Void, Integer, Void> {

    @Override
    protected void onPreExecute() {
        if (mCallbacks != null) {
            mCallbacks.onPreExecute();
        }
    }

    @Override
    protected Void doInBackground(Void... ignore) {

        // do stuff here

        return null;
    }

    @Override
    protected void onProgressUpdate(Integer... percent) {
        if (mCallbacks != null) {
            mCallbacks.onProgressUpdate(percent[0]);
        }
    }

    @Override
    protected void onCancelled() {
        if (mCallbacks != null) {
            mCallbacks.onCancelled();
        }
    }

    @Override
    protected void onPostExecute(Void ignore) {
        if (mCallbacks != null) {
            mCallbacks.onPostExecute();
        }
    }
}
}

次に、このスタートアップタスクフラグメントを1回実行するメイン(または親)アクティビティ内。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    FragmentManager fm = getFragmentManager();
    StartupTaskFragment st = (StartupTaskFragment) fm.findFragmentByTag(StartupTaskFragment.TAG);

    if(st == null) {
        fm.beginTransaction().add(mStartupTaskFragment = new StartupTaskFragment(), StartupTaskFragment.TAG).commit();
    }

    ...
}

保持されたフラグメントのアイデアはここから来ました: http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html 。私は、設定の変更を除いて、他の用途を理解しました。

4
Poly Bug

はい、AndroidのSharedPrefernceコンセプトを使用して実行できます。ブールフラグを作成してSharedPrefernceに保存し、その値をonCreate()メソッドで確認するだけです。

2
Sujit

私はこれを自分で解決しただけで、アプリケーションの実行中に何度もメインアクティビティを再開しました。コンストラクターはいくつかのものに対して有効なアプローチですが、現在のアプリケーションコンテキストにアクセスして、他のものの間でトーストを書き込むことはできません

私の解決策は、MainActivityのクラスでtrueに設定された単純な 'firstRun'ブール値を作成することでした。そこから、ifステートメントのコンテンツを実行し、trueに設定しました。例:

public class MainActivity extends AppCompatActivity
{
     private static boolean firstRun = true;

     @Override
     protected void onCreate(Bundle savedInstanceState)
     {
         if(firstRun)
         {
              Toast.makeText(getApplicationContext(), "FIRST RUN", Toast.LENGTH_SHORT).show();
              //YOUR FIRST RUN CODE HERE
         }
         firstRun = false;

         super.onCreate(savedInstanceState);
         //THE REST OF YOUR CODE
}
0

これにはSharedPreferenceを使用します

  1. アプリがアクティブになった後でランチャーアクティビティを再開しない場合は、その場合はそれを使用します。

  2. アプリに実装する場合は、これをスプラッシュ画面で使用します。

  3. スプラッシュ画面を使用していない場合は、ビューを設定せずにアクティビティを作成する必要があります。そのoncreate呼び出しで、更新を開始してメインアクティビティを開始できます。

これには、カウンター値またはブール値を使用できます。

ここにSharedPreference docがあります:

http://developer.Android.com/reference/Android/content/SharedPreferences.html

0
Vineet Shukla
 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
  if (!prefs.getBoolean("onlyonce", false)) {
    // <---- run your one time code here


    // mark once runned.
    SharedPreferences.Editor editor = prefs.edit();
    editor.putBoolean("onlyonce", true);
    editor.commit();
  }
}
0
Makvin

これは、他の回答で説明したのと同じ方法で行います。マニフェストのリリース番号と一致する最初のアクティビティにグローバル変数があるだけです。アップグレードのたびに値を増やし、チェックでより大きな数値が見つかると、1回限りのコードを実行します。

成功すると、新しい設定が共有設定に書き込まれるため、次のアップグレードまで再度行われません。

共有設定からバージョンを取得するときは、デフォルトを-1に割り当てて、コードを実行せずにアプリを正しく更新しないのではなく、コードをもう一度実行するときにエラーが発生するようにしてください。

0
trgraglia
      try {

          boolean firstboot = getSharedPreferences("BOOT_PREF",MODE_PRIVATE)
    .getBoolean("firstboot", true);

                    if(firstboot){
                //place your code that will run single time                  
getSharedPreferences("BOOT_PREF",MODE_PRIVATE).edit().
    putBoolean("firstboot", false)
                        .commit();


                    }
0
Rahulkapil