Подтвердить что ты не робот

Android-приложение перезапускается после сбоя/силы закрытия

Мое приложение для Android запускается после принудительного закрытия, через мое приложение, состоящее из 20 видов деятельности, я полагаюсь на статические данные, созданные в основном действии. Таким образом, как только приложение становится разбитым, все мои статические данные теряются, и когда приложение автоматически перезапускается, у него нет никаких важных данных для работы.

Мой вопрос: после аварии я хочу, чтобы это случилось.

  • Если приложение аварийно завершает работу, я не хочу, чтобы приложение перезапускалось, но я хочу, чтобы весь стек/задача, связанная с этим приложением, была уничтожена из памяти. Пользователь может перезапустить его с самого начала.
  • Если я не могу предотвратить перезапуск приложения, по крайней мере, я хочу сохранить важные данные, чтобы при перезапуске приложения я мог их вернуть. Также, когда он перезапускается, я хочу, чтобы мое приложение начиналось с основного действия.

Я знаю, что при сбоях в работе система андроида приведет к следующему действию в стеке на передний план, и это является причиной того, что мое приложение создает избыточные результаты. также я прошел через разработчиков Android, но только то, что я узнал, было создание атрибута в манифесте android:finishOnTaskLaunch="true". Но, к сожалению, это не помогает мне. Я был бы признателен за вашу помощь в решении этой проблемы, а также дал бы мне знать причину и анализ.

4b9b3361

Ответ 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();
    }
}

Это может помочь и в вашем случае.