Android 崩溃日志 本地存储 与 远程保存

来源:互联网 发布:聚合数据气费接口收费 编辑:程序博客网 时间:2024/06/01 09:06

示例代码下载 :http://download.csdn.net/detail/linder_qzy/9543246



一. 崩溃日志本地存储



1. 保存原理解析


崩溃信息本地保存步骤 : 

-- 1. 自定义类实现 UncaughtExceptionHandler : public class CrashHandler implements UncaughtExceptionHandler;

-- 2. 设置该自定义的 CrashHandler 类为单例模式 : 

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. // 单例模式  
  2. private static CrashHandler INSTANCE = new CrashHandler();  
  3. private CrashHandler() {  
  4. }  
  5. public static CrashHandler getInstance() {  
  6.     return INSTANCE;  
  7. }  
-- 重写 uncaughtException 方法 : 

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @Override  
  2. public void uncaughtException(Thread thread, Throwable ex)  
-- 自定义 handleException 方法处理异常信息 : 在该方法中进行设备信息收集, 以及将信息保存到文件中;


(1) UncaughtExceptionHandler 类解析


UncaughtExceptionHandler 作用 : 该类处理以下情况, 如果有未捕获的异常发生, 出现了程序崩溃闪退的情况, 此时会回调该类的 uncaughtException 方法;


(2) 线程相关


线程相关 : 每个线程都对应有响应的默认的未捕获异常处理器;

-- 获取线程默认的未捕获异常处理器 : Thread.getDefaultUncaughtExceptionHandler();

-- 设置线程默认的未捕获异常处理器 : Thread.setDefaultUncaughtExceptionHandler(this);


(3) uncaughtException 方法


uncaughtException 方法解析 : 

-- 回调时机 : 出现未定义的异常时;

-- 回调参数 : 回调时会传入 线程对象 和 要抛出的异常信息, 我们可以在程序中拿到这两个信息;

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public void uncaughtException(Thread thread, Throwable ex)  


(4) 手机设备信息


手机设备信息手机步骤 : 

-- 1. 获取包信息 : 

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //获取包管理器  
  2. PackageManager pm = ctx.getPackageManager();  
  3. //获取包信息  
  4. PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(),  
  5.         PackageManager.GET_ACTIVITIES);  
-- 2. 获取版本号信息 : 

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. if (pi != null) {  
  2.     //版本号  
  3.     String versionName = pi.versionName == null ? "null"  
  4.             : pi.versionName;  
  5.     //版本代码  
  6.     String versionCode = pi.versionCode + "";  
  7.     //将版本信息存放到 成员变量 Map<String, String> mInfos 中  
  8.     this.mInfos.put("versionName", versionName);  
  9.     this.mInfos.put("versionCode", versionCode);  
  10. }  

-- 3. 使用反射获取 Build 类成员变量变量 , 并遍历获取这些变量内容

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //获取 Build 中定义的变量, 使用反射方式获取, 该类中定义了设备相关的变量信息  
  2. Field[] fields = Build.class.getDeclaredFields();  
  3. //遍历获取额变量, 将这些信息存放到成员变量 Map<String, String> mInfos 中  
  4. for (Field field : fields) {  
  5.     try {  
  6.         //设置 Build 成员变量可访问  
  7.         field.setAccessible(true);  
  8.         //将 设备相关的信息存放到 mInfos 成员变量中  
  9.         mInfos.put(field.getName(), field.get(null).toString());  
  10.         Log.d(TAG, field.getName() + " : " + field.get(null));  
  11.     } catch (Exception e) {  
  12.         Log.e(TAG, "an error occured when collect crash info", e);  
  13.     }  
  14. }  


(4) 保存崩溃信息到文件


保存文件步骤 : 这些步骤就很简单了, 使用 IO流即可;

-- 1. 将之前获取的 Build 设备信息, 版本信息, 崩溃信息转为字符串 : 

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //存储相关的字符串信息  
  2. StringBuffer sb = new StringBuffer();  
  3. //将成员变量 Map<String, String> mInfos  中的数据 存储到 StringBuffer sb 中  
  4. for (Map.Entry<String, String> entry : this.mInfos.entrySet()) {  
  5.     String key = entry.getKey();  
  6.     String value = entry.getValue();  
  7.     sb.append(key + "=" + value + "\n");  
  8. }  
