Как программно «перезапустить» приложение Android? - PullRequest
189 голосов
/ 07 июля 2011

Во-первых, я знаю, что на самом деле нельзя убивать / перезапускать приложение на 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, который затем запускает логин Activity 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?

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

Так, как я мог решить это, чтобы стек активности стал (A)> L?

Ответы [ 21 ]

5 голосов
/ 13 февраля 2018

Единственный код, который не вызвал «Ваше приложение неожиданно закрылось», выглядит следующим образом.Это также не устаревший код, который не требует внешней библиотеки.Также не требуется таймер.

public static void triggerRebirth(Context context, Class myClass) {
    Intent intent = new Intent(context, myClass);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    context.startActivity(intent);
    Runtime.getRuntime().exit(0);
}
3 голосов
/ 11 мая 2016

Вот пример для перезапуска вашего приложения с помощью PackageManager:

Intent i = getBaseContext().getPackageManager()
             .getLaunchIntentForPackage( getBaseContext().getPackageName() );
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
3 голосов
/ 07 июля 2011

Попробуйте использовать FLAG_ACTIVITY_CLEAR_TASK

3 голосов
/ 29 сентября 2017

попробуйте это:

Intent intent = getPackageManager().getLaunchIntentForPackage(getPackageName());
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
2 голосов
/ 26 февраля 2019

Мой лучший способ перезапустить приложение - это использовать finishAffinity();
Поскольку finishAffinity(); можно использовать только в версиях JELLY BEAN, поэтому мы можем использовать ActivityCompat.finishAffinity(YourCurrentActivity.this); для более низких версий.

Тогдаиспользуйте Intent для запуска первого действия, поэтому код будет выглядеть так:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
    finishAffinity();
    Intent intent = new Intent(getApplicationContext(), YourFirstActivity.class);
    startActivity(intent);
} else {
    ActivityCompat.finishAffinity(YourCurrentActivity.this);
    Intent intent = new Intent(getApplicationContext(), YourFirstActivity.class);
    startActivity(intent);
}

Надеюсь, это поможет.

2 голосов
/ 19 марта 2013

Использование:

navigateUpTo(new Intent(this, MainActivity.class));

Это работает, начиная с уровня API 16 (4.1), я полагаю.

2 голосов
/ 18 января 2017

Мне пришлось добавить обработчик для задержки выхода:

 mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 200, mPendingIntent);
        final Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                Runtime.getRuntime().exit(0);
            }
        }, 100);
2 голосов
/ 14 сентября 2016

Прямой запуск начального экрана с FLAG_ACTIVITY_CLEAR_TASK и FLAG_ACTIVITY_NEW_TASK.

1 голос
/ 05 июня 2016

Вы можете использовать startInstrumentation метод Activity.Вам нужно реализовать пустой Instrumentation и указать в манифесте.После этого вы можете вызвать этот метод для перезапуска вашего приложения.Например:

try {           
    InstrumentationInfo info = getPackageManager().queryInstrumentation(getPackageName(), 0).get(0);
    ComponentName component = new ComponentName(this, Class.forName(info.name));
    startInstrumentation(component, null, null);
} catch (Throwable e) {             
    new RuntimeException("Failed restart with Instrumentation", e);
}

Я получаю имя класса Instrumentation динамически, но вы можете жестко его кодировать.Некоторым это нравится:

try {           
    startInstrumentation(new ComponentName(this, RebootInstrumentation.class), null, null); 
} catch (Throwable e) {             
    new RuntimeException("Failed restart with Instrumentation", e);
}

Звоните startInstrumentation перезагрузите ваше приложение.Прочитайте описание этого метода.Но это может быть небезопасно, если вы будете действовать как kill app.

1 голос
/ 21 ноября 2016

Приложение, над которым я работаю, должно дать пользователю возможность выбирать, какие фрагменты отображать (фрагменты динамически изменяются во время выполнения).Лучшим решением для меня было перезапустить полностью приложение.

Итак, я перепробовал множество решений, и ни одно из них не помогло мне, но это:

final Intent mStartActivity = new Intent(SettingsActivity.this, Splash.class);
final int mPendingIntentId = 123456;
final PendingIntent mPendingIntent = PendingIntent.getActivity(SettingsActivity.this, mPendingIntentId, mStartActivity,
                    PendingIntent.FLAG_CANCEL_CURRENT);
final AlarmManager mgr = (AlarmManager) SettingsActivity.this.getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
this.finishAffinity(); //notice here
Runtime.getRuntime().exit(0); //notice here

Надеюсь, что это поможет кому-то еще!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...