Android 应用程序在崩溃/强制关闭时重新启动

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12560590/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 10:59:38  来源:igfitidea点击:

Android App Restarts upon Crash/force close

androidcrashstackforceclose

提问by Techfist

My android app is getting restarted after force close, through my entire application which consist of 20 activities, I am relying on static data created on a main activity. So once the app is getting crashed all my static data is getting lost and when the app auto restarts practically it does not have any essential data to operate upon.

我的 android 应用程序在强制关闭后重新启动,通过我的整个应用程序(由 20 个活动组成),我依赖于在主活动上创建的静态数据。因此,一旦应用程序崩溃,我的所有静态数据都会丢失,并且当应用程序几乎自动重新启动时,它没有任何可操作的基本数据。

My question is, upon crash i want this things to happen

我的问题是,在崩溃时我希望这件事发生

  1. If the app crashes, I don't want the app to restart rather I want all the stack/task related with this app to be wiped out of memory. A user can restart it from the beginning again
  2. If I can't prevent app from restart, at least I want to preserve essential data so that when the app restarts I can assign them back. Also when it restarts I want my app to start from the main activity.
  1. 如果应用程序崩溃,我不希望应用程序重新启动,而是希望将与此应用程序相关的所有堆栈/任务从内存中清除。用户可以重新从头开始
  2. 如果我不能阻止应用程序重新启动,至少我想保留必要的数据,以便在应用程序重新启动时我可以将它们分配回来。此外,当它重新启动时,我希望我的应用程序从主要活动开始。

I know when activity crashes android system will bring next activity in stack to foreground, and this is reason for my app producing redundant results. also i went through the android developers but only thing i got to know was setting up an attribute in Manifest android:finishOnTaskLaunch="true". But unfortunately this is of no help to me. I would appreciate your help on solving this issue, and also letting me know the cause and analysis.

我知道当活动崩溃时,android 系统会将堆栈中的下一个活动带到前台,这就是我的应用程序产生冗余结果的原因。我还浏览了 android 开发人员,但我唯一知道的是在 Manifest 中设置一个属性android:finishOnTaskLaunch="true"。但不幸的是,这对我没有帮助。感谢您帮助解决此问题,并让我知道原因和分析。

回答by Archie.bpgc

  1. Best solution would be instead of using Static data, use Shared Preferencesor store data in a Databaseand if any uncaught Exceptionoccurs, show a message like Application has crashed and a report is sent to the adminand then restart the Activity that caused the Crash. This way user can continue using the application.

  2. Do the same but instead of restarting the Activity which caused the Exception restart the application.

  1. 最好的解决方案是不使用静态数据,而是Shared Preferences在 a 中使用或存储数据Database,如果uncaught Exception发生任何情况,显示一条消息Application has crashed and a report is sent to the admin,然后重新启动导致崩溃的活动。这样用户就可以继续使用该应用程序。

  2. 执行相同的操作,而不是重新启动导致异常的 Activity 重新启动应用程序。

create a class used to handle unCaughtException

创建一个用于处理的类 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);
    }
}

and in every Activity create an Object of this class and set it as the DefaultUncaughtExceptionHandler

并在每个活动中创建此类的一个对象并将其设置为 DefaultUncaughtExceptionHandler

    Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler(this,
            YourCurrentActivity.class));

回答by Paul

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 );
        }
    }
}

回答by konmik

Do not store data in static fields. Your process could be stopped on low memory event and you will lost everything. Your activities will be restored from saved state if user switch to your app again, but your static variables will not get restored.

不要将数据存储在静态字段中。您的进程可能会因内存不足事件而停止,您将丢失一切。如果用户再次切换到您的应用程序,您的活动将从保存的状态恢复,但您的静态变量不会恢复。

回答by PhuocLuong

  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....

(reference: Archie.bpgc)

(参考:Archie.bpgc)

回答by UgglyNoodle

If the user is force stopping your app (from Settings > Apps > App Info, or from the recent apps list) or the operating system is stopping your app, then you can save whatever you need using onSaveInstanceState().

如果用户强制停止您的应用程序(从设置 > 应用程序 > 应用程序信息,或从最近的应用程序列表)或操作系统正在停止您的应用程序,那么您可以使用onSaveInstanceState().

However, if your app is crashing, then there's not much you can do about it (apart from periodically saving important stuff to preferences/databases/etc.). It is probably better to focus on preventing crashes, rather than trying to handle crashes!

但是,如果您的应用程序崩溃,那么您无能为力(除了定期将重要内容保存到首选项/数据库/等)。最好专注于防止崩溃,而不是试图处理崩溃!

回答by BCS Software

Well, an application is not only interface(activities). Imagine you have some complex enterprise application, using SQL transactions, security, Web Authentication, etc.. It is almost impossible to make each activity able to recover the whole app context using only Shared Preferences. So in this case, I use this piece of Code:

好吧,应用程序不仅仅是界面(活动)。想象一下,您有一些复杂的企业应用程序,使用 SQL 事务、安全性、Web 身份验证等。几乎不可能让每个活动都能够仅使用共享首选项来恢复整个应用程序上下文。所以在这种情况下,我使用这段代码:

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();
    /*
    ....
    */
 }
/*
    ....
*/
}

回答by Shivam

My app was also getting resumed with blank screen, when it was getting crashed. To resolve this, I checked the savedInstanceState object on onCreate method of my main activity and if it is not null (means it is restarted by android system) then I finished my activity. Something like that:

我的应用程序在崩溃时也以空白屏幕恢复。为了解决这个问题,我检查了我的主要活动的 onCreate 方法上的 savedInstanceState 对象,如果它不为空(意味着它被 android 系统重新启动),那么我完成了我的活动。类似的东西:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    if (savedInstanceState != null) {
        finish();
    }
}

It may help in your case too.

它也可能对您的情况有所帮助。