在Android應用程序中,如果我們沒有得到正確的例外,我們通常會得到「強制關閉」錯誤。Android:如何在「強制關閉」後自動重啓應用程序?
如何強制關閉時自動重新啓動應用程序?
是否有任何特定權限用於此?
在Android應用程序中,如果我們沒有得到正確的例外,我們通常會得到「強制關閉」錯誤。Android:如何在「強制關閉」後自動重啓應用程序?
如何強制關閉時自動重新啓動應用程序?
是否有任何特定權限用於此?
要做到這一點,你必須做兩件事情:
見下文如何做這些:
呼叫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方法? plz幫助。謝謝。 – 2011-11-04 05:38:36
@MayuMayooresan您可以擴展應用程序類或Activity並在onCreate()中執行以下操作: Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler(){...}); – AgentKnopf 2012-04-04 07:50:35
如果您擴展了活動,值得注意的是您需要爲每個可以充當應用程序入口點的活動(包括Android OS可能決定啓動的活動 - 例如窗口死亡等)執行相同的操作 – Mick 2012-05-31 19:47:18
訣竅是確保它不首先強制關閉。
如果您使用the Thread.setDefaultUncaughtExceptionHandler()
method您可以捕獲導致您的應用程序強制關閉的例外。
查看使用UncaughtExceptionHandler
來記錄應用程序引發的異常的示例at this question。
感謝您的線索。 後續問題是何時調用UncaughtExceptionHandler.uncaughtException? 如果用戶沒有點擊「強制關閉」按鈕,UncaughtExceptionHandler.uncaughtException仍會被調用嗎? – Johnny 2010-04-21 09:46:34
@Johnny當應用程序引發一個未處理的異常時,您會收到強制關閉。如果使用UncaughtExceptionHandler,則應用程序可以處理其所有異常,並且用戶永遠不會看到強制關閉對話框。換句話說,當強制關閉對話框被顯示時,UncaughtExceptionHandler被調用。但是,您將需要小心如何處理應用程序捕獲的任何意外異常;繼續和假裝什麼都沒發生顯然是有風險的。 – 2010-04-21 10:08:10
感謝您的解釋。它很好地解釋了UncaughtExceptionHandler。 但我見過的應用程序會在強制關閉後自動重啓。例如。啓動器(可能不是一個好例子,但我看到第三方應用程序也是這樣工作的)。如果我想讓我的應用程序像這樣工作會怎樣?我必須使用某種系統權限嗎? – Johnny 2010-04-21 15:13:22
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();
}
如果使用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);
}
});
只是在你的包添加該類
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));
試着獲得正確的例外。自動重新啓動的應用程序可能會讓用戶煩惱。 – 2010-04-21 09:17:44
我只是想重新啓動我的應用程序,如果它墜毀。我認爲這比煩人更友好,特別是當用戶在我的應用程序中時。 是的,我試圖讓每個例外都正確。 :) – Johnny 2010-04-21 09:47:56
@Johnny:請爲你的問題分享解決方案。 – 2012-07-02 14:29:38