-- 2. 在 Logcat 中打印崩溃信息 : 之前的默认操作就是打印崩溃信息到 Logcat 中, 我们在这里继续执行完这个步骤, 否则Logcat 中没有数据的;

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //将 StringBuffer sb 中的字符串写出到文件中  
  2. Writer writer = new StringWriter();  
  3. PrintWriter printWriter = new PrintWriter(writer);  
  4. ex.printStackTrace(printWriter);  
  5. Throwable cause = ex.getCause();  
  6. while (cause != null) {  
  7.     cause.printStackTrace(printWriter);  
  8.     cause = cause.getCause();  
  9. }  
  10. printWriter.close();  
-- 3. 写出数据到文件中 : IO 流知识点, 不再做过多赘述;

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. String result = writer.toString();  
  2. sb.append(result);  
  3. try {  
  4.     long timestamp = System.currentTimeMillis();  
  5.     String time = formatter.format(new Date());  
  6.     String fileName = "crash-" + time + "-" + timestamp + ".txt";  
  7.     if (Environment.getExternalStorageState().equals(  
  8.             Environment.MEDIA_MOUNTED)) {  
  9.         //获取文件输出路径  
  10.         String path = Environment.getExternalStorageDirectory()  
  11.                 + "/crashinfo/";  
  12.         //创建文件夹和文件  
  13.         File dir = new File(path);  
  14.         if (!dir.exists()) {  
  15.             dir.mkdirs();  
  16.         }  
  17.         //创建输出流  
  18.         FileOutputStream fos = new FileOutputStream(path + fileName);  
  19.         //向文件中写出数据  
  20.         fos.write(sb.toString().getBytes());  
  21.         fos.close();  
  22.     }  
  23.     return fileName;  
  24. catch (Exception e) {  
  25.     Log.e(TAG, "an error occured while writing file...", e);  
  26. }  



2. 代码及示例



(1) 相关代码示例


故意发生错误的代码 : 

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public class MainActivity extends Activity {  
  2.   
  3.     @Override  
  4.     protected void onCreate(Bundle savedInstanceState) {  
  5.         super.onCreate(savedInstanceState);  
  6.         setContentView(R.layout.activity_main);  
  7.           
  8.     }  
  9.       
  10.     public void onClick(View view) {  
  11.         int i = 3;  
  12.         i = i / 0;  
  13.     }  
  14.   
  15. }  


CrashHandler 注册代码 : 在 Activity 或者 Application 中注册该代码;

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. CrashHandler.getInstance().init(getApplicationContext());  


CrashHandler 代码 : 

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package cn.org.octpus.crash;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileOutputStream;  
  5. import java.io.PrintWriter;  
  6. import java.io.StringWriter;  
  7. import java.io.Writer;  
  8. import java.lang.Thread.UncaughtExceptionHandler;  
  9. import java.lang.reflect.Field;  
  10. import java.text.DateFormat;  
  11. import java.text.SimpleDateFormat;  
  12. import java.util.Date;  
  13. import java.util.HashMap;  
  14. import java.util.Map;  
  15.   
  16. import android.content.Context;  
  17. import android.content.pm.PackageInfo;  
  18. import android.content.pm.PackageManager;  
  19. import android.content.pm.PackageManager.NameNotFoundException;  
  20. import android.os.Build;  
  21. import android.os.Environment;  
  22. import android.os.Looper;  
  23. import android.util.Log;  
  24. import android.widget.Toast;  
  25.   
  26. /** 
  27.  * UncaughtExceptionHanlder 作用 : 处理 线程被未捕获的异常终止 的情况, 一旦出现了未捕获异常崩溃, 系统就会回调该类的 
  28.  * uncaughtException 方法; 
  29.  */  
  30. public class CrashHandler implements UncaughtExceptionHandler {  
  31.     // 用于打印日志的 TAG 标识符  
  32.     public static final String TAG = "octopus.CrashHandler";  
  33.   
  34.     // 系统默认的UncaughtException处理类  
  35.     private Thread.UncaughtExceptionHandler mDefaultHandler;  
  36.     // 程序的Context对象  
  37.     private Context mContext;  
  38.     // 用来存储设备信息和异常信息  
  39.     private Map<String, String> mInfos = new HashMap<String, String>();  
  40.     // 用于格式化日期,作为日志文件名的一部分  
  41.     private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");  
  42.   
  43.     // 单例模式  
  44.     private static CrashHandler INSTANCE = new CrashHandler();  
  45.     private CrashHandler() {  
  46.     }  
  47.     public static CrashHandler getInstance() {  
  48.         return INSTANCE;  
  49.     }  
  50.   
  51.     /** 
  52.      * 初始化该类, 向系统中注册 
  53.      * @param context 
  54.      */  
  55.     public void init(Context context) {  
  56.         mContext = context;  
  57.         // 获取系统默认的 UncaughtException 处理器  
  58.         mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();  
  59.         // 设置该 CrashHandler 为程序的默认处理器  
  60.         Thread.setDefaultUncaughtExceptionHandler(this);  
  61.     }  
  62.   
  63.     /* 
  64.      * 出现未捕获的异常时, 会自动回调该方法 
  65.      * (non-Javadoc) 
  66.      * @see java.lang.Thread.UncaughtExceptionHandler#uncaughtException(java.lang.Thread, java.lang.Throwable) 
  67.      */  
  68.     @Override  
  69.     public void uncaughtException(Thread thread, Throwable ex) {  
  70.         /* 
  71.          * 调用 handleException() 方法处理该线程 
  72.          * 如果返回 true 说明处理成功, 如果返回 false 则调用默认的异常处理器来处理 
  73.          * 一般情况下该方法都会成功处理 
  74.          */  
  75.         if (!handleException(ex) && mDefaultHandler != null) {  
  76.             // 如果用户没有处理则让系统默认的异常处理器来处理  
  77.             mDefaultHandler.uncaughtException(thread, ex);  
  78.         } else {  
  79.             try {  
  80.                 Thread.sleep(3000);  
  81.             } catch (InterruptedException e) {  
  82.                 Log.e(TAG, "error : ", e);  
  83.             }  
  84.             // 退出程序  
  85.             android.os.Process.killProcess(android.os.Process.myPid());  
  86.             System.exit(1);  
  87.         }  
  88.     }  
  89.   
  90.     /** 
  91.      * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成. 
  92.      * @param ex     
  93.      *      异常信息 
  94.      * @return  
  95.      *      true:如果处理了该异常信息;否则返回false. 
  96.      */  
  97.     private boolean handleException(Throwable ex) {  
  98.         if (ex == null) {  
  99.             return false;  
  100.         }  
  101.         /* 
  102.          * 使用Toast来显示异常信息,  
  103.          * 由于在主线程会阻塞,  
  104.          * 不能实时出现 Toast 信息,  
  105.          * 这里我们在子线程中处理 Toast 信息 
  106.          */  
  107.         new Thread() {  
  108.             @Override  
  109.             public void run() {  
  110.                 Looper.prepare();  
  111.                 Toast.makeText(mContext, "很抱歉,程序出现异常,即将退出.", Toast.LENGTH_LONG)  
  112.                         .show();  
  113.                 Looper.loop();  
  114.             }  
  115.         }.start();  
  116.         // 收集设备参数信息  
  117.         collectDeviceInfo(mContext);  
  118.         // 保存日志文件  
  119.         saveCrashInfo2File(ex);  
  120.         return true;  
  121.     }  
  122.   
  123.     /** 
  124.      * 收集设备参数信息, 将手机到的信息存储到 
  125.      * @param ctx 
  126.      *      上下文对象 
  127.      */  
  128.     public void collectDeviceInfo(Context ctx) {  
  129.         try {  
  130.             //获取包管理器  
  131.             PackageManager pm = ctx.getPackageManager();  
  132.             //获取包信息  
  133.             PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(),  
  134.                     PackageManager.GET_ACTIVITIES);  
  135.             if (pi != null) {  
  136.                 //版本号  
  137.                 String versionName = pi.versionName == null ? "null"  
  138.                         : pi.versionName;  
  139.                 //版本代码  
  140.                 String versionCode = pi.versionCode + "";  
  141.                 //将版本信息存放到 成员变量 Map<String, String> mInfos 中  
  142.                 this.mInfos.put("versionName", versionName);  
  143.                 this.mInfos.put("versionCode", versionCode);  
  144.             }  
  145.         } catch (NameNotFoundException e) {  
  146.             Log.e(TAG, "an error occured when collect package info", e);  
  147.         }  
  148.           
  149.         //获取 Build 中定义的变量, 使用反射方式获取, 该类中定义了设备相关的变量信息  
  150.         Field[] fields = Build.class.getDeclaredFields();  
  151.         //遍历获取额变量, 将这些信息存放到成员变量 Map<String, String> mInfos 中  
  152.         for (Field field : fields) {  
  153.             try {  
  154.                 //设置 Build 成员变量可访问  
  155.                 field.setAccessible(true);  
  156.                 //将 设备相关的信息存放到 mInfos 成员变量中  
  157.                 mInfos.put(field.getName(), field.get(null).toString());  
  158.                 Log.d(TAG, field.getName() + " : " + field.get(null));  
  159.             } catch (Exception e) {  
  160.                 Log.e(TAG, "an error occured when collect crash info", e);  
  161.             }  
  162.         }  
  163.     }  
  164.   
  165.     /** 
  166.      * 保存错误信息到文件中 
  167.      * @param ex 
  168.      * @return 返回文件名称,便于将文件传送到服务器 
  169.      */  
  170.     private String saveCrashInfo2File(Throwable ex) {  
  171.         //存储相关的字符串信息  
  172.         StringBuffer sb = new StringBuffer();  
  173.         //将成员变量 Map<String, String> mInfos  中的数据 存储到 StringBuffer sb 中  
  174.         for (Map.Entry<String, String> entry : this.mInfos.entrySet()) {  
  175.             String key = entry.getKey();  
  176.             String value = entry.getValue();  
  177.             sb.append(key + "=" + value + "\n");  
  178.         }  
  179.   
  180.         //将 StringBuffer sb 中的字符串写出到文件中  
  181.         Writer writer = new StringWriter();  
  182.         PrintWriter printWriter = new PrintWriter(writer);  
  183.         ex.printStackTrace(printWriter);  
  184.         Throwable cause = ex.getCause();  
  185.         while (cause != null) {  
  186.             cause.printStackTrace(printWriter);  
  187.             cause = cause.getCause();  
  188.         }  
  189.         printWriter.close();  
  190.         String result = writer.toString();  
  191.         sb.append(result);  
  192.         try {  
  193.             long timestamp = System.currentTimeMillis();  
  194.             String time = formatter.format(new Date());  
  195.             String fileName = "crash-" + time + "-" + timestamp + ".txt";  
  196.             if (Environment.getExternalStorageState().equals(  
  197.                     Environment.MEDIA_MOUNTED)) {  
  198.                 //获取文件输出路径  
  199.                 String path = Environment.getExternalStorageDirectory()  
  200.                         + "/crashinfo/";  
  201.                 //创建文件夹和文件  
  202.                 File dir = new File(path);  
  203.                 if (!dir.exists()) {  
  204.                     dir.mkdirs();  
  205.                 }  
  206.                 //创建输出流  
  207.                 FileOutputStream fos = new FileOutputStream(path + fileName);  
  208.                 //向文件中写出数据  
  209.                 fos.write(sb.toString().getBytes());  
  210.                 fos.close();  
  211.             }  
  212.             return fileName;  
  213.         } catch (Exception e) {  
  214.             Log.e(TAG, "an error occured while writing file...", e);  
  215.         }  
  216.         return null;  
  217.     }  
  218. }  


