精华内容
下载资源
问答
  • android 处理程序全局异常和错误

    千次阅读 2011-04-22 17:49:00
    本文将分析在程序出错的情况下如何收集相关的错误信息,并发送错误...该对话框出现对用户来说是相当不友好的,本文中将会告诉您如何在程序出错不显示该对话框。 随着OPhone设备和系统版本的增加,现在在

    本文将分析在程序出错的情况下如何收集相关的错误信息,并发送错误信息到服务器供开发者分析和调试程序。错误信息将成为您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类实现了错误报告的主要处理逻辑,该类代码如下(在代码中会有详细注释来解释各种处理情况):

     

    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.     }  

     

     

    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中包含本文使用的项目文件及资源。

    展开全文
  • 本文将分析在程序出错的情况下如何收集相关的错误信息,并发送错误信息到服务器供开发者分析和调试程序。错误信息将成为您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>

     

    原文地址:http://blog.csdn.net/zhong_ch/archive/2011/04/27/6366023.aspx

    转载于:https://www.cnblogs.com/yingql/archive/2011/06/26/2090698.html

    展开全文
  • 那么万一中毒了,该如何处理呢?下面就谈谈中毒后的一些紧急处理措施:  一、正在上网的用户,发现异常应首先马上断开连接  如果你发现IE经常询问你是否运行某些ACTIVEX控件,或是生成莫明其妙的文件、询问调试...
  • 程序中断方式

    2020-12-30 15:53:00
    程序中断是指在计算机执行现行程序的过程中,出现某些急需处理异常情况或特殊请求,CPU暂时中止现行程序,而转去对这些异常情况或特殊请求进行处理,在处理完毕后CPU又自动返回到现行程序的断点处,继续执行原程序...

    1.中断的基本概念

    程序中断是指在计算机执行现行程序的过程中,出现某些急需处理的异常情况或特殊请求,CPU暂时中止现行程序,而转去对这些异常情况或特殊请求进行处理,在处理完毕后CPU又自动返回到现行程序的断点处,继续执行原程序。

    非屏蔽中断:关中断时也会被响应(如:掉电)
    可屏蔽中断:关中断时不会被响应

    2.中断请求标记(如何判断是哪个设备发来的中断信号?)

    每个中断源向CPU发出中断请求的时间是随机的。
    为了记录中断事件并区分不同的中断源,中断系统需对每个中断源设置中断请求标记触发器INTR,当其状态为“1"时,表示中断源有请求。
    这些触发器可组成中断请求标记寄存器,该寄存器可集中在cPU中,也可分散在各个中断源中。

    在这里插入图片描述

    对于外中断,CPU是在统一的时刻即每条指令执行阶段结束前向接口发出中断查询信号,以获取I/o的中断请求,也就是说,CPU响应中断的时间是在每条指令执行阶段的结束时刻。
    CPU响应中断必须满足以下3个条件:
    ①中断源有中断请求。
    ②CPU允许中断即开中断。
    ③一条指令执行完毕,且没有更紧迫的任务。

    3.中断判优

    在这里插入图片描述

    优先级设置
    1硬件故障中断属于最高级,其次是软件中断;
    2.非屏蔽中断优于可屏蔽中断;
    3.DMA请求优于I/o设备传送的中断请求
    4.高速设备优于低速设备;
    5.输入设备优于输出设备;
    6.实时设备优于普通设备。

    4.中断处理过程

    4.1中断隐指令

    中断隐指令:保存原程序的PC值,并让PC指向中断服务程序的第一条指令
    在这里插入图片描述

    4.1.1硬件向量法

    在这里插入图片描述

    4.1.2软件查询法

    4.2中断服务程序

    在这里插入图片描述

    5.多重中断

    单重中断:执行中断服务程序时不响应新的中断请求。
    多重中断:又称中断嵌套,执行中断服务程序时可响应新的中断请求。
    在这里插入图片描述

    5.1中断屏蔽技术

    在这里插入图片描述

    展开全文
  • 下面这个函数,确定可以关闭MessageBox,但是,弹出多个MessageBox,还是会出现“stackoverflowexception”异常。 private void KillMessageBox() { IntPtr ptr = FindWindow(null, "title"); if (ptr !...
  • 有两部分,请分别下载。...实务13 创建数据库出现错误“ora-03113: end-of-file on 实务13 communication channel” 实务14 安装oracle,报告错误“ora-27102:out of memory” 实务15 在linux(unix)环境...
  • 有两部分,请分别下载。...实务13 创建数据库出现错误“ora-03113: end-of-file on 实务13 communication channel” 实务14 安装oracle,报告错误“ora-27102:out of memory” 实务15 在linux(unix)环境...
  • 实务13 创建数据库出现错误“ora-03113: end-of-file on 实务13 communication channel” 实务14 安装oracle,报告错误“ora-27102:out of memory” 实务15 在linux(unix)环境下成功安装了oracle g,从...
  • [完整][Oracle][Oracle数据库精讲与疑难解析].pdf ...实务16 在Linux AS4安装Oracle i(9.2.X.X),执行runInstaller出现错误 实务17 是否可以在同一机器上既装Oracle i又装Oracle i 实务 实务18 安装Oracle i...
  • 156.屏幕上出现异常杂点或图案 157.显卡过热导致出现花屏、黑屏 158.显卡过热 159.显存芯片过热 160.显存故障导致死机 161.显存设置错误导致游戏速度过慢 162.显卡自检显存不正常 163.不能设置显存大小 164.升级...
  • 多媒体教室

    2013-06-14 08:10:31
    启动教师机后,教师机主界面被最小化,将鼠标移动到屏幕顶部(右半边),会出现以下工具条: 其中窗口按钮可显示教师机主界面,教师机主界面出现后,此工具条将不会弹出;设置按钮指系统设置;复位按钮可以结束...
  • 比如,跳转页面需要登陆状态如何拦截,跳转页面传递参数该怎么办,程序意外跳转异常或者失败又该如何处理? 使用Arouter注意事项有哪些?如何让代码变得更加容易让人维护? 直接看我这篇博客:...
  • 定义一个BaseVideoController类,这个主要是集成各种事件的处理逻辑,比如播放器状态改变,控制视图隐藏和显示,播放进度改变,锁定状态改变,设备方向监听等等操作 定义一个view的接口InterControlView,在这里类里...
  • 多个作业或用户访问存储系统,如何保证优先级和公平性 1.3.1 最大频率栈 1.3.2 给定一个链表,删除链表的倒数第N个节点,并且返回链表的头结点 1.3.3 如果让你设计一个通用的、支持各种数据库秒级备份和恢复...
  • 在测试发现程序死在循环之中,得到的错误记录是"Bus Error"(总线出错),由此可以说明出现了内存操作异常。 经过跟踪变量值发现循环变量i的阀值pSysHead->dbf_count的数值为0xFFFFFFFF,该值是从被破坏的内存...
  •  异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误。java编译器要求方法必须声明抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕获...
  • java 面试题 总结

    2009-09-16 08:45:34
    异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误。java编译器要求方法必须声明抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕获的...
  • 德力西产品说明.pdf

    2019-10-10 18:41:58
    本手册为标准附件,务必请您阅读后妥善保管,以备今后对变频器进行检修和维护使用。 本手册除叙述操作说明外,还提供接线图供您参考。如果您对本产品的使用存在疑难或有特殊要求, 可以联系本公司各地办事处或...
  • •进程管理:又称处理机管理,实质上是对处理机执行“时间”的管理,即如何将CPU真正合理地分配给每个任务。 4、表征操作系统的属性 主要有:响应比,并发性,信息的共享、保密与保护,可扩充性、可移植...
  • C++MFC教程

    热门讨论 2013-05-21 13:37:15
    MFC借助C++的优势为Windows开发开辟了一片新天地,同时也借助ApplicationWizzard使开发者摆脱离了那些每次都必写基本代码,借助ClassWizard和消息映射使开发者摆脱了定义消息处理时那种混乱和冗长的代码段。...
  • 40条引线引出8086/8088的所有信号是不够用的,采用地址/数据线复用引线方法可以解决这一矛盾,从逻辑角度,地址与数据信号不会同时出现,二者可以分复用同一组引线。 9. 8086与8088的主要区别是什么? 答:8086有...
  • 6.21 数组是函数的参数,为什么sizeof不能正确报告数组的大小? 6.22 如何在一个文件中判断声明为extern的数组的大小(例如,数组定义和大小在另一个文件中)?sizeof操作符似乎不行。 6.23 sizeof返回的大小是...
  • (3)针对页面自适应问题,本文结合渐进增强以及拥抱流式布局的思想,同时研究利用了移动设备的视口特性,实现跨分辨率、跨设备的页面自适应。 (4)针对系统的功能实现问题,通过结合利用原生态框架与HTML5的跨平台...
  • 在断言函数的子函数中(例如:在 RT-Thread 的断言钩子方法中)使用,由于函数嵌套会存在寄存器入栈的操作,此时再获取 SP 将发生变化,就需要人为调整(加减固定的偏差值)入参值,所以作为新手 不建议在断言的...
  •  在网络上,我经常能够看到大量精彩的诊断案例与故障处理过程,又常常遗憾这些文字被互联网的海量信息所淹没,于是我进一步萌生了对这些文字进行“编辑”的想法,想通过自己的阅读、学习和选择,让更多的作者能将...
  • 《你必须知道的495个C语言问题》

    热门讨论 2010-03-20 16:41:18
    }但是我如下调用:int *ip; f(ip); 调用者的指针没有任何变化。 47  4.9 能否用void ** 通用指针作为参数,使函数模拟按引用传递参数? 48 4.10 我有一个函数extern intf(int *); ,它接受指向int型的指针。...
  • }但是我如下调用:int *ip; f(ip); 调用者的指针没有任何变化。 47  4.9 能否用void ** 通用指针作为参数,使函数模拟按引用传递参数? 48 4.10 我有一个函数extern intf(int *); ,它接受指向int型的指针。...
  • C#微软培训教材(高清PDF)

    千次下载 热门讨论 2009-07-30 08:51:17
    8.4 异常处理语句 .95 8.5 小 结 .100 第三部分 面向对象的 C#.101 第九章 面向对象的程序设计 .101 9.1 面向对象的基本概念.101 9.2 对象的模型技术 .103 9.3 面向对象的分析 .105 9.4 面向对象的设计...

空空如也

空空如也

1 2 3
收藏数 48
精华内容 19
关键字:

当设备出现异常时如何处理