Как я могу выполнить что-то только один раз за запуск приложения? - PullRequest
24 голосов
/ 09 сентября 2011

Я хотел бы реализовать средство проверки обновлений в приложении, и мне, очевидно, нужно, чтобы оно появлялось только один раз при запуске приложения. Если я выполняю вызов в методе onCreate() или onStart(), он будет отображаться при каждом создании операции, и это не является жизнеспособным решением.

Итак, мой вопрос: Есть ли способ сделать что-то, например, проверить наличие обновлений, только один раз за запуск / запуск приложения?

Извините, если это немного сложно понять, мне трудно объяснить это.

Ответы [ 9 ]

51 голосов
/ 11 декабря 2012

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>

Вы даже можете нажать кнопку «Назад», чтобы приложение перешло в фоновый режим, и не будет тратить ресурсы процессора, только ресурсы памяти, а затем вы сможете запустить его снова и конструкторвсе еще не огонь, так как заявка еще не была завершена.

Вы можете очистить память в диспетчере задач, чтобы все приложения были закрыты, а затем повторно запустили ваше приложение, чтобы убедиться, что ваш код инициализации снова запускается.

4 голосов
/ 07 сентября 2014

Подход с общими предпочтениями беспорядочный, и у класса приложения нет доступа к деятельности.

Другой альтернативой, которую я использовал, является наличие экземпляра сохраненного фрагмента, и в этом экземпляре можно сделать гораздо больше, особенно если вам нужен доступ к основному интерфейсу действий.

Для этого примера я использовал asynctask внутри сохраненного фрагмента. Мой AsyncTask имеет обратные вызовы родительской активности. Гарантируется, что он запускается только один раз для каждого приложения, потому что фрагмент никогда не уничтожается и не воссоздается, когда уничтожается и воссоздается одно и то же действие. Это сохранившийся фрагмент.

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

Затем в основном (или родительском) действии, где вы хотите, чтобы этот фрагмент задачи запуска запускался один раз.

@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 голосов
/ 09 сентября 2011

похоже, что вам, возможно, придется сделать что-то вроде этого

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

Вы можете делать это каждый раз, чтобы проверить, было ли обновлено приложение, поэтому оно запускается только один раз для обновления приложения

2 голосов
/ 09 сентября 2011

Да, вы можете сделать это, используя концепцию SharedPrefernce для Android. Просто создайте логический флаг, сохраните его в SharedPrefernce и проверьте его значение в методе onCreate ().

0 голосов
/ 03 ноября 2017
 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 голосов
/ 15 июня 2017

Я просто решил сделать это сам, я снова и снова открывал свою основную деятельность во время выполнения приложения. Хотя конструктор является подходящим подходом для некоторых вещей, он не позволяет вам получить доступ к текущему контексту приложения, чтобы писать тосты среди прочего .

Мое решение состояло в том, чтобы создать простое логическое значение firstRun со значением true в классе моей функции MainActivity, после чего я запускаю содержимое оператора 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 голосов
/ 25 июня 2012
      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 голосов
/ 09 сентября 2011

Используйте SharedPreference для этого -

  1. Если вы не перезапускаете свою активность запуска после того, как ваше приложение активно, то в этом случае вы используете его.

  2. Используйте это на экране-заставке, если вы внедряете его в приложение.

  3. Если вы не используете заставку, вам нужно создать действие без видаустановить и включить его вызов, вы можете запустить обновление и начать свою основную деятельность.

вы можете использовать для этого значение счетчика или логическое значение.

Вот документ SharedPreference:

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

0 голосов
/ 09 сентября 2011

Я делаю это так же, как описано в другом ответе.У меня просто есть глобальная переменная в первом действии, которая соответствует номеру выпуска из манифеста.Я увеличиваю его при каждом обновлении, и когда чек видит большее число, он выполняет одноразовый код.

В случае успеха он записывает новый номер в общие настройки, поэтому он не будет делать это до следующего обновления.

Убедитесь, что вы присвоили значение по умолчанию -1, когда вы извлекаете версию из общих настроек, чтобы вы допустили ошибку на стороне повторного запуска кода, а не на его запуске и неправильном обновлении приложения.

...