(2) 结果示例



崩溃日志存放文件路径 : /storage/sdcard0/crashinfo/crash-2015-04-27-19-31-41-1430134301642.txt;

-- 说明 : 其中 /storage/sdcard0/ 是系统默认的 SD 卡路径, crashinfo/crash-2015-04-27-19-31-41-1430134301642.txt 是我们创建的文件;


崩溃日志内容 : 

[plain] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. 1430134301642.txt                                                             <  
  2. HARDWARE=pxa1088  
  3. RADIO=unknown  
  4. versionCode=1  
  5. HOST=SWDA2601  
  6. TAGS=release-keys  
  7. ID=JDQ39  
  8. MANUFACTURER=samsung  
  9. TYPE=user  
  10. IS_TRANSLATION_ASSISTANT_ENABLED=false  
  11. IS_SECURE=false  
  12. TIME=1416298944000  
  13. FINGERPRINT=samsung/wilcoxdszn/wilcoxds:4.2.2/JDQ39/G3812ZNUANK1:user/release-keys  
  14. UNKNOWN=unknown  
  15. BOARD=PXA1088  
  16. PRODUCT=wilcoxdszn  
  17. versionName=1.0  
  18. DISPLAY=JDQ39.G3812ZNUANK1  
  19. USER=se.infra  
  20. DEVICE=wilcoxds  
  21. MODEL=SM-G3812  
  22. BOOTLOADER=unknown  
  23. CPU_ABI=armeabi-v7a  
  24. CPU_ABI2=armeabi  
  25. IS_SYSTEM_SECURE=false  
  26. IS_DEBUGGABLE=false  
  27. SERIAL=5202889565301100  
  28. BRAND=samsung  
  29. java.lang.IllegalStateException: Could not execute method of the activity  
  30.     at android.view.View$1.onClick(View.java:3804)  
  31.     at android.view.View.performClick(View.java:4439)  
  32.     at android.widget.Button.performClick(Button.java:142)  
  33.     at android.view.View$PerformClick.run(View.java:18395)  
  34.     at android.os.Handler.handleCallback(Handler.java:725)  
  35.     at android.os.Handler.dispatchMessage(Handler.java:92)  
  36.     at android.os.Looper.loop(Looper.java:176)  
  37.     at android.app.ActivityThread.main(ActivityThread.java:5319)  
  38.     at java.lang.reflect.Method.invokeNative(Native Method)  
  39.     at java.lang.reflect.Method.invoke(Method.java:511)  
  40.     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)  
  41.     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)  
  42.     at dalvik.system.NativeStart.main(Native Method)  
  43. Caused by: java.lang.reflect.InvocationTargetException  
  44.     at java.lang.reflect.Method.invokeNative(Native Method)  
  45.     at java.lang.reflect.Method.invoke(Method.java:511)  
  46.     at android.view.View$1.onClick(View.java:3799)  
  47.     ... 12 more  
  48. Caused by: java.lang.ArithmeticException: divide by zero  
  49.     at cn.org.octpus.crash.MainActivity.onClick(MainActivity.java:20)  
  50.     ... 15 more  
  51. java.lang.reflect.InvocationTargetException  
  52.     at java.lang.reflect.Method.invokeNative(Native Method)  
  53.     at java.lang.reflect.Method.invoke(Method.java:511)  
  54.     at android.view.View$1.onClick(View.java:3799)  
  55.     at android.view.View.performClick(View.java:4439)  
  56.     at android.widget.Button.performClick(Button.java:142)  
  57.     at android.view.View$PerformClick.run(View.java:18395)  
  58.     at android.os.Handler.handleCallback(Handler.java:725)  
  59.     at android.os.Handler.dispatchMessage(Handler.java:92)  
  60.     at android.os.Looper.loop(Looper.java:176)  
  61.     at android.app.ActivityThread.main(ActivityThread.java:5319)  
  62.     at java.lang.reflect.Method.invokeNative(Native Method)  
  63.     at java.lang.reflect.Method.invoke(Method.java:511)  
  64.     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)  
  65.     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)  
  66.     at dalvik.system.NativeStart.main(Native Method)  
  67. Caused by: java.lang.ArithmeticException: divide by zero  
  68.     at cn.org.octpus.crash.MainActivity.onClick(MainActivity.java:20)  
  69.     ... 15 more  
  70. java.lang.ArithmeticException: divide by zero  
  71.     at cn.org.octpus.crash.MainActivity.onClick(MainActivity.java:20)  
  72.     at java.lang.reflect.Method.invokeNative(Native Method)  
  73.     at java.lang.reflect.Method.invoke(Method.java:511)  
  74.     at android.view.View$1.onClick(View.java:3799)  
  75.     at android.view.View.performClick(View.java:4439)  
  76.     at android.widget.Button.performClick(Button.java:142)  
  77.     at android.view.View$PerformClick.run(View.java:18395)  
  78.     at android.os.Handler.handleCallback(Handler.java:725)  
  79.     at android.os.Handler.dispatchMessage(Handler.java:92)  
  80.     at android.os.Looper.loop(Looper.java:176)  
  81.     at android.app.ActivityThread.main(ActivityThread.java:5319)  
  82.     at java.lang.reflect.Method.invokeNative(Native Method)  
  83.     at java.lang.reflect.Method.invoke(Method.java:511)  
  84.     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)  
  85.     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)  
  86.     at dalvik.system.NativeStart.main(Native Method)  




