Как я могу выполнить что-то только один раз за запуск приложения?
Я хотел бы использовать средство проверки обновлений в приложении, и мне, очевидно, нужно, чтобы это отображалось только при запуске приложения. Если я выполняю вызов в методе onCreate()
или onStart()
, он будет отображаться каждый раз, когда создается действие, и это не является жизнеспособным решением.
Итак, мой вопрос: Есть ли способ сделать что-то, например проверять наличие обновлений, только один раз для запуска/запуска приложения?
Мне очень жаль, если это немного сложно понять, у меня возникают трудности с объяснением этого.
Ответы
Ответ 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();
}
}