| package com.secondworld.universalsdk; | 
|   | 
| import android.content.Context; | 
| import android.content.pm.PackageInfo; | 
| import android.content.pm.PackageManager; | 
| import android.os.Build; | 
| import android.os.Looper; | 
| import android.os.SystemClock; | 
| import android.widget.Toast; | 
|   | 
| import java.io.File; | 
| import java.io.FileOutputStream; | 
| import java.io.FilenameFilter; | 
| import java.io.PrintWriter; | 
| import java.io.StringWriter; | 
| import java.io.Writer; | 
| import java.text.DateFormat; | 
| import java.text.SimpleDateFormat; | 
| import java.util.Calendar; | 
| import java.util.Date; | 
| import java.util.HashMap; | 
| import java.util.Map; | 
|   | 
| /** | 
|  * Created by Administrator on 2018/7/19 0019. | 
|  */ | 
|   | 
| public class CrashCatchUtil implements Thread.UncaughtExceptionHandler | 
| { | 
|     private static final String TAG = "CrashCatchUtil"; | 
|     private Context m_Context; | 
|     private Thread.UncaughtExceptionHandler m_UncaughtExceptionHandler; | 
|     private Map<String, String> m_DevicceInfo = new HashMap<>(); | 
|   | 
|     private CrashCatchUtil() {} | 
|   | 
|     private static CrashCatchUtil m_Instance; | 
|   | 
|     public static CrashCatchUtil getInstance() | 
|     { | 
|         if (m_Instance == null) | 
|         { | 
|             m_Instance = new CrashCatchUtil(); | 
|         } | 
|         return m_Instance; | 
|     } | 
|   | 
|     public void init(Context context) | 
|     { | 
|         m_Context = context; | 
|         m_UncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler(); | 
|         Thread.setDefaultUncaughtExceptionHandler(this); | 
|         autoClear(5); | 
|     } | 
|   | 
|     @Override | 
|     public void uncaughtException(Thread thread, Throwable throwable) | 
|     { | 
|         if (!handleException(throwable) && m_UncaughtExceptionHandler != null) | 
|         { | 
|             m_UncaughtExceptionHandler.uncaughtException(thread, throwable); | 
|         } | 
|         else | 
|         { | 
|             SystemClock.sleep(3000); | 
|             android.os.Process.killProcess(android.os.Process.myPid()); | 
|             System.exit(1); | 
|         } | 
|     } | 
|   | 
|     private void recordDeviceInfo() | 
|     { | 
|         m_DevicceInfo.clear(); | 
|         m_DevicceInfo.put("brand", Build.BRAND); | 
|         m_DevicceInfo.put("model", Build.MODEL); | 
|         m_DevicceInfo.put("android_version", String.valueOf(Build.VERSION.SDK_INT)); | 
|         try | 
|         { | 
|             PackageManager _pkgMgr = m_Context.getPackageManager(); | 
|             PackageInfo _pkgInfo = _pkgMgr.getPackageInfo(m_Context.getPackageName(), | 
|                                                           PackageManager.GET_ACTIVITIES); | 
|             if (_pkgInfo != null) | 
|             { | 
|                 m_DevicceInfo.put("versionName", _pkgInfo.versionName); | 
|                 m_DevicceInfo.put("versionCode", String.valueOf(_pkgInfo.versionCode)); | 
|             } | 
|         } catch (PackageManager.NameNotFoundException e) | 
|         { | 
|             e.printStackTrace(); | 
|         } | 
|     } | 
|   | 
|     private boolean handleException(Throwable throwable) | 
|     { | 
|         if (throwable == null) | 
|         { | 
|             return false; | 
|         } | 
|   | 
|         try | 
|         { | 
|             new Thread(new Runnable() | 
|             { | 
|                 @Override | 
|                 public void run() | 
|                 { | 
|                     Looper.prepare(); | 
|                     Toast.makeText(m_Context, "程序出现异常,即将重启", Toast.LENGTH_LONG).show(); | 
|                     Looper.loop(); | 
|                 } | 
|             }).start(); | 
|   | 
|             recordDeviceInfo(); | 
|   | 
|             save(throwable); | 
|   | 
|             SystemClock.sleep(3000); | 
|   | 
|         } catch (Exception e) | 
|         { | 
|             e.printStackTrace(); | 
|         } | 
|         return true; | 
|     } | 
|   | 
|     private String save(Throwable throwable) throws Exception | 
|     { | 
|         StringBuffer sb = new StringBuffer(); | 
|         try | 
|         { | 
|             SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | 
|             String date = sDateFormat.format(new Date()); | 
|             sb.append("\r\n" + date + "\n"); | 
|             for (Map.Entry<String, String> entry : m_DevicceInfo.entrySet()) | 
|             { | 
|                 String key = entry.getKey(); | 
|                 String value = entry.getValue(); | 
|                 sb.append(key + "=" + value + "\n"); | 
|             } | 
|   | 
|             Writer writer = new StringWriter(); | 
|             PrintWriter printWriter = new PrintWriter(writer); | 
|             throwable.printStackTrace(printWriter); | 
|             Throwable cause = throwable.getCause(); | 
|             while (cause != null) | 
|             { | 
|                 cause.printStackTrace(printWriter); | 
|                 cause = cause.getCause(); | 
|             } | 
|             printWriter.flush(); | 
|             printWriter.close(); | 
|             String result = writer.toString(); | 
|             sb.append(result); | 
|   | 
|             String fileName = writeFile(sb.toString()); | 
|             return fileName; | 
|         } catch (Exception e) | 
|         { | 
|             sb.append("写入崩溃日志时, 出现了异常状况...\r\n"); | 
|             writeFile(sb.toString()); | 
|         } | 
|         return null; | 
|   | 
|     } | 
|   | 
|     private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); | 
|   | 
|     private String writeFile(String sb) throws Exception | 
|     { | 
|         String time = formatter.format(new Date()); | 
|         String fileName = "crash-" + time + ".log"; | 
|         String path = getPath(); | 
|         File dir = new File(getPath()); | 
|         if (!dir.exists()) | 
|         { | 
|             dir.mkdirs(); | 
|         } | 
|         FileOutputStream fos = new FileOutputStream(path + fileName, true); | 
|         fos.write(sb.getBytes()); | 
|         fos.flush(); | 
|         fos.close(); | 
|         return fileName; | 
|     } | 
|   | 
|     private String getPath() | 
|     { | 
|         return m_Context.getExternalFilesDir("").getAbsolutePath() | 
|                 + File.separator | 
|                 + "crash" | 
|                 + File.separator; | 
|     } | 
|   | 
|     /** | 
|      * 文件删除 | 
|      * | 
|      * @param autoClearDay 文件保存天数 | 
|      */ | 
|     public void autoClear(final int autoClearDay) | 
|     { | 
|         delete(getPath(), new FilenameFilter() | 
|         { | 
|             @Override | 
|             public boolean accept(File file, String filename) | 
|             { | 
|                 String s = FileUtil.getFileNameWithoutExtension(filename); | 
|                 int day = autoClearDay < 0 ? autoClearDay : -1 * autoClearDay; | 
|                 String date = "crash-" + getOtherDay(day); | 
|                 return date.compareTo(s) >= 0; | 
|             } | 
|         }); | 
|     } | 
|   | 
|     private void delete(String path, FilenameFilter filter) | 
|     { | 
|         File _file = new File(path); | 
|         if (!_file.exists()) | 
|         { | 
|             return; | 
|         } | 
|         File[] _files = _file.listFiles(filter); | 
|         for (int i = _files.length - 1; i >= 0; i--) | 
|         { | 
|             _files[i].delete(); | 
|         } | 
|     } | 
|   | 
|     private String getOtherDay(int offset) | 
|     { | 
|         Calendar _calendar = Calendar.getInstance(); | 
|         _calendar.add(Calendar.DATE, offset); | 
|         return formatter.format(_calendar.getTime()); | 
|     } | 
| } |