Android-приложение перезапускается после сбоя/силы закрытия
Мое приложение для Android запускается после принудительного закрытия, через мое приложение, состоящее из 20 видов деятельности, я полагаюсь на статические данные, созданные в основном действии. Таким образом, как только приложение становится разбитым, все мои статические данные теряются, и когда приложение автоматически перезапускается, у него нет никаких важных данных для работы.
Мой вопрос: после аварии я хочу, чтобы это случилось.
- Если приложение аварийно завершает работу, я не хочу, чтобы приложение перезапускалось, но я хочу, чтобы весь стек/задача, связанная с этим приложением, была уничтожена из памяти. Пользователь может перезапустить его с самого начала.
- Если я не могу предотвратить перезапуск приложения, по крайней мере, я хочу сохранить важные данные, чтобы при перезапуске приложения я мог их вернуть. Также, когда он перезапускается, я хочу, чтобы мое приложение начиналось с основного действия.
Я знаю, что при сбоях в работе система андроида приведет к следующему действию в стеке на передний план, и это является причиной того, что мое приложение создает избыточные результаты. также я прошел через разработчиков Android, но только то, что я узнал, было создание атрибута в манифесте android:finishOnTaskLaunch="true"
. Но, к сожалению, это не помогает мне. Я был бы признателен за вашу помощь в решении этой проблемы, а также дал бы мне знать причину и анализ.
Ответы
Ответ 1
-
Лучшим решением будет использование данных Static, используйте Shared Preferences
или сохраните данные в Database
, и если произойдет uncaught Exception
, покажите сообщение типа Application has crashed and a report is sent to the admin
, а затем перезапустите действие, которое вызвало авария. Таким образом, пользователь может продолжать использовать приложение.
-
Сделайте то же самое, но вместо перезапуска Activity, которая вызвала перезапуск приложения Exception.
создать класс, используемый для обработки unCaughtException
public class MyExceptionHandler implements
java.lang.Thread.UncaughtExceptionHandler {
private final Context myContext;
private final Class<?> myActivityClass;
public MyExceptionHandler(Context context, Class<?> c) {
myContext = context;
myActivityClass = c;
}
public void uncaughtException(Thread thread, Throwable exception) {
StringWriter stackTrace = new StringWriter();
exception.printStackTrace(new PrintWriter(stackTrace));
System.err.println(stackTrace);// You can use LogCat too
Intent intent = new Intent(myContext, myActivityClass);
String s = stackTrace.toString();
//you can use this String to know what caused the exception and in which Activity
intent.putExtra("uncaughtException",
"Exception is: " + stackTrace.toString());
intent.putExtra("stacktrace", s);
myContext.startActivity(intent);
//for restarting the Activity
Process.killProcess(Process.myPid());
System.exit(0);
}
}
и в каждом действии создайте объект этого класса и установите его как DefaultUncaughtExceptionHandler
Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler(this,
YourCurrentActivity.class));
Ответ 2
public class MyApp extends Application {
private static final String TAG = "MyApp";
private static final String KEY_APP_CRASHED = "KEY_APP_CRASHED";
@Override
public void onCreate() {
super.onCreate();
final UncaughtExceptionHandler defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler( new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread thread, Throwable exception) {
// Save the fact we crashed out.
getSharedPreferences( TAG , Context.MODE_PRIVATE ).edit()
.putBoolean( KEY_APP_CRASHED, true ).apply();
// Chain default exception handler.
if ( defaultHandler != null ) {
defaultHandler.uncaughtException( thread, exception );
}
}
} );
boolean bRestartAfterCrash = getSharedPreferences( TAG , Context.MODE_PRIVATE )
.getBoolean( KEY_APP_CRASHED, false );
if ( bRestartAfterCrash ) {
// Clear crash flag.
getSharedPreferences( TAG , Context.MODE_PRIVATE ).edit()
.putBoolean( KEY_APP_CRASHED, false ).apply();
// Re-launch from root activity with cleared stack.
Intent intent = new Intent( this, MyRootActivity.class );
intent.addFlags( Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK );
startActivity( intent );
}
}
}
Ответ 3
setContentView(R.layout.current);
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(0);
}
code....
(ссылка: Archie.bpgc)
Ответ 4
Если пользователь принудительно останавливает ваше приложение (из "Настройки" > "Приложения" > "Информация о приложении" или из списка последних приложений), или операционная система останавливает ваше приложение, вы можете сохранить все, что вам нужно, используя onSaveInstanceState()
.
Однако, если ваше приложение терпит крах, то вы не можете с ним поделать (кроме того, чтобы периодически сохранять важные вещи в настройках/базах данных и т.д.). Вероятно, лучше сосредоточиться на предотвращении сбоев, а не на попытках справиться с авариями!
Ответ 5
Не хранить данные в статических полях.
Ваш процесс может быть остановлен на событии с низкой памятью, и вы потеряете все.
Ваши действия будут восстановлены из сохраненного состояния, если пользователь снова переключится на ваше приложение, но ваши статические переменные не будут восстановлены.
Ответ 6
Ну, приложение - это не только интерфейс (действия). Представьте, что у вас есть сложное корпоративное приложение, использующее транзакции SQL, безопасность, веб-аутентификацию и т.д.
Практически невозможно сделать каждое действие возможным восстановить весь контекст приложения, используя только общие настройки.
Поэтому в этом случае я использую этот фрагмент кода:
public class MyApplication extends Application {
private static final String TAG = "my.app";
public static final String MainActivityName = "my.app.top.activity";
@Override
public void onCreate() {
try{
ActivityManager am = (ActivityManager) this .getSystemService(ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
ComponentName componentInfo = taskInfo.get(0).topActivity;
if (MainActivityName.length()>0 && !componentInfo.getClassName().equals(MainActivityName)){
Log.d(TAG, "Partial Restart Not Supported! : " +componentInfo.getClassName());
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(0);
return;
}else
Log.d(TAG, "!!! BCSApplication topActivity=" +componentInfo.getClassName());
}catch(Exception eee){}
super.onCreate();
/*
....
*/
}
/*
....
*/
}
Ответ 7
Мое приложение также возобновлялось с пустым экраном, когда он падал. Чтобы решить эту проблему, я проверил объект savedInstanceState на методе onCreate моего основного действия, и если он не является нулевым (значит, он перезагружен системой Android), я закончил свою деятельность. Что-то вроде этого:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState != null) {
finish();
}
}
Это может помочь и в вашем случае.