二. 崩溃日志保存到远程服务器



实现途径 

-- 1. 自己开发服务器端 : 在上面的保存文件的基础上, 在开发一个服务器端, 使用网络编程接口将打印到文件的内容上传到服务器端;

-- 2. 使用第三方服务 : 使用 Testin 的崩溃大师, 地址 http://crash.testin.cn/app?scnavbar ;


1. 集成崩溃大师步骤



(1) 创建应用 获取 key 值


创建应用步骤 : 

-- 1. 创建界面 : http://crash.testin.cn/apm/task/create ;

-- 2. 填写一个应用信息 : 


-- 3. 获取 key : 点击"提交并获取 Appkey" 按钮, 获取到了 AppKey "0da6263ca1f5b84a2dd405b07227f483";



(2) 设置类型


第二步设置类型, 选择默认的应用即可 



(3) 下载 jar 包


jar 包简介 : 集成崩溃大师, 只需要集成一个 jar 包即可, 点击如下按钮即可下载 该 jar 包;

-- jar 包内容 : 下载后解压, jar 包名称是 testinagent.jar ;



(4) 导入 SDK 


导入 SDK : 在应用下 创建一个 libs 目录, 将jar 包拷贝进去即可;




(5) 配置 AndroidManifest.xml 文件 


在配置文件中添加如下用户权限即可 : 

