Подтвердить что ты не робот

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

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

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

Мне очень жаль, если это немного сложно понять, у меня возникают трудности с объяснением этого.

4b9b3361

Ответ 1

SharedPreferences кажется уродливым решением для меня. Это гораздо более удобно, когда вы используете конструктор приложений для таких целей.

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

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>

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

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

Ответ 2

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

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

В этом примере я использовал 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. Я просто вычислил его другие варианты использования, кроме изменений конфигурации.

Ответ 3

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

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

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

Ответ 4

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

Ответ 5

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

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

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

Ответ 6

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

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

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

  • Если вы не используете какой-либо всплывающий экран, вам нужно создать действие без набора представлений и на нем вызывать вызов, вы можете начать обновление и начать свою основную деятельность.

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

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

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

Ответ 7

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


                    }

Ответ 8

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

Мое решение состояло в том, чтобы создать простой "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
}

Ответ 9

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