Android学习之 应用崩溃异常处理
2014-06-17 23:34
344 查看
针对应用程序不可避免的出现一些异常使得应用崩溃的情况,当然android系统本身在软件遇到没有捕获的异常之后 系统会弹出一个默认的强制关闭对话框,
但是只实际的应用开发中 我们通常会有一个全局的异常捕获器,当出现一个我们没有发现的异常时,捕获这个异常,并且将异常信息记录下来,在UI上给出友好的提示 或是上传到服务器供开发者分析出现异常的具体原因。
实现机制:在Application中注册我们自己的线程未捕获异常处理器<实现UncaughtExceptionHandler接口>
先了解这两个类:android.app.Application和java.lang.Thread.UncaughtExceptionHandler
Application:用来管理应用程序的全局状态
Thread.UncaughtExceptionHandler:线程未捕获异常处理器,用来处理未捕获异常。如果程序出现了未捕获异常,默认会弹出系统中强制关闭对话框。我们需要实现此接口,并注册为程序中默认未捕获异常处理。这样当未捕获异常发生时,就可以做一些个性化的异常处理操作。
下面是具体的代码实现:
1、线程未捕获异常处理器,用来处理未捕获的异常类:CrashHandler.java
2、完成这个CrashHandler后,我们需要在一个Application环境中让其运行,为此,我们继承android.app.Application 在子类中<IceApplication>注册初始化CrashHandler。代码如下:
3、最后,为了让我们的IceApplication取代android.app.Application的地位,在我们的代码中生效,我们需要修改AndroidManifest.xml:
4、在代码中有遇到异常后要保存设备参数和具体异常信息到sdCard,所以我们需要在AndroidManifest.xml中加入读写SDCARD权限:
5、运行项目、当应用遇到有未捕获的异常后 看到的效果如下:
同时在SDCARD上有生成的日志信息文件:
这些日志信息文件对于开发者来说是非常有帮助的。
最后感谢博客:http://blog.csdn.net/liuhe688/article/details/6584143 给我带来学习参考的内容。
但是只实际的应用开发中 我们通常会有一个全局的异常捕获器,当出现一个我们没有发现的异常时,捕获这个异常,并且将异常信息记录下来,在UI上给出友好的提示 或是上传到服务器供开发者分析出现异常的具体原因。
实现机制:在Application中注册我们自己的线程未捕获异常处理器<实现UncaughtExceptionHandler接口>
先了解这两个类:android.app.Application和java.lang.Thread.UncaughtExceptionHandler
Application:用来管理应用程序的全局状态
Thread.UncaughtExceptionHandler:线程未捕获异常处理器,用来处理未捕获异常。如果程序出现了未捕获异常,默认会弹出系统中强制关闭对话框。我们需要实现此接口,并注册为程序中默认未捕获异常处理。这样当未捕获异常发生时,就可以做一些个性化的异常处理操作。
下面是具体的代码实现:
1、线程未捕获异常处理器,用来处理未捕获的异常类:CrashHandler.java
package com.ice.android.common.excepion; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.io.Writer; import java.lang.Thread.UncaughtExceptionHandler; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Map; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.os.Looper; import android.os.Process; import android.util.Log; import android.widget.Toast; import com.ice.android.common.utils.SdcardUtil; /** * 线程未捕获异常处理器,用来处理未捕获的异常 * 当程序发生Uncaught异常的时候,由该类来处理程序并记录/发送错误报告 * @author ice * * 参考博客:http://blog.csdn.net/liuhe688/article/details/6584143 */ public class CrashHandler implements UncaughtExceptionHandler { public static final String TAG = "CrashHandler"; /** 系统默认的 UncaughtException 处理对象 */ private Thread.UncaughtExceptionHandler mDefaultHandler; private Context mContext; /** * 用于存储手机设备的参数信息 */ private Map<String, String> infos = new HashMap<String, String>(); private static CrashHandler mCrashHandler; private CrashHandler(){ } /** 获取CrashHandler实例 ,单例模式 */ public synchronized static CrashHandler getInstance(){ if(mCrashHandler == null){ mCrashHandler = new CrashHandler(); } return mCrashHandler; } public void init(Context context){ mContext = context; /** 获得系统默认的UncaughtException处理对象 */ mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); /** 设置mCrashHandler为该程序默认的 UncaughtException处理对象 */ Thread.setDefaultUncaughtExceptionHandler(this); } /** * 当UncaughtException发生时,会调用该方法 */ @Override public void uncaughtException(Thread thread, Throwable ex) { Log.d(TAG, "应用发生未知错误"); if(!handleException(ex) && mDefaultHandler != null){ // 如果用户自定义的mCrashHandler没有处理,则让系统默认的异常处理器来进行处理 mDefaultHandler.uncaughtException(thread, ex); }else{ // 3秒后退出程序 try { Thread.sleep(3000); } catch (InterruptedException e) { Log.e(TAG, "error : ", e); } Process.killProcess(Process.myPid()); System.exit(1); } } /** * 自定义错误处理、收集错误信息、发送错误报告 * @param ex * @return */ private boolean handleException(Throwable ex){ if(ex == null){ return false; } // 使用Toast来显示异常信息 new Thread(){ @Override public void run() { /** * 这里我们可以使用Toast简单的来显示异常后信息,也可以弹出对话框来显示 具体看项目的不同需求啦 */ Looper.prepare(); Toast.makeText(mContext, "很抱歉,程序出现异常,即将退出", Toast.LENGTH_LONG).show(); Looper.loop(); } }.start(); // 收集设备参数信息 collectDeviceInfo(mContext); // 保存日志文件 saveCrashInfo2File(ex,mContext); return true; } /** * 收集手机设备参数信息 * @param ctx */ private void collectDeviceInfo(Context ctx) { try { PackageManager pm = ctx.getPackageManager(); PackageInfo packageInfo = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES); if(packageInfo != null){ String versionName = packageInfo.versionName == null ? "null": packageInfo.versionName; String versionCode = packageInfo.versionCode + ""; Log.d(TAG, "versionName:"+versionName+" ,versionCode:"+versionCode); infos.put("versionName", versionName); infos.put("versionCode", versionCode); } } catch (NameNotFoundException e) { Log.e(TAG, "an error occured when collect package info", e); } } /** * 保存错误信息到本地sdCard上指定目录的日志文件 * @param ex * @param ctx * @return 返回文件名 便于将文件上传至服务器 */ private String saveCrashInfo2File(Throwable ex,Context ctx) { StringBuilder sb = new StringBuilder(); for(String keySet:infos.keySet()){ sb.append(keySet+"="+infos.get(keySet)+"\n"); } Writer writer = new StringWriter(); PrintWriter printWriter = new PrintWriter(writer); ex.printStackTrace(printWriter); Throwable cause = ex.getCause(); while(cause != null){ cause.printStackTrace(printWriter); cause = cause.getCause(); } printWriter.close(); String result = writer.toString(); sb.append(result); Log.d(TAG, sb.toString()); long timestamp = System.currentTimeMillis(); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); String time = sdf.format(new Date(timestamp)); String fileName = "crash_"+time+".log"; if(SdcardUtil.isSdcardWritable()){ String path = "/sdcard/"+ctx.getPackageName()+"/crash/"; Log.d(TAG, "crash path: "+path); try { File dir = new File(path); if (!dir.exists()) { dir.mkdirs(); } FileOutputStream fos = new FileOutputStream(path+fileName); fos.write(sb.toString().getBytes()); fos.close(); Log.d(TAG, "错误日志已保存在路径:"+path+fileName); return fileName; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } return null; } /** * 将错误日志信息上传到服务器 * @param file * @param url */ private void upLoadCrashInfo2Service(File file,String url){ } }
2、完成这个CrashHandler后,我们需要在一个Application环境中让其运行,为此,我们继承android.app.Application 在子类中<IceApplication>注册初始化CrashHandler。代码如下:
package com.ice.android; import com.ice.android.common.excepion.CrashHandler; import android.app.Application; /** * * @author ice * 参考博客:http://blog.csdn.net/liuhe688/article/details/6584143 */ public class IceApplication extends Application { @Override public void onCreate() { super.onCreate(); // 获得自定义的 未捕获异常处理器 CrashHandler mCrashHandler = CrashHandler.getInstance(); mCrashHandler.init(getApplicationContext()); } }
3、最后,为了让我们的IceApplication取代android.app.Application的地位,在我们的代码中生效,我们需要修改AndroidManifest.xml:
<application android:name=".IceApplication" ...> </application>
4、在代码中有遇到异常后要保存设备参数和具体异常信息到sdCard,所以我们需要在AndroidManifest.xml中加入读写SDCARD权限:
<!-- 写入SdCard卡权限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
5、运行项目、当应用遇到有未捕获的异常后 看到的效果如下:
同时在SDCARD上有生成的日志信息文件:
这些日志信息文件对于开发者来说是非常有帮助的。
最后感谢博客:http://blog.csdn.net/liuhe688/article/details/6584143 给我带来学习参考的内容。
相关文章推荐
- android应用开发-------------应用崩溃全局异常捕获处理(UncaughtExceptionHandler)
- Android处理应用崩溃异常并重启应用
- Android 如何处理崩溃的异常
- Android中处理崩溃异常
- Android 如何处理崩溃的异常
- Android 处理崩溃异常
- Android中处理崩溃异常和记录日志
- Android中处理崩溃异常
- Android中处理崩溃异常
- Android中处理崩溃异常
- Android 如何处理崩溃的异常
- Android中处理崩溃异常
- Android:处理程序崩溃异常
- Android中处理崩溃异常
- Android中处理崩溃异常,并提交
- Android中处理崩溃异常
- Android:处理程序崩溃异常
- Android中处理崩溃异常
- Android中处理崩溃异常
- Android中处理崩溃异常