Как программно «перезапустить» приложение Android?

Во-первых, я знаю, что на самом деле не следует убивать / перезапускать приложение на Android. В моем случае использования я хочу восстановить заводские настройки своего приложения в конкретном случае, когда сервер отправляет конкретная информация для клиента.

Пользователь может войти в систему на сервере только с ОДНИМ экземпляром приложения (т. е. использование нескольких устройств не допускается). Если другой экземпляр получает эту блокировку для входа в систему, тогда все остальные экземпляры этого пользователя должны удалить свои данные (восстановить заводские настройки), чтобы сохранить согласованность.

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

Из-за этой возможности принудительного использования нам нужно всегда проверять в конкретном случае, что он имеет блокировку. Это делается (почти) при каждом запросе к серверу. Сервер может отправить «неправильный идентификатор блокировки». Если это обнаружено, клиентское приложение должно удалить все.


Это был пример использования.

У меня есть Activity A, которое запускает действие Login Activity L или основное Activity B приложения в зависимости от значение sharedPrefs. После запуска L или B он закрывается, так что работают только L или B. Таким образом, в случае, если пользователь уже вошел в систему, B сейчас работает.

B запускает C. C вызывает startService для IntentService D. В результате получается следующий стек:

(A)> B> C> D

Из метода onHandleIntent объекта D событие отправляется в ResultReceiver R.

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

После сброса настроек я хочу перезапустить приложение (чтобы закрыть все действия) и снова запустить только A, который затем запускает логин Действие L и завершается само:

(A)> L

Метод onClick диалогового окна выглядит так:

@Override
public void onClick(DialogInterface dialog, int which) {

    // Will call onCancelListener
    MyApplication.factoryReset(); // (Deletes the database, clears sharedPrefs, etc.)
    Intent i = new Intent(MyApp.getContext(), A.class);
    i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    MyApp.getContext().startActivity(i);
}

И это класс MyApp :

public class MyApp extends Application {
    private static Context context;

    @Override
    public void onCreate() {
        super.onCreate();
        context = getApplicationContext();
    }

    public static Context getContext() {
        return context;
    }

    public static void factoryReset() {
        // ...
    }
}

проблема в том, что если я использую FLAG_ACTIVITY_NEW_TASK , действия B и C все еще выполняются. Если я нажму кнопку «Назад» при входе в систему Activity , я вижу C, но хочу вернуться на главный экран.

Если я не установил FLAG_ACTIVITY_NEW_TASK , я получаю ошибка:

07-07 12:27:12.272: ERROR/AndroidRuntime(9512): android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity  context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?

Я не могу использовать Контекст действий , потому что ServiceIntent D также может быть вызван из фоновой задачи, которая запускается AlarmManager .

Итак, как я могу решить эту проблему, чтобы стек действий стал (A)> L?

209
задан Athira 30 May 2019 в 00:51
поделиться

1 ответ

Я нашел, что это работает над API 29 и позже - в целях уничтожения и перезапуска приложения, как будто пользователь запустил его, когда это не работало.

public void restartApplication(final @NonNull Activity activity) {
   // Systems at 29/Q and later don't allow relaunch, but System.exit(0) on
   // all supported systems will relaunch ... but by killing the process, then
   // restarting the process with the back stack intact. We must make sure that
   // the launch activity is the only thing in the back stack before exiting.
   final PackageManager pm = activity.getPackageManager();
   final Intent intent = pm.getLaunchIntentForPackage(activity.getPackageName());
   activity.finishAffinity(); // Finishes all activities.
   activity.startActivity(intent);    // Start the launch activity
   System.exit(0);    // System finishes and automatically relaunches us.
}

, Который был сделан, когда действие средства запуска в приложении имеет это:

<intent-filter>
    <action android:name="android.intent.action.VIEW"/>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

я видел, что комментарии утверждают, что категория ЗНАЧЕНИЯ ПО УМОЛЧАНИЮ необходима, но я не нашел, что это имеет место. Я подтвердил, что Объект приложения в моем приложении воссоздается, таким образом, я полагаю, что процесс действительно был уничтожен и перезапущен.

единственная цель, для которой я использую это, состоит в том, чтобы перезапустить приложение после того, как пользователь включил или отключил катастрофический отказ, сообщающий для Firebase Crashlytics. Согласно их документам, приложение должно быть перезапущено (процесс, уничтоженный и воссозданный) для того изменения для вступления в силу.

1
ответ дан 23 November 2019 в 04:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: