Android:如何在“强制关闭”后自动重启应用程序?

Posted

技术标签:

【中文标题】Android:如何在“强制关闭”后自动重启应用程序?【英文标题】:Android: How to auto-restart an application after it has been "force closed"? 【发布时间】:2011-02-10 12:14:13 【问题描述】:

android 应用程序中,如果我们没有正确处理异常,我们通常会收到“强制关闭”错误。

如果我的应用程序被强制关闭,如何自动重启?

是否为此使用了任何特定权限?

【问题讨论】:

尝试正确处理异常。自动重启的应用程序可能会让用户感到厌烦。 如果我的应用程序崩溃了,我只想重新启动它。我认为它会比烦人更友好,尤其是当用户在我的应用程序中时。是的,我正在努力纠正每个例外情况。 :) @Johnny : 请分享您的问题的解决方案。 检查 this article 以在出现任何异常时重新启动您的应用程序。 【参考方案1】:

要做到这一点,你必须做两件事:

    避免“强制关闭” - 应用程序崩溃的标准方式。 在崩溃发生时设置重启机制。

请参阅下面的操作方法:

    调用Thread.setDefaultUncaughtExceptionHandler() 以捕获所有未捕获的异常,在这种情况下将调用uncaughtException() 方法。 “强制关闭”不会出现,应用程序将无响应,这不是一件好事。 为了在应用程序崩溃时重新启动您的应用程序,您应该执行以下操作:

    onCreate 方法中,在你的主活动中初始化一个PendingIntent 成员:

    Intent intent = PendingIntent.getActivity(
        YourApplication.getInstance().getBaseContext(),
        0,
        new Intent(getIntent()),
        getIntent().getFlags());
    

然后将以下内容放入您的uncaughtException() 方法中:

AlarmManager mgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 2000, intent);
System.exit(2);

您还必须致电System.exit(),否则将无法正常工作。 这样,您的应用程序将在 2 秒后重新启动。

最终,您可以在应用程序崩溃的意图中设置一些标志,并在您的 onCreate() 方法中显示一个对话框“对不起,应用程序崩溃了,希望再也不会 :)”。

【讨论】:

我想通了。现在的问题是在哪里实现 uncaughtException 方法?请帮忙。谢谢。 @MayuMayooresan 您可以扩展应用程序类或 Activity 并在 onCreate() 中执行以下操作: Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler()...); 如果您扩展活动,值得注意的是,您需要对每个可以充当应用程序入口点的活动(包括 Android 操作系统可能决定启动的活动 - 例如当窗口死亡等) 通过管理应用程序菜单强制停止进程后,它似乎在 ICS 中不起作用。 YourApplication 是什么意思?我使用了@Mahesh 的建议,但没有奏效。请有人解释一下。【参考方案2】:

诀窍是首先确保它不会强制关闭。

如果您使用the Thread.setDefaultUncaughtExceptionHandler() method,您可以捕获导致您的应用程序强制关闭的异常。

查看at this question 以获取使用UncaughtExceptionHandler 记录应用程序引发的异常的示例。

【讨论】:

感谢您的提示。一个后续问题是何时调用 UncaughtExceptionHandler.uncaughtException?如果用户没有点击“强制关闭”按钮,UncaughtExceptionHandler.uncaughtException 还会被调用吗? @Johnny 当应用程序引发未处理的异常时,您将获得强制关闭。如果您使用 UncaughtExceptionHandler,那么您的应用程序可以处理其所有异常,并且用户将永远不会看到强制关闭对话框。换句话说,当将显示强制关闭对话框时调用 UncaughtExceptionHandler。但是,您需要小心处理应用程序捕获的任何意外异常;继续并假装什么都没发生显然是有风险的。 感谢您的解释。它很好地解释了 UncaughtExceptionHandler。但我见过强制关闭后会自动重启的应用程序。例如。启动器(也许不是一个很好的例子,但我已经看到第三方应用程序也以这种方式工作)。如果我希望我的应用程序像这样工作怎么办?我必须使用某种系统权限吗?【参考方案3】:

如果您使用 Crittercism 或其他一些错误报告服务,接受的答案几乎是正确的..

final UncaughtExceptionHandler defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() 
            public void uncaughtException(Thread thread, Throwable ex) 
              Intent launchIntent = new Intent(activity().getIntent());
              PendingIntent pending = PendingIntent.getActivity(CSApplication.getContext(), 0,
                    launchIntent, activity().getIntent().getFlags());
              getAlarmManager().set(AlarmManager.RTC, System.currentTimeMillis() + 2000, pending);
              defaultHandler.uncaughtException(thread, ex);
            
);

【讨论】:

【参考方案4】:

只需在你的包中添加这个类

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

在您的应用程序或每个活动类中,在 onCreate() 方法中,然后简单地调用:

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

