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