| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.doumee.keyCabinet.utils; |
| | | |
| | | import android.app.AlarmManager; |
| | | import android.app.PendingIntent; |
| | | import android.content.Context; |
| | | import android.content.Intent; |
| | | import android.content.pm.PackageInfo; |
| | | import android.content.pm.PackageManager; |
| | | import android.content.pm.PackageManager.NameNotFoundException; |
| | | import android.os.Build; |
| | | import android.os.Environment; |
| | | import android.os.Looper; |
| | | |
| | | import com.doumee.keyCabinet.ui.guide.GuideActivity; |
| | | import com.doumee.keyCabinet.ui.main.MainActivity; |
| | | import com.doumee.lib_coremodel.util.SpUtil; |
| | | import com.innohi.YNHAPI; |
| | | |
| | | import java.io.BufferedWriter; |
| | | import java.io.ByteArrayOutputStream; |
| | | import java.io.File; |
| | | import java.io.FileWriter; |
| | | import java.io.IOException; |
| | | import java.io.PrintStream; |
| | | import java.io.PrintWriter; |
| | | import java.io.StringWriter; |
| | | import java.io.Writer; |
| | | import java.lang.Thread.UncaughtExceptionHandler; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.Date; |
| | | import java.util.Properties; |
| | | |
| | | /** |
| | | * |
| | | * |
| | | * UncaughtExceptionHandlerï¼çº¿ç¨æªæè·å¼å¸¸æ§å¶å¨æ¯ç¨æ¥å¤çæªæè·å¼å¸¸çã 妿ç¨åºåºç°äºæªæè·å¼å¸¸é»è®¤æ
åµä¸åä¼åºç°å¼ºè¡å
³éå¯¹è¯æ¡ |
| | | * å®ç°è¯¥æ¥å£å¹¶æ³¨å为ç¨åºä¸çé»è®¤æªæè·å¼å¸¸å¤ç è¿æ ·å½æªæè·å¼å¸¸åçæ¶ï¼å°±å¯ä»¥åäºå¼å¸¸å¤çæä½ ä¾å¦ï¼æ¶éå¼å¸¸ä¿¡æ¯ï¼åéé误æ¥å çã |
| | | * |
| | | * UncaughtExceptionå¤çç±»,å½ç¨åºåçUncaughtå¼å¸¸çæ¶å,ç±è¯¥ç±»æ¥æ¥ç®¡ç¨åº,å¹¶è®°å½åéé误æ¥å. |
| | | */ |
| | | public class CrashHandler implements UncaughtExceptionHandler { |
| | | private static final String TAG = "CrashHandler"; |
| | | private static String PATH = Environment.getExternalStorageDirectory().getPath() + "/log/"; |
| | | public static final String FILE_NAME = "crash"; |
| | | //logæä»¶çåç¼å |
| | | private static final String FILE_NAME_SUFFIX = ".txt"; |
| | | |
| | | public static final String CLIENT_VERSION = "clientVersion"; |
| | | |
| | | /** CrashHandlerå®ä¾ */ |
| | | private static CrashHandler INSTANCE; |
| | | /** ç¨åºçContext对象 */ |
| | | private Context mContext; |
| | | /** ç³»ç»é»è®¤çUncaughtExceptionå¤çç±» */ |
| | | private UncaughtExceptionHandler mDefaultHandler; |
| | | |
| | | /** 使ç¨Propertiesæ¥ä¿å设å¤çä¿¡æ¯åéè¯¯å æ ä¿¡æ¯ */ |
| | | private Properties mDeviceCrashInfo = new Properties(); |
| | | |
| | | /** ä¿è¯åªæä¸ä¸ªCrashHandlerå®ä¾ */ |
| | | private CrashHandler() { |
| | | } |
| | | |
| | | /** è·åCrashHandlerå®ä¾ ,å便¨¡å¼ */ |
| | | public static CrashHandler getInstance() { |
| | | if (INSTANCE == null) { |
| | | INSTANCE = new CrashHandler(); |
| | | } |
| | | return INSTANCE; |
| | | } |
| | | |
| | | /** |
| | | * åå§å,注åContext对象, è·åç³»ç»é»è®¤çUncaughtExceptionå¤çå¨, 设置该CrashHandler为ç¨åºçé»è®¤å¤çå¨ |
| | | * |
| | | * @param ctx |
| | | */ |
| | | public void init(Context ctx) { |
| | | mContext = ctx; |
| | | //PATH = ctx.getFilesDir().getParentFile().getAbsolutePath()+ "/log/"; |
| | | mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); |
| | | Thread.setDefaultUncaughtExceptionHandler(this); |
| | | // æ¶é设å¤ä¿¡æ¯ |
| | | collectCrashDeviceInfo(mContext); |
| | | } |
| | | |
| | | @Override |
| | | public void uncaughtException(Thread thread, Throwable ex) { |
| | | try { |
| | | //导åºå¼å¸¸ä¿¡æ¯å°SDå¡ä¸ |
| | | YNHAPI mAPI = YNHAPI.getInstance(); |
| | | mAPI.setNavigationBarVisibility(YNHAPI.NavigationBarVisibility.VISIBLE); |
| | | dumpExceptionToSDCard(ex); |
| | | long time = SpUtil.getLong("err_app"); |
| | | SpUtil.saveLong("err_app",System.currentTimeMillis()); |
| | | if(System.currentTimeMillis()-time>60000){ |
| | | //æ¥éé´é60ç§ï¼æéå¯ |
| | | //System.out.println("éå¯åºç¨"); |
| | | // å建ä¸ä¸ªæ°çå¯å¨æå¾ |
| | | Intent intent = new Intent(mContext, MainActivity.class); |
| | | // 设置FLAG_ACTIVITY_CLEAR_TASKæ å¿ä½ |
| | | intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); |
| | | // 使ç¨PendingIntentå
è£
å¯å¨æå¾ |
| | | PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT); |
| | | // è·åAlarmManagerå®ä¾ |
| | | AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); |
| | | // å¨500毫ç§å触åéå¯æä½ |
| | | alarmManager.set(AlarmManager.RTC, System.currentTimeMillis() + 10, pendingIntent); |
| | | |
| | | android.os.Process.killProcess(android.os.Process.myPid()); |
| | | System.exit(1); |
| | | } |
| | | //è¿éå¯ä»¥éè¿ç½ç»ä¸ä¼ å¼å¸¸ä¿¡æ¯å°æå¡å¨ï¼ä¾¿äºå¼å人ååææ¥å¿ä»èè§£å³bug |
| | | |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | System.out.println("é误æ¥å¿1"+e.getMessage()); |
| | | } |
| | | //æå°åºå½åè°ç¨æ ä¿¡æ¯ |
| | | ex.printStackTrace(); |
| | | //å¦æç³»ç»æä¾äºé»è®¤çå¼å¸¸å¤çå¨ï¼å交ç»ç³»ç»å»ç»ææä»¬çç¨åºï¼å¦åå°±ç±æä»¬èªå·±ç»æèªå·± |
| | | if (mDefaultHandler != null) { |
| | | mDefaultHandler.uncaughtException(thread, ex); |
| | | } else { |
| | | android.os.Process.killProcess(android.os.Process.myPid()); |
| | | } |
| | | |
| | | if (!handleException(ex) && mDefaultHandler != null) { |
| | | // å¦æç¨æ·æ²¡æå¤çå让系ç»é»è®¤çå¼å¸¸å¤ç卿¥å¤ç |
| | | mDefaultHandler.uncaughtException(thread, ex); |
| | | } else { |
| | | /*try { |
| | | Thread.sleep(500); |
| | | } catch (InterruptedException e) { |
| | | Log.e(TAG, "error : ", e); |
| | | }*/ |
| | | /*System.out.println("éå¯åºç¨"); |
| | | // å建ä¸ä¸ªæ°çå¯å¨æå¾ |
| | | Intent intent = new Intent(mContext, GuideActivity.class); |
| | | // 设置FLAG_ACTIVITY_CLEAR_TASKæ å¿ä½ |
| | | intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); |
| | | // 使ç¨PendingIntentå
è£
å¯å¨æå¾ |
| | | PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT); |
| | | // è·åAlarmManagerå®ä¾ |
| | | AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); |
| | | // å¨500毫ç§å触åéå¯æä½ |
| | | alarmManager.set(AlarmManager.RTC, System.currentTimeMillis() + 10, pendingIntent); |
| | | |
| | | android.os.Process.killProcess(android.os.Process.myPid()); |
| | | System.exit(1);*/ |
| | | /*// æªæè·å¼å¸¸åæä»¶ |
| | | writeCrashInfoToFile(ex); |
| | | // éåºæ´ä¸ªåºç¨ |
| | | if (mDefaultHandler != null) { |
| | | mDefaultHandler.uncaughtException(thread, ex); |
| | | } else { |
| | | System.exit(0); |
| | | }*/ |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * èªå®ä¹é误å¤ç,æ¶ééè¯¯ä¿¡æ¯ åéé误æ¥åçæä½å卿¤å®æ. å¼åè
å¯ä»¥æ ¹æ®èªå·±çæ
嵿¥èªå®ä¹å¼å¸¸å¤çé»è¾ |
| | | * |
| | | * @param ex |
| | | * @return true:妿å¤çäºè¯¥å¼å¸¸ä¿¡æ¯;å¦åè¿åfalse |
| | | */ |
| | | private boolean handleException(Throwable ex) { |
| | | if (ex == null) { |
| | | return false; |
| | | } |
| | | // 使ç¨Toastæ¥æ¾ç¤ºå¼å¸¸ä¿¡æ¯ |
| | | new Thread() { |
| | | @Override |
| | | public void run() { |
| | | Looper.prepare(); |
| | | //T.ss("徿±æ,ç¨åºåºç°å¼å¸¸,å³å°éåº"); |
| | | Looper.loop(); |
| | | } |
| | | }.start(); |
| | | // æªæè·å¼å¸¸åæä»¶ |
| | | writeCrashInfoToFile(ex); |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * æ¶éç¨åºå´©æºç设å¤ä¿¡æ¯ |
| | | * |
| | | * @param ctx |
| | | */ |
| | | private void collectCrashDeviceInfo(Context ctx) { |
| | | try { |
| | | PackageManager pm = ctx.getPackageManager(); |
| | | |
| | | PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), |
| | | PackageManager.GET_ACTIVITIES); |
| | | if (pi != null) { |
| | | mDeviceCrashInfo.setProperty(CLIENT_VERSION, |
| | | pi.versionName == null ? "not set" : pi.versionName); |
| | | } |
| | | } catch (NameNotFoundException e) { |
| | | e.printStackTrace(); |
| | | System.out.println("é误æ¥å¿3"+e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å°å¼å¸¸ä¿¡æ¯åå
¥æ¥å¿æä»¶ |
| | | * |
| | | * @param ex |
| | | * @return |
| | | */ |
| | | private String writeCrashInfoToFile(Throwable ex) { |
| | | Writer info = new StringWriter(); |
| | | PrintWriter printWriter = new PrintWriter(info); |
| | | // printStackTrace(PrintWriter s) |
| | | // å°æ¤ throwable åå
¶è¿½è¸ªè¾åºå°æå®ç PrintWriter |
| | | ex.printStackTrace(printWriter); |
| | | |
| | | // getCause() è¿åæ¤ throwable ç causeï¼å¦æ cause ä¸å卿æªç¥ï¼åè¿å nullã |
| | | Throwable cause = ex.getCause(); |
| | | while (cause != null) { |
| | | cause.printStackTrace(printWriter); |
| | | cause = cause.getCause(); |
| | | } |
| | | |
| | | // toString() 以å符串çå½¢å¼è¿å该ç¼å²åºçå½åå¼ã |
| | | String result = info.toString(); |
| | | printWriter.close(); |
| | | |
| | | String errorLog = String |
| | | .format("FINGERPRINT=%s|" |
| | | + "STACK_TRACE=%s|versionName=%s|MODEL=%s|MANUFACTURER=%s|BRAND=%s|RELEASE=%s", |
| | | // 硬件åç§° |
| | | Build.FINGERPRINT, |
| | | // å¼å¸¸ä¿¡æ¯ |
| | | result, |
| | | // åºç¨çæ¬åç§° |
| | | mDeviceCrashInfo.getProperty(CLIENT_VERSION), |
| | | // 设å¤åç§° |
| | | Build.MODEL, |
| | | // 硬件å¶é å |
| | | Build.MANUFACTURER, |
| | | // androidç³»ç»å®å¶å |
| | | Build.BRAND, |
| | | // android SDKçæ¬ |
| | | Build.VERSION.RELEASE); |
| | | //sp.setString(Constants.SP_CRASH_EXCEPTION, errorLog); |
| | | return null; |
| | | } |
| | | |
| | | private void dumpExceptionToSDCard(Throwable ex) throws IOException { |
| | | //妿SDå¡ä¸åå¨ææ æ³ä½¿ç¨ï¼åæ æ³æå¼å¸¸ä¿¡æ¯åå
¥SDå¡ |
| | | if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { |
| | | /*if (Const.DEBUG) { |
| | | LogUtils.w(TAG, "sdcard unmounted,skip dump exception"); |
| | | return; |
| | | }*/ |
| | | return; |
| | | } |
| | | /*File dir = new File(PATH); |
| | | if (!dir.exists()) { |
| | | dir.mkdirs(); |
| | | }*/ |
| | | long current = System.currentTimeMillis(); |
| | | String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(current)); |
| | | try { |
| | | ByteArrayOutputStream out = new ByteArrayOutputStream(); |
| | | PrintStream print = new PrintStream(out); |
| | | //导åºåçå¼å¸¸çæ¶é´ |
| | | print.println(time); |
| | | //å¯¼åºææºä¿¡æ¯ |
| | | dumpPhoneInfo(print); |
| | | print.println(); |
| | | ex.printStackTrace(print); |
| | | //SpUtil.saveString(FILE_NAME+time,new String(out.toByteArray())); |
| | | print.close(); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | System.out.println("é误æ¥å¿2"+e.getMessage()); |
| | | //LogUtils.e(TAG, "dump crash info failed"); |
| | | } |
| | | //以å½åæ¶é´å建logæä»¶ |
| | | File file = new File(PATH , FILE_NAME + time + FILE_NAME_SUFFIX); |
| | | try { |
| | | PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(file))); |
| | | //导åºåçå¼å¸¸çæ¶é´ |
| | | pw.println(time); |
| | | //å¯¼åºææºä¿¡æ¯ |
| | | dumpPhoneInfo(pw); |
| | | pw.println(); |
| | | //导åºå¼å¸¸çè°ç¨æ ä¿¡æ¯ |
| | | ex.printStackTrace(pw); |
| | | pw.close(); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | System.out.println("é误æ¥å¿2"+e.getMessage()); |
| | | //LogUtils.e(TAG, "dump crash info failed"); |
| | | } |
| | | } |
| | | private void dumpPhoneInfo(PrintStream pw) throws NameNotFoundException { |
| | | //åºç¨ççæ¬åç§°åçæ¬å· |
| | | PackageManager pm = mContext.getPackageManager(); |
| | | PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES); |
| | | pw.print("App Version: "); |
| | | pw.print(pi.versionName); |
| | | pw.print('_'); |
| | | pw.println(pi.versionCode); |
| | | //androidçæ¬å· |
| | | pw.print("OS Version: "); |
| | | pw.print(Build.VERSION.RELEASE); |
| | | pw.print("_"); |
| | | pw.println(Build.VERSION.SDK_INT); |
| | | //ææºå¶é å |
| | | pw.print("Vendor: "); |
| | | pw.println(Build.MANUFACTURER); |
| | | //ææºåå· pw.print("Model: "); |
| | | pw.println(Build.MODEL); |
| | | //cpuæ¶æ |
| | | pw.print("CPU ABI: "); |
| | | pw.println(Build.CPU_ABI); } |
| | | |
| | | private void dumpPhoneInfo(PrintWriter pw) throws NameNotFoundException { |
| | | //åºç¨ççæ¬åç§°åçæ¬å· |
| | | PackageManager pm = mContext.getPackageManager(); |
| | | PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES); |
| | | pw.print("App Version: "); |
| | | pw.print(pi.versionName); |
| | | pw.print('_'); |
| | | pw.println(pi.versionCode); |
| | | //androidçæ¬å· |
| | | pw.print("OS Version: "); |
| | | pw.print(Build.VERSION.RELEASE); |
| | | pw.print("_"); |
| | | pw.println(Build.VERSION.SDK_INT); |
| | | //ææºå¶é å |
| | | pw.print("Vendor: "); |
| | | pw.println(Build.MANUFACTURER); |
| | | //ææºåå· pw.print("Model: "); |
| | | pw.println(Build.MODEL); |
| | | //cpuæ¶æ |
| | | pw.print("CPU ABI: "); |
| | | pw.println(Build.CPU_ABI); } |
| | | } |