【讨论】:

【参考方案5】:
public class ForceCloseExceptionHandalingActivity extends Activity 
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        setContentView(MyLayout());
        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() 
            @Override
            public void uncaughtException(Thread paramThread, Throwable paramThrowable) 
                myHandaling(paramThread, paramThrowable);
            
        );
    

    private ViewGroup MyLayout()
        LinearLayout mainLayout = new LinearLayout(this);
        mainLayout.setOrientation(LinearLayout.VERTICAL);  
        Button btnHello =new Button(this);
        btnHello.setText("Show all button");
        btnHello.setOnClickListener(new OnClickListener()          
            @Override
            public void onClick(View v)                    
                setContentView(MyLayout2());            
            
        );             
        mainLayout.addView(btnHello);       
        return mainLayout;
    

    private ViewGroup MyLayout2()
        LinearLayout mainLayout = new LinearLayout(this);
        mainLayout.setOrientation(LinearLayout.VERTICAL);  
        Button btnHello =new Button(this);
        btnHello.setText("I am a EEROR uncaughtException");
        btnHello.setOnClickListener(new OnClickListener()          
            @Override
            public void onClick(View v)                    
                Log.e("Alert","btn  uncaughtException::");
                Toast.makeText(ForceCloseExceptionHandalingActivity.this, "Alert uncaughtException222",Toast.LENGTH_LONG).show();
                View buttone = null;
                setContentView(buttone);            
            
        );     
        Button btnHello2 =new Button(this);
        btnHello2.setText("I am a EEROR Try n catch");
        btnHello2.setOnClickListener(new OnClickListener()             
            @Override
            public void onClick(View v)    

                try
                    View buttone = null;
                    setContentView(buttone);
                
                catch (Exception e) 
                    Log.e("Alert","Try n catch:::");
                    Toast.makeText(ForceCloseExceptionHandalingActivity.this, "Alert Try n catch",Toast.LENGTH_LONG).show();
                    setContentView(MyLayout());
                

            
        );     
        mainLayout.addView(btnHello);
        mainLayout.addView(btnHello2);
        return mainLayout;
    
    public void myHandaling(Thread paramThread, Throwable paramThrowable)
        Log.e("Alert","Lets See if it Works !!!" +"paramThread:::" +paramThread +"paramThrowable:::" +paramThrowable);
        Toast.makeText(ForceCloseExceptionHandalingActivity.this, "Alert uncaughtException111",Toast.LENGTH_LONG).show();
        Intent in =new Intent(ForceCloseExceptionHandalingActivity.this,com.satya.ForceCloseExceptionHandaling.ForceCloseExceptionHandalingActivity.class);
        startActivity(in);
        finish();
        android.os.Process.killProcess(android.os.Process.myPid()); 
    
    @Override
    protected void onDestroy() 
        Log.e("Alert","onDestroy:::");
        Toast.makeText(ForceCloseExceptionHandalingActivity.this, "Alert onDestroy",Toast.LENGTH_LONG).show();
        super.onDestroy();  
    

【讨论】:

此代码获取“Thread.setDefaultUncaughtExceptionHandler”并在关闭后调用..【参考方案6】:

以下是对我有用的代码。你应该在MainActivityonCreate()方法中调用appInitialization()

    /*
    * App Restart on crash logic
    * */

    public void triggerRestart(Activity context) 
        Intent intent = new Intent(context, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
        if (context instanceof Activity) 
            finish();
        
        Runtime.getRuntime().exit(0);
    

    private void appInitialization() 
        defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(_unCaughtExceptionHandler);
    

    //make crash report on ex.stackreport
    private Thread.UncaughtExceptionHandler defaultUEH;
    // handler listener
    private Thread.UncaughtExceptionHandler _unCaughtExceptionHandler = new Thread.UncaughtExceptionHandler() 
        @Override
        public void uncaughtException(Thread thread, Throwable ex) 
            // You can code here to send crash analytics
            ex.printStackTrace();
            triggerRestart(currentActivity);
        
    ;

【讨论】:

感谢您提供答案。您能否编辑您的答案以包括对您的代码的解释?这将帮助未来的读者更好地理解正在发生的事情,尤其是那些不熟悉该语言并努力理解这些概念的社区成员。与 OP 的问题相关的关键线是什么?为什么它们比现有五个答案中的建议更受欢迎?

以上是关于Android:如何在“强制关闭”后自动重启应用程序?的主要内容,如果未能解决你的问题,请参考以下文章

Android 捕获异常并在应用崩溃后重启应用

android-在崩溃或退出时远程重启应用程序

添加启动画面后Android应用程序强制关闭

Android,强制关闭应用程序后到底会发生啥?

android 怎么调用强制关闭

如何确定Android应用程序是不是被强制关闭?