2010-04-21 124 views
65

在Android應用程序中,如果我們沒有得到正確的例外,我們通常會得到「強制關閉」錯誤。Android:如何在「強制關閉」後自動重啓應用程序?

如何強制關閉時自動重新啓動應用程序?

是否有任何特定權限用於此?

+4

試着獲得正確的例外。自動重新啓動的應用程序可能會讓用戶煩惱。 – 2010-04-21 09:17:44

+10

我只是想重新啓動我的應用程序,如果它墜毀。我認爲這比煩人更友好,特別是當用戶在我的應用程序中時。 是的,我試圖讓每個例外都正確。 :) – Johnny 2010-04-21 09:47:56

+2

@Johnny:請爲你的問題分享解決方案。 – 2012-07-02 14:29:38

回答

90

要做到這一點,你必須做兩件事情:

  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()方法中,您可以顯示一個對話框「對不起,應用程序崩潰,希望不會再來:)」。

+3

我明白了。現在的問題是在哪裏實現uncaughtException方法? plz幫助。謝謝。 – 2011-11-04 05:38:36

+1

@MayuMayooresan您可以擴展應用程序類或Activity並在onCreate()中執行以下操作: Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler(){...}); – AgentKnopf 2012-04-04 07:50:35

+1

如果您擴展了活動,值得注意的是您需要爲每個可以充當應用程序入口點的活動(包括Android OS可能決定啓動的活動 - 例如窗口死亡等)執行相同的操作 – Mick 2012-05-31 19:47:18

15

訣竅是確保它不首先強制關閉。

如果您使用the Thread.setDefaultUncaughtExceptionHandler() method您可以捕獲導致您的應用程序強制關閉的例外。

查看使用UncaughtExceptionHandler來記錄應用程序引發的異常的示例at this question

+1

感謝您的線索。 後續問題是何時調用UncaughtExceptionHandler.uncaughtException? 如果用戶沒有點擊「強制關閉」按鈕,UncaughtExceptionHandler.uncaughtException仍會被調用嗎? – Johnny 2010-04-21 09:46:34

+3

@Johnny當應用程序引發一個未處理的異常時,您會收到強制關閉。如果使用UncaughtExceptionHandler,則應用程序可以處理其所有異常,並且用戶永遠不會看到強制關閉對話框。換句話說,當強制關閉對話框被顯示時,UncaughtExceptionHandler被調用。但是,您將需要小心如何處理應用程序捕獲的任何意外異常;繼續和假裝什麼都沒發生顯然是有風險的。 – 2010-04-21 10:08:10

+0

感謝您的解釋。它很好地解釋了UncaughtExceptionHandler。 但我見過的應用程序會在強制關閉後自動重啓。例如。啓動器(可能不是一個好例子,但我看到第三方應用程序也是這樣工作的)。如果我想讓我的應用程序像這樣工作會怎樣?我必須使用某種系統權限嗎? – Johnny 2010-04-21 15:13:22

2
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(); 
    } 
+3

過於詳細,不清楚。 – greg7gkb 2013-02-01 03:39:30

+0

此代碼獲取「Thread.setDefaultUncaughtExceptionHandler」並在關閉後調用。 – Satya 2013-02-28 07:10:33

6

如果使用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); 
      } 
}); 
0

只是在你的包添加該類

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

然後,只需撥打:

Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler(this, 
      SplashScreenActivity.class)); 
相關問題