[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />  
  2. <uses-permission android:name="android.permission.INTERNET" />  
  3. <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />  
  4. <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />  
  5. <uses-permission android:name="android.permission.READ_PHONE_STATE" />  
  6. <uses-permission android:name="android.permission.READ_LOGS" />  
  7. <uses-permission android:name="android.permission.GET_TASKS" />  


(6) 初始化设置


在代码中注册 : 

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //初始化 Testin 崩溃大师  
  2. TestinAgent.init(getApplicationContext(), "0da6263ca1f5b84a2dd405b07227f483""octopus");  




2. 测试示例



(1) 日志信息


测试成功会打印如下信息 : 

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. 04-27 20:11:40.890: E/TestinAgent(16432): ****************************************  
  2. 04-27 20:11:40.890: E/TestinAgent(16432): A Java crash caught by TestinAgent, pkg=cn.org.octpus.crash   
  3. 04-27 20:11:40.890: E/TestinAgent(16432): ----------------------------------------  
  4. 04-27 20:11:40.890: E/TestinAgent(16432): reason: java.lang.IllegalStateException: Could not execute method of the activity   
  5. 04-27 20:11:40.890: E/TestinAgent(16432): ----------------------------------------  
  6. 04-27 20:11:40.890: E/TestinAgent(16432): stacktrace:   
  7. 04-27 20:11:40.890: E/TestinAgent(16432):   at android.view.View$1.onClick(View.java:3804)  
  8. 04-27 20:11:40.890: E/TestinAgent(16432):   at android.view.View.performClick(View.java:4439)  
  9. 04-27 20:11:40.890: E/TestinAgent(16432):   at android.widget.Button.performClick(Button.java:142)  
  10. 04-27 20:11:40.890: E/TestinAgent(16432):   at android.view.View$PerformClick.run(View.java:18395)  
  11. 04-27 20:11:40.890: E/TestinAgent(16432):   at android.os.Handler.handleCallback(Handler.java:725)  
  12. 04-27 20:11:40.890: E/TestinAgent(16432):   at android.os.Handler.dispatchMessage(Handler.java:92)  
  13. 04-27 20:11:40.890: E/TestinAgent(16432):   at android.os.Looper.loop(Looper.java:176)  
  14. 04-27 20:11:40.890: E/TestinAgent(16432):   at android.app.ActivityThread.main(ActivityThread.java:5319)  
  15. 04-27 20:11:40.890: E/TestinAgent(16432):   at java.lang.reflect.Method.invokeNative(Native Method)  
  16. 04-27 20:11:40.890: E/TestinAgent(16432):   at java.lang.reflect.Method.invoke(Method.java:511)  
  17. 04-27 20:11:40.890: E/TestinAgent(16432):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)  
  18. 04-27 20:11:40.890: E/TestinAgent(16432):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)  
  19. 04-27 20:11:40.890: E/TestinAgent(16432):   at dalvik.system.NativeStart.main(Native Method)  
  20. 04-27 20:11:40.890: E/TestinAgent(16432): Caused by: java.lang.reflect.InvocationTargetException  
  21. 04-27 20:11:40.890: E/TestinAgent(16432):   at java.lang.reflect.Method.invokeNative(Native Method)  
  22. 04-27 20:11:40.890: E/TestinAgent(16432):   at java.lang.reflect.Method.invoke(Method.java:511)  
  23. 04-27 20:11:40.890: E/TestinAgent(16432):   at android.view.View$1.onClick(View.java:3799)  
  24. 04-27 20:11:40.890: E/TestinAgent(16432):   ... 12 more  
  25. 04-27 20:11:40.890: E/TestinAgent(16432): Caused by: java.lang.ArithmeticException: divide by zero  
  26. 04-27 20:11:40.890: E/TestinAgent(16432):   at cn.org.octpus.crash.MainActivity.onClick(MainActivity.java:20)  
  27. 04-27 20:11:40.890: E/TestinAgent(16432):   ... 15 more  
  28. 04-27 20:11:40.890: E/TestinAgent(16432): ----------------------------------------  
  29. 04-27 20:11:40.890: E/TestinAgent(16432): deviceinfo:   
  30. 04-27 20:11:40.890: E/TestinAgent(16432):   Device: samsung/SM-G3812  
  31. 04-27 20:11:40.890: E/TestinAgent(16432):   OS: 4.2.2  
  32. 04-27 20:11:40.890: E/TestinAgent(16432):   AppVersion: 1.0  
  33. 04-27 20:11:40.890: E/TestinAgent(16432):   PackageName: cn.org.octpus.crash  
  34. 04-27 20:11:40.890: E/TestinAgent(16432):   Activity: MainActivity  
  35. 04-27 20:11:40.890: E/TestinAgent(16432):   Total Disk Space: 2328 MB ; Free Disk Space: 1688 MB   
  36. 04-27 20:11:40.890: E/TestinAgent(16432):   Total SD Space: 2308 MB ; Free SD Space: 1668 MB   
  37. 04-27 20:11:40.890: E/TestinAgent(16432):   CPU Usage: 17.742 %   
  38. 04-27 20:11:40.890: E/TestinAgent(16432):   Memory Usage: 12 MB  
  39. 04-27 20:11:40.890: E/TestinAgent(16432):   Userinfo:    
  40. 04-27 20:11:40.890: E/TestinAgent(16432): ****************************************  


(2) 后台信息


后台崩溃数据 

-- 控制台信息 : 进入崩溃大师的控制台, 就会看到刚看到的 CrashInfoDemo 应用, 此时我们估计产生的异常已经打印出来了;


-- 点击进入该应用的详情 : 


-- 详细的崩溃信息查看 



0 0