精华内容
下载资源
问答
  •  彻底解决:禁止Apport(Apport是Ubuntu中错误信息的收集报告系统),打开终端,输入以下命令: gksu gedit /etc/default/apport  这个文件的内容是: # 设置0表示禁用Apportw,或者1开启它。# 你可以用下面...
    #暂时的解决方法,清除错误报告
    sudo rm /var/crash/*
         彻底解决:禁止Apport(Apport是Ubuntu中错误信息的收集报告系统),打开终端,输入以下命令:
    1. gksu gedit /etc/default/apport

           这个文件的内容是:

    1. # 设置0表示禁用Apportw,或者1开启它。
    2. # 你可以用下面的命令暂时关闭它:
    3. # sudo service apport start force_start=1
    4. enabled=1
        把enabled=1改为enabled=0。保存并关闭文件。完成之后你就再也不会看到弹窗报告错误了。很显然,如果我们想重新开

       启错误报告功能,只要再打开这个文件,把enabled设置为1就可以了。


    编译自:http://itsfoss.com/how-to-fix-system-program-problem-detected-ubuntu/ 作者: Abhishek
    原创:LCTT https://linux.cn/article-5904-1.html 译者: XLCYun
    转载地址:https://linux.cn/article-5904-1.html

    展开全文
  • 本文将分析在程序出错的情况下如何收集相关的错误信息,并发送错误信息到服务器供开发者分析和调试程序错误信息将成为您Debug的一把利刃,通过错误信息您可以最及时的掌握程序在各个系统版本和设备上的运行情况。 ...

    本文将分析在程序出错的情况下如何收集相关的错误信息,并发送错误信息到服务器供开发者分析和调试程序。错误信息将成为您Debug的一把利刃,通过错误信息您可以最及时的掌握程序在各个系统版本和设备上的运行情况。

    错误处理介绍

    在一般情况下,OPhone程序出错都会出现如下一个提示对话框:

    图一:OPhone默认出错提示


    这种情况下,用户只有点击“强行关闭”来结束程序。当该对话框出现对用户来说是相当不友好的,本文中将会告诉您如何在程序出错时不显示该对话框。
    随着OPhone设备和系统版本的增加,现在在不同设备和版本上调试程序越来越麻烦,开发者不可能购买所有的设备来逐个调试程序。如果程序在模拟器上运行正常但是到最终用户手中运行却出现了错误,这种情况下如果可以收集到程序错误堆栈信息和具体设备的信息,对开发者调试程序就有莫大的帮助了。
    要收集错误信息,我们需要了解两个主要接口API的使用:android.app.Application 和java.lang.Thread.UncaughtExceptionHandler 。下面就对着两个API做简单介绍。

    UncaughtExceptionHandler:线程未捕获异常控制器是用来处理未捕获异常的。如果程序出现了未捕获异常默认情况下则会出现上面所示的强行关闭对话框。在本文将实现该接口并注册为程序中的默认未捕获异常处理。这样当未捕获异常发生时,就可以做些异常处理操作,例如:收集异常信息,发送错误报告 等。

    Application:在开发OPhone应用时都会和Activity打交道,而Application使用的就相对较少了。Application 在OPhone中是用来管理应用程序的全局状态的,比如载入资源文件。在应用程序启动的时候Application会首先创建,然后才会根据情况(Intent)来启动相应的Activity或者Service。在本文将在Application中注册未捕获异常处理器。

    UncaughtExceptionHandler接口实现

    首先创建一个OPhone项目(项目的创建请参考OPhoneSDN上的其他文章),本文示例项目名称为:CrashReporter ;包名为:org.goodev.cr;并创建一个默认的Activity名字为:ReporterTest。然后创建CrashHandler类实现UncaughtExceptionHandler接口,并实现其函数:public void uncaughtException(Thread thread, Throwable ex)。CrashHandler类实现了错误报告的主要处理逻辑,该类代码如下(在代码中会有详细注释来解释各种处理情况):

    1. package org.goodev.cr;  
    2.   
    3. Import 省略...;  
    4. /** 
    5.  * UncaughtException处理类,当程序发生Uncaught异常的时候,有该类 
    6.  * 来接管程序,并记录 发送错误报告. 
    7.  * 
    8.  */  
    9. public class CrashHandler implements UncaughtExceptionHandler {  
    10.     /** Debug Log tag*/  
    11.     public static final String TAG = "CrashHandler";  
    12.     /** 是否开启日志输出,在Debug状态下开启, 
    13.      * 在Release状态下关闭以提示程序性能 
    14.      * */  
    15.     public static final boolean DEBUG = true;  
    16.     /** 系统默认的UncaughtException处理类 */  
    17.     private Thread.UncaughtExceptionHandler mDefaultHandler;  
    18.     /** CrashHandler实例 */  
    19.     private static CrashHandler INSTANCE;  
    20.     /** 程序的Context对象 */  
    21.     private Context mContext;  
    22.       
    23.     /** 使用Properties来保存设备的信息和错误堆栈信息*/  
    24.     private Properties mDeviceCrashInfo = new Properties();  
    25.     private static final String VERSION_NAME = "versionName";  
    26.     private static final String VERSION_CODE = "versionCode";  
    27.     private static final String STACK_TRACE = "STACK_TRACE";  
    28.     /** 错误报告文件的扩展名 */  
    29.     private static final String CRASH_REPORTER_EXTENSION = ".cr";  
    30.       
    31.     /** 保证只有一个CrashHandler实例 */  
    32.     private CrashHandler() {}  
    33.     /** 获取CrashHandler实例 ,单例模式*/  
    34.     public static CrashHandler getInstance() {  
    35.         if (INSTANCE == null) {  
    36.             INSTANCE = new CrashHandler();  
    37.         }  
    38.         return INSTANCE;  
    39.     }  
    40.   
    41.     /** 
    42.      * 初始化,注册Context对象, 
    43.      * 获取系统默认的UncaughtException处理器, 
    44.      * 设置该CrashHandler为程序的默认处理器 
    45.      *  
    46.      * @param ctx 
    47.      */  
    48.     public void init(Context ctx) {  
    49.         mContext = ctx;  
    50.         mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();  
    51.         Thread.setDefaultUncaughtExceptionHandler(this);  
    52.     }  
    53.   
    54.     /** 
    55.      * 当UncaughtException发生时会转入该函数来处理 
    56.      */  
    57.     @Override  
    58.     public void uncaughtException(Thread thread, Throwable ex) {  
    59.         if (!handleException(ex) && mDefaultHandler != null) {  
    60.             //如果用户没有处理则让系统默认的异常处理器来处理  
    61.             mDefaultHandler.uncaughtException(thread, ex);  
    62.         } else {  
    63.             //Sleep一会后结束程序  
    64.             try {  
    65.                 Thread.sleep(3000);  
    66.             } catch (InterruptedException e) {  
    67.                 Log.e(TAG, "Error : ", e);  
    68.             }  
    69.             android.os.Process.killProcess(android.os.Process.myPid());  
    70.             System.exit(10);  
    71.         }  
    72.     }  
    73.   
    74.     /** 
    75.      * 自定义错误处理,收集错误信息 
    76.      * 发送错误报告等操作均在此完成. 
    77.      * 开发者可以根据自己的情况来自定义异常处理逻辑 
    78.      * @param ex 
    79.      * @return true:如果处理了该异常信息;否则返回false 
    80.      */  
    81.     private boolean handleException(Throwable ex) {  
    82.         if (ex == null) {  
    83.             return true;  
    84.         }  
    85.         final String msg = ex.getLocalizedMessage();  
    86.         //使用Toast来显示异常信息  
    87.         new Thread() {  
    88.             @Override  
    89.             public void run() {  
    90.                 Looper.prepare();  
    91.                 Toast.makeText(mContext, "程序出错啦:" + msg, Toast.LENGTH_LONG)  
    92.                         .show();  
    93.                 Looper.loop();  
    94.             }  
    95.   
    96.         }.start();  
    97.         //收集设备信息  
    98.         collectCrashDeviceInfo(mContext);  
    99.         //保存错误报告文件  
    100.         String crashFileName = saveCrashInfoToFile(ex);  
    101.         //发送错误报告到服务器  
    102.         sendCrashReportsToServer(mContext);  
    103.         return true;  
    104.     }  
    105.   
    106.     /** 
    107.      * 在程序启动时候, 可以调用该函数来发送以前没有发送的报告 
    108.      */  
    109.     public void sendPreviousReportsToServer() {  
    110.         sendCrashReportsToServer(mContext);  
    111.     }  
    112.   
    113.     /** 
    114.      * 把错误报告发送给服务器,包含新产生的和以前没发送的. 
    115.      *  
    116.      * @param ctx 
    117.      */  
    118.     private void sendCrashReportsToServer(Context ctx) {  
    119.         String[] crFiles = getCrashReportFiles(ctx);  
    120.         if (crFiles != null && crFiles.length > 0) {  
    121.             TreeSet<String> sortedFiles = new TreeSet<String>();  
    122.             sortedFiles.addAll(Arrays.asList(crFiles));  
    123.   
    124.             for (String fileName : sortedFiles) {  
    125.                 File cr = new File(ctx.getFilesDir(), fileName);  
    126.                 postReport(cr);  
    127.                 cr.delete();// 删除已发送的报告  
    128.             }  
    129.         }  
    130.     }  
    131.   
    132.     private void postReport(File file) {  
    133.         // TODO 使用HTTP Post 发送错误报告到服务器  
    134.         // 这里不再详述,开发者可以根据OPhoneSDN上的其他网络操作  
    135.         // 教程来提交错误报告  
    136.     }  
    137.   
    138.     /** 
    139.      * 获取错误报告文件名 
    140.      * @param ctx 
    141.      * @return 
    142.      */  
    143.     private String[] getCrashReportFiles(Context ctx) {  
    144.         File filesDir = ctx.getFilesDir();  
    145.         FilenameFilter filter = new FilenameFilter() {  
    146.             public boolean accept(File dir, String name) {  
    147.                 return name.endsWith(CRASH_REPORTER_EXTENSION);  
    148.             }  
    149.         };  
    150.         return filesDir.list(filter);  
    151.     }  
    152.     /** 
    153.      * 保存错误信息到文件中 
    154.      * @param ex 
    155.      * @return 
    156.      */  
    157.     private String saveCrashInfoToFile(Throwable ex) {  
    158.         Writer info = new StringWriter();  
    159.         PrintWriter printWriter = new PrintWriter(info);  
    160.         ex.printStackTrace(printWriter);  
    161.   
    162.         Throwable cause = ex.getCause();  
    163.         while (cause != null) {  
    164.             cause.printStackTrace(printWriter);  
    165.             cause = cause.getCause();  
    166.         }  
    167.   
    168.         String result = info.toString();  
    169.         printWriter.close();  
    170.         mDeviceCrashInfo.put(STACK_TRACE, result);  
    171.   
    172.         try {  
    173.             long timestamp = System.currentTimeMillis();  
    174.             String fileName = "crash-" + timestamp + CRASH_REPORTER_EXTENSION;  
    175.             FileOutputStream trace = mContext.openFileOutput(fileName,  
    176.                     Context.MODE_PRIVATE);  
    177.             mDeviceCrashInfo.store(trace, "");  
    178.             trace.flush();  
    179.             trace.close();  
    180.             return fileName;  
    181.         } catch (Exception e) {  
    182.             Log.e(TAG, "an error occured while writing report file...", e);  
    183.         }  
    184.         return null;  
    185.     }  
    186.   
    187.   
    188.     /** 
    189.      * 收集程序崩溃的设备信息 
    190.      *  
    191.      * @param ctx 
    192.      */  
    193.     public void collectCrashDeviceInfo(Context ctx) {  
    194.         try {  
    195.             PackageManager pm = ctx.getPackageManager();  
    196.             PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(),  
    197.                     PackageManager.GET_ACTIVITIES);  
    198.             if (pi != null) {  
    199.                 mDeviceCrashInfo.put(VERSION_NAME,  
    200.                         pi.versionName == null ? "not set" : pi.versionName);  
    201.                 mDeviceCrashInfo.put(VERSION_CODE, pi.versionCode);  
    202.             }  
    203.         } catch (NameNotFoundException e) {  
    204.             Log.e(TAG, "Error while collect package info", e);  
    205.         }  
    206.         //使用反射来收集设备信息.在Build类中包含各种设备信息,  
    207.         //例如: 系统版本号,设备生产商 等帮助调试程序的有用信息  
    208. //具体信息请参考后面的截图  
    209.         Field[] fields = Build.class.getDeclaredFields();  
    210.         for (Field field : fields) {  
    211.             try {  
    212.                 field.setAccessible(true);  
    213.                 mDeviceCrashInfo.put(field.getName(), field.get(null));  
    214.                 if (DEBUG) {  
    215.                     Log.d(TAG, field.getName() + " : " + field.get(null));  
    216.                 }  
    217.             } catch (Exception e) {  
    218.                 Log.e(TAG, "Error while collect crash info", e);  
    219.             }  
    220.   
    221.         }  
    222.   
    223.     }  
    224.   
    225. }  

    在上面CrashHandler实现中,当错误发生的时候使用Toast显示错误信息,然后收集错误报告并保存在文件中。 发送错误报告代码请读者自己实现。在uncaughtException函数中调用了Thread.sleep(3000);来让线程停止一会是为了显示Toast信息给用户,然后Kill程序。如果你不用Toast来显示信息则可以去除该代码。除了Toast外,开发者还可以选择使用Notification来显示错误内容并让用户选择是否提交错误报告而不是自动提交。关于Notification的实现请读者参考:NotificationManager。在发送错误报道的时候,可以先检测网络是否可用,如果不可用则可以在以后网络情况可用的情况下发送。 网络监测代码如下:

    1. /** 
    2.      * 检测网络连接是否可用 
    3.      * @param ctx 
    4.      * @return true 可用; false 不可用 
    5.      */  
    6.     private boolean isNetworkAvailable(Context ctx) {  
    7.         ConnectivityManager cm =   
    8.             (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);  
    9.         if(cm == null) {  
    10.             return false;  
    11.         }  
    12.         NetworkInfo[] netinfo = cm.getAllNetworkInfo();  
    13.         if(netinfo == null) {  
    14.             return false;  
    15.         }  
    16.         for (int i = 0; i < netinfo.length; i++) {  
    17.             if(netinfo[i].isConnected()) {  
    18.                 return true;  
    19.             }  
    20.         }  
    21.         return false;  
    22.     }  

    下面是在模拟器和笔者手机(Dell mini3i OPhone1.5系统)上收集的具体信息截图:

    图二: 模拟器信息截图

    图三:Dell mini3i 设备信息截图
     

    Application 实现

    实现一个自定义Application来注册CrashHandler. 代码如下:

    1. public class CrashApplication extends Application {  
    2.   
    3.     @Override  
    4.     public void onCreate() {  
    5.         super.onCreate();  
    6.         CrashHandler crashHandler = CrashHandler.getInstance();  
    7.         //注册crashHandler  
    8.         crashHandler.init(getApplicationContext());  
    9.         //发送以前没发送的报告(可选)  
    10.         crashHandler.sendPreviousReportsToServer();  
    11.     }  
    12.       
    13. }  

    在AndroidManifest.xml中注册

    最后只要在AndroidManifest.xml中注册CrashApplication就可以了。代码如下:

    1. <?xml version="1.0" encoding="utf-8"?>  
    2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
    3.       package="org.goodev.cr"  
    4.       android:versionCode="1"  
    5.       android:versionName="1.0">  
    6.     <application android:icon="@drawable/icon" android:label="@string/app_name"   
    7.         android:name=".CrashApplication">  
    8.         <activity android:name=".ReporterTest"  
    9.                   android:label="@string/app_name">  
    10.             <intent-filter>  
    11.                 <action android:name="android.intent.action.MAIN" />  
    12.                 <category android:name="android.intent.category.LAUNCHER" />  
    13.             </intent-filter>  
    14.         </activity>  
    15.     </application>  
    16. </manifest>   
      总结:通过本文示例的方式,开发者可以在程序中收集详细的崩溃信息,从而为调试程序带来便利,如果您的程序还没有该功能赶快加入吧。crashReporter.zip中包含本文使用的项目文件及资源
    展开全文
  • android 程序错误全局处理

    千次阅读 2011-04-13 17:35:00
    转:http://blog.csdn.net/liangguohuan/archive/2010/11/19/6022419.aspx本文将分析在程序出错的情况下如何收集相关的错误信息,并发送错误信息到服务器供开发者分析和调试程序错误信息将成为您Debug的一把利刃,...

    一、Application Crash Report for Android

    转:http://www.chengyunfeng.com/2010/07/application-crash-report-for-android

    你的Android程序是否会崩溃呢!是否有用户抱怨程序崩溃,但是您又收集不到崩溃时候的详细信息呢?是否希望给您的用户提供更好的用户体验呢?ACRA(Android程序崩溃报告)就是一个帮助您在程序崩溃时候收集信息的项目.

    使用ACRA当您的程序崩溃的时候,可以发送一个崩溃报告到Google Doc中,然后您就可以查看程序崩溃时候系统的信息.

    项目主页:http://code.google.com/p/acra/

    使用文档:http://code.google.com/p/acra/wiki/ACRAHowTo

     

    、 android 程序错误全局处理

    转:http://blog.csdn.net/liangguohuan/archive/2010/11/19/6022419.aspx

    本文将分析在程序出错的情况下如何收集相关的错误信息,并发送错误信息到服务器供开发者分析和调试程序。错误信息将成为您Debug的一把利刃,通过错误信息您可以最及时的掌握程序在各个系统版本和设备上的运行情况。 错误处理介绍 在一般情况下,OPhone程序出错都会出现如下一个提示对话框:

     

    图一:OPhone默认出错提示

     

     

    这种情况下,用户只有点击“强行关闭”来结束程序。当该对话框出现对用户来说是相当不友好的,本文中将会告诉您如何在程序出错时不显示该对话框。
    随着OPhone设备和系统版本的增加,现在在不同设备和版本上调试程序越来越麻烦,开发者不可能购买所有的设备来逐个调试程序。如果程序在模拟器上运行正常但是到最终用户手中运行却出现了错误,这种情况下如果可以收集到程序错误堆栈信息和具体设备的信息,对开发者调试程序就有莫大的帮助了。
    要收集错误信息,我们需要了解两个主要接口API的使用:android.app.Application 和java.lang.Thread.UncaughtExceptionHandler 。下面就对着两个API做简单介绍。

    UncaughtExceptionHandler:线程未捕获异常控制器是用来处理未捕获异常的。如果程序出现了未捕获异常默认情况下则会出现上面所示的强行关闭对话框。在本文将实现该接口并注册为程序中的默认未捕获异常处理。这样当未捕获异常发生时,就可以做些异常处理操作,例如:收集异常信息,发送错误报告 等。

    Application:在开发OPhone应用时都会和Activity打交道,而Application使用的就相对较少了。Application 在OPhone中是用来管理应用程序的全局状态的,比如载入资源文件。在应用程序启动的时候Application会首先创建,然后才会根据情况(Intent)来启动相应的Activity或者Service。在本文将在Application中注册未捕获异常处理器。

    UncaughtExceptionHandler接口实现

    首先创建一个OPhone项目(项目的创建请参考OPhoneSDN上的其他文章),本文示例项目名称为:CrashReporter ;包名为:org.goodev.cr;并创建一个默认的Activity名字为:ReporterTest。然后创建CrashHandler类实现UncaughtExceptionHandler接口,并实现其函数:public void uncaughtException(Thread thread, Throwable ex)。CrashHandler类实现了错误报告的主要处理逻辑,该类代码如下(在代码中会有详细注释来解释各种处理情况):

     

     

     

     

    在上面CrashHandler实现中,当错误发生的时候使用Toast显示错误信息,然后收集错误报告并保存在文件中。 发送错误报告代码请读者自己实现。在uncaughtException函数中调用了Thread.sleep(3000);来让线程停止一会是为了显示Toast信息给用户,然后Kill程序。如果你不用Toast来显示信息则可以去除该代码。除了Toast外,开发者还可以选择使用Notification来显示错误内容并让用户选择是否提交错误报告而不是自动提交。关于Notification的实现请读者参考:NotificationManager。在发送错误报道的时候,可以先检测网络是否可用,如果不可用则可以在以后网络情况可用的情况下发送。 网络监测代码如下:

     

     

     

    下面是在模拟器和笔者手机(Dell mini3i OPhone1.5系统)上收集的具体信息截图:

     

     

    图二: 模拟器信息截图

    图三:Dell mini3i 设备信息截图

     

     

     

    Application 实现

    实现一个自定义Application来注册CrashHandler. 代码如下:

     

     

     

     

     

    在AndroidManifest.xml中注册

    最后只要在AndroidManifest.xml中注册CrashApplication就可以了。代码如下:

     

     

     

     

    总结:通过本文示例的方式,开发者可以在程序中收集详细的崩溃信息,从而为调试程序带来便利,如果您的程序还没有该功能赶快加入吧。crashReporter.zip中包含本文使用的项目文件及资源。

    作者简介: 程云峰,网名icess,目前就职于杭州恒生电子研发中心,喜欢Java开源技术。
    个人网站:http://www.chengyunfeng.com/ 

    (声明:本网的新闻及文章版权均属OPhone SDN网站所有,如需转载请与我们编辑团队联系。任何媒体、网站或个人未经本网书面协议授权,不得进行任何形式的转载。已经取得本网协议授权的媒体、网站,在转载使用时请注明稿件来源。)


     

     

    展开全文
  • 本文将分析在程序出错的情况下如何收集相关的错误信息,并发送错误信息到服务器供开发者分析和调试程序错误信息将成为您Debug的一把利刃,通过错误信息您可以最及时的掌握程序在各个系统版本和设备上的运行情况。 ...
    本文将分析在程序出错的情况下如何收集相关的错误信息,并发送错误信息到服务器供开发者分析和调试程序。错误信息将成为您Debug的一把利刃,通过错误信息您可以最及时的掌握程序在各个系统版本和设备上的运行情况。

    错误处理介绍

    在一般情况下,OPhone程序出错都会出现一个提示对话框
    这种情况下,用户只有点击“强行关闭”来结束程序。当该对话框出现对用户来说是相当不友好的,本文中将会告诉您如何在程序出错时不显示该对话框。
    随着OPhone设备和系统版本的增加,现在在不同设备和版本上调试程序越来越麻烦,开发者不可能购买所有的设备来逐个调试程序。如果程序在模拟器上运行正常但是到最终用户手中运行却出现了错误,这种情况下如果可以收集到程序错误堆栈信息和具体设备的信息,对开发者调试程序就有莫大的帮助了。
    要收集错误信息,我们需要了解两个主要接口API的使用:Android.app.Application 和java.lang.Thread.UncaughtExceptionHandler 。下面就对着两个API做简单介绍。

    UncaughtExceptionHandler:线程未捕获异常控制器是用来处理未捕获异常的。如果程序出现了未捕获异常默认情况下则会出现上面所示的强行关闭对话框。在本文将实现该接口并注册为程序中的默认未捕获异常处理。这样当未捕获异常发生时,就可以做些异常处理操作,例如:收集异常信息,发送错误报告 等。

    Application:在开发OPhone应用时都会和Activity打交道,而Application使用的就相对较少了。Application 在OPhone中是用来管理应用程序的全局状态的,比如载入资源文件。在应用程序启动的时候Application会首先创建,然后才会根据情况(Intent)来启动相应的Activity或者Service。在本文将在Application中注册未捕获异常处理器。


    UncaughtExceptionHandler接口实现

    首先创建一个OPhone项目(项目的创建请参考OPhoneSDN上的其他文章),本文示例项目名称为:CrashReporter ;包名为:org.goodev.cr;并创建一个默认的Activity名字为:ReporterTest。然后创建CrashHandler类实现UncaughtExceptionHandler接口,并实现其函数:public void uncaughtException(Thread thread, Throwable ex)。CrashHandler类实现了错误报告的主要处理逻辑,该类代码如下(在代码中会有详细注释来解释各种处理情况):





    package org.goodev.cr;

    Import 省略...;
    /**
    * UncaughtException处理类,当程序发生Uncaught异常的时候,有该类
    * 来接管程序,并记录 发送错误报告.
    *
    */
    public class CrashHandler implements UncaughtExceptionHandler {
    /** Debug Log tag*/
    public static final String TAG = "CrashHandler";
    /** 是否开启日志输出,在Debug状态下开启,
    * 在Release状态下关闭以提示程序性能
    * */
    public static final boolean DEBUG = true;
    /** 系统默认的UncaughtException处理类 */
    private Thread.UncaughtExceptionHandler mDefaultHandler;
    /** CrashHandler实例 */
    private static CrashHandler INSTANCE;
    /** 程序的Context对象 */
    private Context mContext;

    /** 使用Properties来保存设备的信息和错误堆栈信息*/
    private Properties mDeviceCrashInfo = new Properties();
    private static final String VERSION_NAME = "versionName";
    private static final String VERSION_CODE = "versionCode";
    private static final String STACK_TRACE = "STACK_TRACE";
    /** 错误报告文件的扩展名 */
    private static final String CRASH_REPORTER_EXTENSION = ".cr";

    /** 保证只有一个CrashHandler实例 */
    private CrashHandler() {}
    /** 获取CrashHandler实例 ,单例模式*/
    public static CrashHandler getInstance() {
    if (INSTANCE == null) {
    INSTANCE = new CrashHandler();
    }
    return INSTANCE;
    }

    /**
    * 初始化,注册Context对象,
    * 获取系统默认的UncaughtException处理器,
    * 设置该CrashHandler为程序的默认处理器
    *
    * @param ctx
    */
    public void init(Context ctx) {
    mContext = ctx;
    mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
    Thread.setDefaultUncaughtExceptionHandler(this);
    }

    /**
    * 当UncaughtException发生时会转入该函数来处理
    */
    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
    if (!handleException(ex) && mDefaultHandler != null) {
    //如果用户没有处理则让系统默认的异常处理器来处理
    mDefaultHandler.uncaughtException(thread, ex);
    } else {
    //Sleep一会后结束程序
    try {
    Thread.sleep(3000);
    } catch (InterruptedException e) {
    Log.e(TAG, "Error : ", e);
    }
    Android.os.Process.killProcess(android.os.Process.myPid());
    System.exit(10);
    }
    }

    /**
    * 自定义错误处理,收集错误信息
    * 发送错误报告等操作均在此完成.
    * 开发者可以根据自己的情况来自定义异常处理逻辑
    * @param ex
    * @return true:如果处理了该异常信息;否则返回false
    */
    private boolean handleException(Throwable ex) {
    if (ex == null) {
    return true;
    }
    final String msg = ex.getLocalizedMessage();
    //使用Toast来显示异常信息
    new Thread() {
    @Override
    public void run() {
    Looper.prepare();
    Toast.makeText(mContext, "程序出错啦:" + msg, Toast.LENGTH_LONG)
    .show();
    Looper.loop();
    }

    }.start();
    //收集设备信息
    collectCrashDeviceInfo(mContext);
    //保存错误报告文件
    String crashFileName = saveCrashInfoToFile(ex);
    //发送错误报告到服务器
    sendCrashReportsToServer(mContext);
    return true;
    }

    /**
    * 在程序启动时候, 可以调用该函数来发送以前没有发送的报告
    */
    public void sendPreviousReportsToServer() {
    sendCrashReportsToServer(mContext);
    }

    /**
    * 把错误报告发送给服务器,包含新产生的和以前没发送的.
    *
    * @param ctx
    */
    private void sendCrashReportsToServer(Context ctx) {
    String[] crFiles = getCrashReportFiles(ctx);
    if (crFiles != null && crFiles.length > 0) {
    TreeSet<String> sortedFiles = new TreeSet<String>();
    sortedFiles.addAll(Arrays.asList(crFiles));

    for (String fileName : sortedFiles) {
    File cr = new File(ctx.getFilesDir(), fileName);
    postReport(cr);
    cr.delete();// 删除已发送的报告
    }
    }
    }

    private void postReport(File file) {
    // TODO 使用HTTP Post 发送错误报告到服务器
    // 这里不再详述,开发者可以根据OPhoneSDN上的其他网络操作
    // 教程来提交错误报告
    }

    /**
    * 获取错误报告文件名
    * @param ctx
    * @return
    */
    private String[] getCrashReportFiles(Context ctx) {
    File filesDir = ctx.getFilesDir();
    FilenameFilter filter = new FilenameFilter() {
    public boolean accept(File dir, String name) {
    return name.endsWith(CRASH_REPORTER_EXTENSION);
    }
    };
    return filesDir.list(filter);
    }
    /**
    * 保存错误信息到文件中
    * @param ex
    * @return
    */
    private String saveCrashInfoToFile(Throwable ex) {
    Writer info = new StringWriter();
    PrintWriter printWriter = new PrintWriter(info);
    ex.printStackTrace(printWriter);

    Throwable cause = ex.getCause();
    while (cause != null) {
    cause.printStackTrace(printWriter);
    cause = cause.getCause();
    }

    String result = info.toString();
    printWriter.close();
    mDeviceCrashInfo.put(STACK_TRACE, result);

    try {
    long timestamp = System.currentTimeMillis();
    String fileName = "crash-" + timestamp + CRASH_REPORTER_EXTENSION;
    FileOutputStream trace = mContext.openFileOutput(fileName,
    Context.MODE_PRIVATE);
    mDeviceCrashInfo.store(trace, "");
    trace.flush();
    trace.close();
    return fileName;
    } catch (Exception e) {
    Log.e(TAG, "an error occured while writing report file...", e);
    }
    return null;
    }


    /**
    * 收集程序崩溃的设备信息
    *
    * @param ctx
    */
    public void collectCrashDeviceInfo(Context ctx) {
    try {
    PackageManager pm = ctx.getPackageManager();
    PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(),
    PackageManager.GET_ACTIVITIES);
    if (pi != null) {
    mDeviceCrashInfo.put(VERSION_NAME,
    pi.versionName == null ? "not set" : pi.versionName);
    mDeviceCrashInfo.put(VERSION_CODE, pi.versionCode);
    }
    } catch (NameNotFoundException e) {
    Log.e(TAG, "Error while collect package info", e);
    }
    //使用反射来收集设备信息.在Build类中包含各种设备信息,
    //例如: 系统版本号,设备生产商 等帮助调试程序的有用信息
    //具体信息请参考后面的截图
    Field[] fields = Build.class.getDeclaredFields();
    for (Field field : fields) {
    try {
    field.setAccessible(true);
    mDeviceCrashInfo.put(field.getName(), field.get(null));
    if (DEBUG) {
    Log.d(TAG, field.getName() + " : " + field.get(null));
    }
    } catch (Exception e) {
    Log.e(TAG, "Error while collect crash info", e);
    }

    }

    }

    }


    在上面CrashHandler实现中,当错误发生的时候使用Toast显示错误信息,然后收集错误报告并保存在文件中。 发送错误报告代码请读者自己实现。在uncaughtException函数中调用了Thread.sleep(3000);来让线程停止一会是为了显示Toast信息给用户,然后Kill程序。如果你不用Toast来显示信息则可以去除该代码。除了Toast外,开发者还可以选择使用Notification来显示错误内容并让用户选择是否提交错误报告而不是自动提交。关于Notification的实现请读者参考:NotificationManager。在发送错误报道的时候,可以先检测网络是否可用,如果不可用则可以在以后网络情况可用的情况下发送。 网络监测代码如下:

    /**
    * 检测网络连接是否可用
    * @param ctx
    * @return true 可用; false 不可用
    */
    private boolean isNetworkAvailable(Context ctx) {
    ConnectivityManager cm =
    (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
    if(cm == null) {
    return false;
    }
    NetworkInfo[] netinfo = cm.getAllNetworkInfo();
    if(netinfo == null) {
    return false;
    }
    for (int i = 0; i < netinfo.length; i++) {
    if(netinfo[i].isConnected()) {
    return true;
    }
    }
    return false;
    }




    Application 实现

    实现一个自定义Application来注册CrashHandler. 代码如下:

    public class CrashApplication extends Application {

    @Override
    public void onCreate() {
    super.onCreate();
    CrashHandler crashHandler = CrashHandler.getInstance();
    //注册crashHandler
    crashHandler.init(getApplicationContext());
    //发送以前没发送的报告(可选)
    crashHandler.sendPreviousReportsToServer();
    }

    }


    在AndroidManifest.xml中注册

    最后只要在AndroidManifest.xml中注册CrashApplication就可以了。代码如下:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:Android="http://schemas.android.com/apk/res/android"
    package="org.goodev.cr"
    Android:versionCode="1"
    Android:versionName="1.0">
    <application Android:icon="@drawable/icon" android:label="@string/app_name"
    Android:name=".CrashApplication">
    <activity Android:name=".ReporterTest"
    Android:label="@string/app_name">
    <intent-filter>
    <action Android:name="android.intent.action.MAIN" />
    <category Android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
    </activity>
    </application>
    </manifest>



    总结:通过本文示例的方式,开发者可以在程序中收集详细的崩溃信息,从而为调试程序带来便利,如果您的程序还没有该功能赶快加入吧。crashReporter.zip中包含本文使用的项目文件及资源。
    展开全文
  • 本文将分析在程序出错的情况下如何收集相关的错误信息,并发送错误信息到服务器供开发者分析和调试程序错误信息将成为您Debug的一把利刃,通过错误信息您可以最及时的掌握程序在各个系统版本和设备上的运行情况。 ...
  • 如何关闭CD自动播放功能.txt 如何关闭Dr.Watson.txt 如何加密文件及文件夹.txt 如何启动休眠功能.txt 如何实现关机时清空页面文件.txt 如何彻底删除输入法文件.txt 如何找到自启动程序.txt 如何挽救软盘文件...
  • 这时可以清理屏幕,减少窗口的数目,关闭不用的应用程序,包括TSR内存驻留程序,将Windows应用程序最小化为图标,如果问题只是在运行一特殊的应用程序时出现,则与应用软件销售商联系,可能是数据对象的管理不好所致...
  •  ·使用plsql warnings和异常处理程序标识和消除错误  ·使用函数、过程、包、集合和触发器  ·定义和部署varray、嵌套表和联合数组数据类型  ·处理外部例程、对象类型、大对象和安全文件  ·使用dbms alert和...
  •  ·使用plsql warnings和异常处理程序标识和消除错误  ·使用函数、过程、包、集合和触发器  ·定义和部署varray、嵌套表和联合数组数据类型  ·处理外部例程、对象类型、大对象和安全文件  ·使用dbms alert和...
  • 本书的目的就是帮助读者了解c++是如何支持编程技术的,使读者能从中获得新的理解,从而成为一名优秀的编程人员和设计人员。适合做高校面向对象编程课程的教科书,也可作为c++爱好者的参考书。 [center] [a href=...
  • C++程序设计语言(特别版)--源代码

    热门讨论 2012-04-23 07:33:51
    本书的目的就是帮助读者了解c++是如何支持编程技术的,使读者能从中获得新的理解,从而成为一名优秀的编程人员和设计人员。适合做高校面向对象编程课程的教科书,也可作为c++爱好者的参考书。 [center] [a href=...
  • 本书的目的就是帮助读者了解c++是如何支持编程技术的,使读者能从中获得新的理解,从而成为一名优秀的编程人员和设计人员。适合做高校面向对象编程课程的教科书,也可作为c++爱好者的参考书。 [center] [a href=...
  • 转--全局异常处理

    2015-03-20 15:16:00
    本文将分析在程序出错的情况下如何收集相关的错误信息,并发送错误信息到服务器供开发者分析和调试程序错误信息将成为您Debug的一把利刃,通过错误信息您可以最及时的掌握程序在各个系统版本和设备上的运行情况。 ...
  • 对app的线上bug的收集(友盟、云捕等)有时会得到这样的异常堆栈信息:没有一行代码是有关自身程序代码的。这使得对bug的解决无从下手,根据经验,内存不足OOM,Dialog关闭,ListView等相关代码很容易引起这类错误。...
  • 使用此扩展程序,您可以在阅读时收集编辑建议,而无需麻烦地复制文本,向下滚动并将其添加到注释中,然后设置其格式以显示需要更改的部分。 如何使用扩展名:1.在RoyalRoadL的章节页面上,选择要建议对其进行编辑的...
  • 这个扩展极大地简化了章节内容中指出错误的过程。 使用此扩展程序,您可以在阅读时收集编辑建议,而无需麻烦地复制文本,向下滚动并将其添加到注释中,然后设置其格式以显示需要更改的部分。 如何使用扩展名:1.在...
  • 通过掌握程序如何映射到系统上,以及程序如何执行的,读者能够更好的理解程序的行为为什么是这样的,以及效率低下是如何造成的。粗略来看,计算机系统包括处理器和存储器硬件、编译器、操作系统和网络互连环境。...
  • 备注:关闭应用程序之前,用函数DestroyMenu来销毁菜单并释放加载菜单占用的内存。Windows CE 1.0不支持层叠式菜单。Windows CE 2.0及更高版本支持层叠式菜单。 速查:Windows NT:3.1及以上版本;Windows:95及...
  • windowsnt 技术内幕

    2014-04-09 20:47:17
    调协系统管理告警(Administrative Alert) 向用户发送系统管理消息 远程关闭一台Windows NT计算机 使用Windows NT系统属性对话框 Windows NT诊断程序(Diagnostic)简介 使用Windows NT诊断程序打印一份报告 在Windows ...
  • 文件操作,数据压缩,文件传输 Java数据压缩与传输实例,可以学习一下实例化套按字、得到文件输入流、压缩输入流、文件输出流、实例化缓冲区、写入数据到文件、关闭输入流、关闭套接字关闭输出流、输出错误信息等Java...

空空如也

空空如也

1 2 3 4 5 6
收藏数 101
精华内容 40
关键字:

如何关闭错误收集程序