在应用发布以后,由于安卓机型的千差万别 ,可能会出现各种各样的问题,这时候如果我们可以将这些信息收集起来,并进行修改就很不错了。下面就来讨论一下怎么处理程序崩溃以后,错误信息的手机。
Java中已经提供了一个接口Thread.UncaughtExceptionHandler来对运行时的异常进行处理。只需要实现这个接口,并覆写 public void uncaughtException(Thread thread, Throwable ex) 方法即可。
由于Application是Android应用启动的第一个入口,所以我们实现自己的Application,让他去实现Thread.UncaughtExceptionHandler接口。使用的时候有一下几个注意事项
1. 需要在manifest文件中的application节点,添加你自己实现的Application类,例如
<application android:name=".CrashApplication" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" >
2.在实现的Application类的onCreate方法中,设置本类为默认的异常处理器,添加如下代码:
Thread.setDefaultUncaughtExceptionHandler(this);
3.在 uncaughtException(Thread thread, Throwable ex) 方法中添加实现。
示例代码如下,实现了收集发生异常的手机设备信息和异常信息,并将这些信息保存至本地
public class CrashApplication extends Application implements UncaughtExceptionHandler { // 单例模式 private static CrashApplication INSTANCE; private Context mContext; // 用来存储设备信息和异常信息 private Map<String, String> info = new HashMap<String, String>(); // 用于格式化日期,作为日志文件名的一部分 private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); public CrashApplication() { } public static CrashApplication getInstance() { if (INSTANCE == null) { INSTANCE = new CrashApplication(); } return INSTANCE; } @Override public void onCreate() { super.onCreate(); mContext = this; // 设置该CrashHandler为程序的默认处理器 Thread.setDefaultUncaughtExceptionHandler(this); } public void uncaughtException(Thread thread, Throwable ex) { // TODO,在这里你可以处理当 程序崩溃时你想做的事情 // 收集设备参数信息 collectDeviceInfo(mContext); // 保存日志文件 saveCrashInfo2File(ex); } /** * 收集设备参数信息 * */ public void collectDeviceInfo(Context context) { try { PackageManager pm = context.getPackageManager();// 获得包管理器 PackageInfo pi = pm.getPackageInfo(context.getPackageName(), PackageManager.GET_ACTIVITIES);// 得到该应用的信息,即主Activity if (pi != null) { String versionName = pi.versionName == null ? "null" : pi.versionName; String versionCode = pi.versionCode + ""; info.put("versionName", versionName); info.put("versionCode", versionCode); } } catch (NameNotFoundException e) { e.printStackTrace(); } Field[] fields = Build.class.getDeclaredFields();// 反射机制 for (Field field : fields) { try { field.setAccessible(true); info.put(field.getName(), field.get("").toString()); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } } /** * 将异常信息保存至SD卡crash目录 */ private String saveCrashInfo2File(Throwable ex) { StringBuffer sb = new StringBuffer(); for (Map.Entry<String, String> entry : info.entrySet()) { String key = entry.getKey(); String value = entry.getValue(); sb.append(key + "=" + value + " "); } Writer writer = new StringWriter(); PrintWriter pw = new PrintWriter(writer); ex.printStackTrace(pw); Throwable cause = ex.getCause(); // 循环着把所有的异常信息写入writer中 while (cause != null) { cause.printStackTrace(pw); cause = cause.getCause(); } pw.close();// 记得关闭 String result = writer.toString(); sb.append(result); // 保存文件 long timetamp = System.currentTimeMillis(); String time = format.format(new Date()); String fileName = "crash-" + time + "-" + timetamp + ".log"; if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { try { File dir = new File(Environment.getExternalStorageDirectory(), "crash"); if (!dir.exists()) dir.mkdir(); File file = new File(dir, fileName); FileOutputStream fos = new FileOutputStream(file); fos.write(sb.toString().getBytes()); fos.close(); return fileName; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } return null; } }