基于开源项目acra实现的定制化Android crash上报库及后台系统

来源:互联网 发布:windows 网络监控工具 编辑:程序博客网 时间:2024/06/10 04:29
出发点:
开源的acra crash上报库(
http://code.google.com/p/acra/
)的缺点有: 1. crash上报到google doc里的话,由于被墙了,所以看不到数据。 2 如果基于邮件上报crash的话,不方便统计crash崩溃率。3. acra上报的字段过多,需要过滤一些没用的字段。

目的:
当Android应用程序崩溃时,可以及时通过浏览器查看到崩溃的堆栈信息,同时后台还可以统计每天的崩溃比率,以方便应用程序的体验改进

实践过程:

1. 首先下载acra的源码svn checkout http://acra.googlecode.com/svn/trunk, 在eclipse中导入该项目,在ACRA.java中发现默认上报的字段内容有:
  1. public static final ReportField[] DEFAULT_REPORT_FIELDS = { REPORT_ID, APP_VERSION_CODE, APP_VERSION_NAME,
  2. PACKAGE_NAME, FILE_PATH, PHONE_MODEL, BRAND, PRODUCT, ANDROID_VERSION, BUILD, TOTAL_MEM_SIZE,
  3. AVAILABLE_MEM_SIZE, CUSTOM_DATA, IS_SILENT, STACK_TRACE, INITIAL_CONFIGURATION, CRASH_CONFIGURATION,
  4. DISPLAY, USER_COMMENT, USER_EMAIL, USER_APP_START_DATE, USER_CRASH_DATE, DUMPSYS_MEMINFO, LOGCAT,
  5. DEVICE_ID, INSTALLATION_ID, DEVICE_FEATURES, ENVIRONMENT, SHARED_PREFERENCES, SETTINGS_SYSTEM,
  6. SETTINGS_SECURE };
复制代码
2.过滤一些无用的字段,当Android应用崩溃后,需要统计的数据只有11个,如下所示:

字段 说明

字段
说明
platform_id
1 =aPad,2=aPhone
android_version
Android版本号
app_version_code
应用的版本代码 如 9
app_version_name
应用的版本名称 如 1.2.2
device_id
设备的唯一id
model
手机/平板的模型,如BCM63
brand
Android设备牌子,如三星
product
Android产品信息
stack_trace
崩溃的堆栈信息
crash_date
崩溃的时间点
package_name
应用的包名

Firgure 1 上报字段

在ACRA.java中的addReportSenders函数中增加Figure1中上报字段的映射:
  1. if (conf.formUri() != null && !"".equals(conf.formUri())) {

  2. Map<ReportField, String> mapField = new HashMap<ReportField,String>();
  3. mapField.put(ReportField.ANDROID_VERSION, "android_version");
  4. mapField.put(ReportField.APP_VERSION_CODE, "app_version_code");
  5. mapField.put(ReportField.APP_VERSION_NAME, "app_version_name");
  6. mapField.put(ReportField.DEVICE_ID, "device_id");
  7. mapField.put(ReportField.PHONE_MODEL, "model");
  8. mapField.put(ReportField.BRAND, "brand");
  9. mapField.put(ReportField.PRODUCT, "product");
  10. mapField.put(ReportField.STACK_TRACE, "stack_trace");
  11. mapField.put(ReportField.USER_CRASH_DATE, "crash_date");
  12. mapField.put(ReportField.PACKAGE_NAME, "package_name");
  13. errorReporter.addReportSender(new HttpPostSender(conf.formUri(), mapField));
  14. return;
  15. }
复制代码
在HttpPostSender.java中的remap函数中修改如下:
  1. for (ReportField field : fields) {
  2. /* if (mMapping == null || mMapping.get(field) == null) {
  3. finalReport.put(field.toString(), report.get(field));
  4. } else {
  5. finalReport.put(mMapping.get(field), report.get(field));
  6. }*/
  7. if(mMapping!=null && mMapping.get(field) != null){

  8. finalReport.put(mMapping.get(field), report.get(field));
  9. }

  10. }
复制代码
finalReport.put("platform_id", ACRA.getConfig().platformId());


3. 修改完后,只需要在应用程序中增加如下几行代码,就可以实时的上报崩溃的堆栈信息(这点比ios平台方便)
  1. @ReportsCrashes(formKey = "", // will not be used
  2. platformId="1",
  3. formUriBasicAuthLogin = "user",
  4. formUriBasicAuthPassword = "password",
  5. formUri = "http://weiwangzi.com:8080/CrashReport/CrashServerlet")
  6. public class TestApplication extends Application {

  7. @Override
  8. public void onCreate() {
  9. // TODO Auto-generated method stub
  10. super.onCreate();
  11. ACRA.init(this);
  12. }
复制代码
4. 实现serverlet来统计上报的crash数据到数据库中
  1. public void doPost(HttpServletRequest request, HttpServletResponse response)
  2. throws ServletException, IOException {

  3. Connection conn = null;
  4. PreparedStatement pstmt = null;
  5. try{
  6. conn = DBUtil.getConnection();
  7. String platformId=request.getParameter("platform_id");
  8. String androidVersion=request.getParameter("android_version");
  9. String appVersionCode=request.getParameter("app_version_code");
  10. String appVersionName=request.getParameter("app_version_name");
  11. String deviceId=request.getParameter("device_id");
  12. String model=request.getParameter("model");
  13. String brand=request.getParameter("brand");
  14. String product=request.getParameter("product");
  15. String stackTrace=request.getParameter("stack_trace");
  16. String crashDate=request.getParameter("crash_date");
  17. String packageName=request.getParameter("package_name");
  18. pstmt = conn.prepareStatement("insert into report(platform_id, android_version, app_version_code,appversion_name,device_id,model,brand,product,stack_trace,crash_date,package_name) values (?, ?, ?,?,?,?,?,?,?,?,?)");
  19. pstmt.setString(1, platformId);
  20. pstmt.setString(2, androidVersion);
  21. pstmt.setString(3, appVersionCode);
  22. pstmt.setString(4, appVersionName);
  23. pstmt.setString(5, deviceId);
  24. pstmt.setString(6, model);
  25. pstmt.setString(7, brand);
  26. pstmt.setString(8, product);
  27. pstmt.setString(9, stackTrace);
  28. pstmt.setString(10, crashDate);
  29. pstmt.setString(11, packageName);
  30. pstmt.executeUpdate();


  31. }catch(Exception e){
  32. e.printStackTrace();

  33. }finally{
  34. if(pstmt!=null){
  35. try {
  36. pstmt.close();
  37. } catch (SQLException e) {
  38. // TODO Auto-generated catch block
  39. //e.printStackTrace();
  40. }
  41. }
  42. if(conn!=null){
  43. try {
  44. conn.close();
  45. } catch (SQLException e) {
  46. // TODO Auto-generated catch block
  47. //e.printStackTrace();
  48. }
  49. }
  50. }


  51. }
复制代码

实践结果:通过数据库可以导出一个excel的crash报表,或者直接通过浏览器查看