Во-первых, я знаю, что не нужно действительно убивать / перезапускать приложение на 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?
источник
Вы можете просто позвонить:
Который используется в библиотеке ProcessPhoenix
Как альтернатива:
Вот немного улучшенная версия ответа @Oleg Koshkin.
Если вы действительно хотите возобновить свою деятельность, включая уничтожение текущего процесса, попробуйте следующий код. Поместите его в HelperClass или там, где вам это нужно.
Это также повторно инициализирует классы jni и все статические экземпляры.
источник
AlarmManager
и неправильное поведение при использовании этого решения. Есть ли лучший подход?Джейк Уортон недавно опубликовал свою библиотеку ProcessPhoenix , которая делает это надежным способом. Вам в основном нужно только позвонить:
Библиотека автоматически завершит вызывающее действие, завершит процесс приложения и впоследствии перезапустит действие приложения по умолчанию.
источник
<category android:name="android.intent.category.DEFAULT" />
к вашей активности по умолчанию <intent-filter> в манифесте приложения.Я немного изменил ответ Ilya_Gazman для использования новых API (IntentCompat устарел, начиная с API 26). Runtime.getRuntime (). Exit (0) кажется лучше, чем System.exit (0).
источник
System.exit(n)
фактически эквивалентен звонку:Runtime.getRuntime().exit(n)
». ВнутреннеSystem.exit()
просто оборачивается и звонитRuntime.getRuntime().exit()
. Нет ничего «лучшего» ни в одном, ни в другом (если не беспокоиться о том, сколько набирает текст или об одном дополнительном слое вызовов методов).Runtime.getRuntime().exit(0)
(илиSystem.exit(0)
), вероятно, будет работать. Некоторые из моих «не очень хороших» комментариев относятся к ответам (например, к письму Ильи Газмана, который с тех пор был отредактирован для включения такого вызова.IntentCompat.makeRestartActivityTask
Новый способ сделать это, используя IntentCompat.makeRestartActivityTask
источник
Application
объект. Поэтому любыеstatic
данные, данные, инициализированные при созданииApplication
классов, или jni, остаются в их текущем состоянии и не инициализируются повторно.IntentCompat.makeRestartActivityTask
сейчас устарела . Если вы проверяете исходный код , это так же просто, как просто добавить флагиIntent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK
.Есть действительно хороший трюк. Моя проблема заключалась в том, что в какой-то действительно старой C ++ jni библиотеке произошла утечка ресурсов. В какой-то момент он перестал функционировать. Пользователь попытался выйти из приложения и запустить его снова - безрезультатно, потому что завершение действия - это не то же самое, что завершение (или уничтожение) процесса. (Кстати, пользователь может перейти к списку запущенных приложений и остановить его оттуда - это будет работать, но пользователи просто не знают, как завершать приложения.)
Если вы хотите наблюдать за эффектом этой функции, добавьте
static
переменную к своей деятельности и увеличивайте ее, скажем, нажатием кнопки. Если вы выйдете из активности приложения, а затем снова вызовете приложение, эта статическая переменная сохранит свое значение. (Если приложение действительно было закрыто, переменной будет присвоено начальное значение.)(И я должен прокомментировать, почему я не хотел вместо этого исправлять ошибку. Библиотека была написана десятилетия назад и с тех пор утечка ресурсов. Руководство считает, что это всегда работало . Стоимость предоставления исправления вместо обходного пути ... Я думаю, вы поняли.)
Теперь, как я могу сбросить разделяемую библиотеку jni (она же динамическая, .so) в исходное состояние? Я решил перезапустить приложение как новый процесс.
Хитрость в том, что System.exit () закрывает текущее действие, а Android заново создает приложение с одним действием меньше.
Итак, код:
Вызывающее действие просто выполняет код
MagicAppRestart.doRestart(this);
, вызывающее действиеonPause()
выполняется, а затем процесс создается заново. И не забудьте упомянуть об этой активности в AndroidManifest.xmlПреимущество этого метода в том, что нет задержек.
UPD: в Android 2.x он работал, но в Android 4 что-то изменилось.
источник
System.exit(0)
наandroid.os.Process.killProcess(android.os.Process.myPid());
? 2) бесконечный цикл, скорее всего, означает, что они не удаляют верхнюю активность при перезапуске приложения. В принципе, вы можете добавить статическую логическую переменную, установить ее в значение true, прежде чем вызывать операцию перезапуска, и после перезапуска она будет иметь значение false. Таким образом, действие может выяснить, произошел ли перезапуск или нет (и если это произошло, просто завершите () ). OTOH, ваш отчет означает, что фокус не работает одинаково на всех устройствах.Мое решение не перезапускает процесс / приложение. Это только позволяет приложению «перезапустить» домашнюю активность (и отклонить все остальные действия). Это выглядит как перезагрузка для пользователей, но процесс такой же. Я думаю, что в некоторых случаях люди хотят достичь этого эффекта, поэтому я просто оставляю это здесь, к вашему сведению.
источник
Хорошо, я провела рефакторинг своего приложения, и я не закончу A автоматически. Я позволю этому бежать всегда и заканчиваю это через
onActivityResult
событие. Таким образом, я могу использоватьFLAG_ACTIVITY_CLEAR_TOP
+FLAG_ACTIVITY_NEW_TASK
флаги, чтобы получить то, что я хочу:и в
ResultReceiver
Спасибо, в любом случае!
источник
источник
Единственный код, который не вызвал «Ваше приложение неожиданно закрылось», выглядит следующим образом. Это также не устаревший код, который не требует внешней библиотеки. Это также не требует таймера.
источник
Я обнаружил, что это работает в API 29 и более поздних версиях - с целью уничтожения и перезапуска приложения, как если бы пользователь запустил его, когда оно не работало.
Это было сделано, когда активность запуска в приложении имеет следующее:
Я видел комментарии, утверждающие, что категория DEFAULT необходима, но я не нашел, чтобы это имело место. Я подтвердил, что объект Application в моем приложении воссоздан, поэтому я считаю, что процесс действительно был убит и перезапущен.
Единственная цель, для которой я использую это, - перезапустить приложение после того, как пользователь включил или отключил отчеты о сбоях для Firebase Crashlytics. Согласно их документам, приложение должно быть перезапущено (процесс убит и заново создан), чтобы это изменение вступило в силу.
источник
Лучший способ полностью перезапустить приложение - это перезапустить его, а не просто перейти к операции с
FLAG_ACTIVITY_CLEAR_TOP
иFLAG_ACTIVITY_NEW_TASK
. Поэтому мое решение состоит в том, чтобы сделать это из вашего приложения или даже из другого приложения, единственное условие - знать имя пакета приложения (пример: ' com.example.myProject ')Пример использования перезапуска или запуска appA из appB :
Вы можете проверить, работает ли приложение:
Примечание : я знаю, что этот ответ немного не в тему, но он может быть действительно полезным для кого-то.
источник
Мой лучший способ перезапустить приложение - использовать
finishAffinity();
С,
finishAffinity();
может использоваться только на версиях JELLY BEAN, поэтому мы можем использовать егоActivityCompat.finishAffinity(YourCurrentActivity.this);
для более низких версий.Затем используйте
Intent
для запуска первое действие, поэтому код будет выглядеть так:Надеюсь, поможет.
источник
Попробуйте использовать
FLAG_ACTIVITY_CLEAR_TASK
источник
Вот пример для перезапуска вашего приложения в общем виде с помощью PackageManager:
источник
Application
объект. Поэтому любые статические данные, данные, инициализированные при созданииApplication
классов, или jni, остаются в их текущем состоянии и не инициализируются повторно.попробуй это:
источник
Прямой запуск начального экрана с помощью
FLAG_ACTIVITY_CLEAR_TASK
иFLAG_ACTIVITY_NEW_TASK
.источник
Мне пришлось добавить обработчик, чтобы задержать выход:
источник
Использование:
Это работает, начиная с уровня API 16 (4.1), я считаю.
источник
Вы можете использовать
startInstrumentation
методActivity
. Вам нужно реализовать пустойInstrumentation
и указанный в манифесте. После этого вы можете вызвать этот метод для перезапуска вашего приложения. Как это:Я получаю имя класса Instrumentation динамически, но вы можете жестко его кодировать. Некоторым нравится это:
Звоните,
startInstrumentation
сделайте перезагрузку вашего приложения. Прочитайте описание этого метода. Но это может быть небезопасно, если вы ведете себя как приложение для уничтоженияисточник
Приложение, над которым я работаю, должно дать пользователю возможность выбирать, какие фрагменты отображать (фрагменты динамически изменяются во время выполнения). Лучшим решением для меня было полностью перезапустить приложение.
Поэтому я перепробовал множество решений, и ни одно из них мне не помогло, но вот:
Надеюсь, что это поможет кому-то еще!
источник
попробуй это:
источник
С библиотекой процесса Феникс . Активность, которую вы хотите перезапустить, называется «A».
Java вкус
Kotlin аромат
источник
Вы можете возобновить свою текущую деятельность следующим образом:
Фрагмент:
Деятельность :
источник