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

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

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

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

【问题讨论】:

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

标签: android


【解决方案1】:

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

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

请参阅下面的操作方法:

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

  2. 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 的问题相关的关键线是什么?为什么它们比现有五个答案中的建议更受欢迎?
      猜你喜欢
      • 1970-01-01
      • 2017-02-23
      • 2015-08-24
      • 2012-09-15
      • 2013-10-01
      • 1970-01-01
      • 2012-04-30
      • 2013-09-01
      • 1970-01-01
      相关资源
      最近更新 更多