Android App中多程序問題:捕獲異常資訊並重啟應用
App crash原因以及解決辦法- https://blog.csdn.net/yangtuxiaojie/article/details/47123243
Android在程式崩潰或者捕獲異常之後重新啟動app- https://www.cnblogs.com/dingxiansen/p/8628998.html
如何使用UncaughtExceptionHandler捕獲程式崩潰錯誤資訊-https://blog.csdn.net/u013171283/article/details/79044984
--瞭解以下兩個類:android.app.Application和java.lang.Thread.UncaughtExceptionHandler。
Application:用來管理應用程式的全域性狀態。在應用程式啟動時Application會首先建立,然後才會根據情況(Intent)來啟動相應的Activity和Service。本示例中將在自定義加強版的Application中註冊未捕獲異常處理器。
Thread.UncaughtExceptionHandler:執行緒未捕獲異常處理器,用來處理未捕獲異常。如果程式出現了未捕獲異常,預設會彈出系統中強制關閉對話方塊。我們需要實現此介面,並註冊為程式中預設未捕獲異常處理。這樣當未捕獲異常發生時,就可以做一些個性化的異常處理操作。
> 實現UncaughtExceptionHandler介面,捕獲到程序奔潰資訊,並重啟應用?
如何殺死異常程序,重啟應用,就得使用PendingIntent,這個類是android中對Intent類的包裝,可以去檢視android API。通過AlarmManager 啟動它,並且關閉開啟的Activity殺死異常程序就能夠實現重新啟動應用。
1、收集所有 avtivity 用於徹底退出應用
2、捕獲崩潰異常,儲存錯誤日誌,並重啟應用
public class HKBaseApplication extends Application {
// activity物件列表,用於activity統一管理
private List<Activity> activityList;
// 異常捕獲
protected boolean isNeedCaughtExeption = true;// 是否捕獲未知異常
private PendingIntent restartIntent;
private MyUncaughtExceptionHandler uncaughtExceptionHandler;
private String packgeName;
@Override
public void onCreate() {
super.onCreate();
activityList = new ArrayList<Activity>();
packgeName = getPackageName();
if (isNeedCaughtExeption) {
cauchException();
}
}
// -------------------異常捕獲-----捕獲異常後重啟系統-----------------//
private void cauchException() {
Intent intent = new Intent();
// 引數1:包名,引數2:程式入口的activity
intent.setClassName(packgeName, packgeName + ".LoginActivity");
restartIntent = PendingIntent.getActivity(getApplicationContext(), -1, intent,
Intent.FLAG_ACTIVITY_NEW_TASK);
// 程式崩潰時觸發執行緒
uncaughtExceptionHandler = new MyUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(uncaughtExceptionHandler);
}
// 建立服務用於捕獲崩潰異常
private class MyUncaughtExceptionHandler implements UncaughtExceptionHandler {
@Override
public void uncaughtException(Thread thread, Throwable ex) {
// 儲存錯誤日誌
saveCatchInfo2File(ex);
// 1秒鐘後重啟應用
AlarmManager mgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, restartIntent);
// 關閉當前應用
finishAllActivity();
finishProgram();
}
};
/**
* 儲存錯誤資訊到檔案中
*
* @return 返回檔名稱
*/
private String saveCatchInfo2File(Throwable ex) {
Writer writer = new StringWriter();
PrintWriter printWriter = new PrintWriter(writer);
ex.printStackTrace(printWriter);
Throwable cause = ex.getCause();
while (cause != null) {
cause.printStackTrace(printWriter);
cause = cause.getCause();
}
printWriter.close();
String sb = writer.toString();
try {
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
String time = formatter.format(new Date());
String fileName = time + ".txt";
System.out.println("fileName:" + fileName);
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
String filePath = Environment.getExternalStorageDirectory() + "/HKDownload/" + packgeName
+ "/crash/";
File dir = new File(filePath);
if (!dir.exists()) {
if (!dir.mkdirs()) {
// 建立目錄失敗: 一般是因為SD卡被拔出了
return "";
}
}
System.out.println("filePath + fileName:" + filePath + fileName);
FileOutputStream fos = new FileOutputStream(filePath + fileName);
fos.write(sb.getBytes());
fos.close();
//檔案儲存完了之後,在應用下次啟動的時候去檢查錯誤日誌,發現新的錯誤日誌,就傳送給開發者
}
return fileName;
} catch (Exception e) {
System.out.println("an error occured while writing file..." + e.getMessage());
}
return null;
}
// ------------------------------activity管理-----------------------//
// activity管理:從列表中移除activity
public void removeActivity(Activity activity) {
activityList.remove(activity);
}
// activity管理:新增activity到列表
public void addActivity(Activity activity) {
activityList.add(activity);
}
// activity管理:結束所有activity
public void finishAllActivity() {
for (Activity activity : activityList) {
if (null != activity) {
activity.finish();
}
}
}
// 結束執行緒,一般與finishAllActivity()一起使用
// 例如: finishAllActivity;finishProgram();
public void finishProgram() {
android.os.Process.killProcess(android.os.Process.myPid());
}
}
或
public class MyApplication extends Application implements Thread.UncaughtExceptionHandler {
@Override
public void onCreate() {
super.onCreate();
//設定Thread Exception Handler
Thread.setDefaultUncaughtExceptionHandler(this);
}
@Override
public void uncaughtException(Thread thread, Throwable ex) {
System.out.println("uncaughtException");
System.exit(0);
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
/*處理崩潰重疊*/
public class UnCeHandler implements Thread.UncaughtExceptionHandler {
private Thread.UncaughtExceptionHandler mDefaultHandler;
public static final String TAG = "CatchExcep";
AppApplication application;
public UnCeHandler(AppApplication application){
//獲取系統預設的UncaughtException處理器
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
this.application = application;
}
@Override
public void uncaughtException(Thread thread, Throwable ex) {
if(!handleException(ex) && mDefaultHandler != null){
//如果使用者沒有處理則讓系統預設的異常處理器來處理
mDefaultHandler.uncaughtException(thread, ex);
}else{
try{
Thread.sleep(2000);
}catch (InterruptedException e){
Log.e(TAG, "error : ", e);
}
Intent intent = new Intent(application.getApplicationContext(), MainActivity.class);
PendingIntent restartIntent = PendingIntent.getActivity(
application.getApplicationContext(), 0, intent, Intent.FLAG_ACTIVITY_NEW_TASK);
//退出程式
AlarmManager mgr = (AlarmManager)application.getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000,
restartIntent); // 1秒鐘後重啟應用
application.finishActivity();
}
}
/**
* 自定義錯誤處理,收集錯誤資訊 傳送錯誤報告等操作均在此完成.
*
* @param ex
* @return true:如果處理了該異常資訊;否則沒有處理返回false.
*/
private boolean handleException(Throwable ex) {
if (ex == null) {
return false;
}
//使用Toast來顯示異常資訊
new Thread(){
@Override
public void run() {
Looper.prepare();
Toast.makeText(application.getApplicationContext(), "很抱歉,程式出現異常,即將退出.",
Toast.LENGTH_SHORT).show();
Looper.loop();
}
}.start();
return true;
}
}