• Android开发之处理崩溃异常


    众所周知,android的设备千差万别,难免会发生崩溃异常等现象,这个时候就需要捕获哪些崩溃异常了,也就是捕获崩溃异常的相关信息,并记录下来,这样一来方便开发人员和测试人员的分析与调试。

    1.首先我们得创建一个处理崩溃异常的类,暂且命名为:CrashHandler吧。实现如下:

     
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.PrintWriter;
    import java.io.StringWriter;
    import java.io.Writer;
    import java.lang.Thread.UncaughtExceptionHandler;
    import java.lang.reflect.Field;
    import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.TimeZone;
    
    
    
    import android.app.Activity;
    import android.app.AlertDialog;
    import android.content.Context;
    import android.content.DialogInterface;
    import android.content.DialogInterface.OnClickListener;
    import android.content.Intent;
    import android.content.pm.PackageInfo;
    import android.content.pm.PackageManager;
    import android.content.pm.PackageManager.NameNotFoundException;
    import android.os.Build;
    import android.os.Looper;
    import android.sax.StartElementListener;
    import android.util.Log;
    import android.widget.Toast;
    
    /**
     * UncaughtException处理类,当程序发生Uncaught异常的时候,有该类来接管程序,并记录发送错误报告到log文件中.
     *
     * @author caizhiming 
     */
    public class CrashHandler implements UncaughtExceptionHandler {
    
        public static final String TAG = "CrashHandler";
    
        // 系统默认的UncaughtException处理类
        private Thread.UncaughtExceptionHandler mDefaultHandler;
        // CrashHandler实例
        private static CrashHandler INSTANCE = new CrashHandler();
        // 程序的Context对象
        private Context mContext;
        // 用来存储设备信息和异常信息
        private Map<String, String> infos = new HashMap<String, String>();
    
        // 用于格式化日期,作为日志文件名的一部分
        private SimpleDateFormat formatter;
    
        /**
         * 保证只有一个CrashHandler实例
         */
        private CrashHandler() {
        }
    
        /**
         * 获取CrashHandler实例 ,单例模式
         */
        public static CrashHandler getInstance() {
            return INSTANCE;
        }
    
        /**
         * 初始化
         *
         * @param context
         */
        public void init(Context context) {
            mContext = context;
            // 获取系统默认的UncaughtException处理器
            mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
            // 设置该CrashHandler为程序的默认处理器
            Thread.setDefaultUncaughtExceptionHandler(this);
        }
    
        /**
         * 当UncaughtException发生时会转入该函数来处理
         */
        @Override
        public void uncaughtException(Thread thread, Throwable ex) {
            if (!handleException(ex) && mDefaultHandler != null) {
                // 如果用户没有处理则让系统默认的异常处理器来处理
                mDefaultHandler.uncaughtException(thread, ex);
            } else {
                // 退出程序
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                android.os.Process.killProcess(android.os.Process.myPid());
                System.exit(1);
            }
        }
    
        /**
         * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
         *
         * @param ex
         * @return true:如果处理了该异常信息;否则返回false.
         */
        private boolean handleException(final Throwable ex) {
            if (ex == null) {
                return false;
            }
    
    //        Intent showcrashDLg = new Intent(mContext,CrashActivity.class);
    //        mContext.startActivity(showcrashDLg);
    
            ex.printStackTrace();
            // 使用Toast来显示异常信息
    
    
            // 收集设备参数信息
            collectDeviceInfo(mContext);
    
    
            // 保存日志文件
            saveCrashInfoToFile(ex);
    
            return true;
        }
    
        /**
         * 收集设备参数信息
         *
         * @param ctx
         */
        public void collectDeviceInfo(Context ctx) {
            try {
                PackageManager pm = ctx.getPackageManager();
                PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(),
                        PackageManager.GET_ACTIVITIES);
                if (pi != null) {
                    String versionName = pi.versionName == null ? "null"
                            : pi.versionName;
                    String versionCode = pi.versionCode + "";
                    infos.put("versionName", versionName);
                    infos.put("versionCode", versionCode);
                }
            } catch (NameNotFoundException e) {
                Log.e(TAG, "an error occured when collect package info", e);
            }
            Field[] fields = Build.class.getDeclaredFields();
            for (Field field : fields) {
                try {
                    field.setAccessible(true);
                    infos.put(field.getName(), field.get(null).toString());
                    Log.d(TAG, field.getName() + " : " + field.get(null));
                } catch (Exception e) {
                    Log.e(TAG, "an error occured when collect crash info", e);
                }
            }
        }
    
        /**
         * 保存错误信息到文件中
         *
         * @param ex
         * @return 错误崩溃信息写到log文件中
         */
        private void saveCrashInfoToFile(Throwable ex) {
            StringBuffer sb = new StringBuffer();
            sb.append("==============================Crash happened at Time:"
                    + CommonUtils.getCurTime()
                    + "==============================
    ");
            for (Map.Entry<String, String> entry : infos.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                sb.append(key + "=" + value + "
    ");
            }
    
    
            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);
            try {
                LogCore.addLog(sb.toString());
    
            } catch (Exception e) {
                Log.e(TAG, "an error occured while writing file...", e);
            }
            Analyse.uplodcrash(sb.toString());
    
        }
    
        /**
         * 用Dialog显示错误信息
         *
         * @param ex
         * @return 用Dialog显示错误信息
         */
        private void showCrashInfoDialog(Throwable ex) {
    
            StringBuffer sb = new StringBuffer();
    
            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);
            try {
                // DlgUtils.ShowDialog(mContext,"程序崩溃了");
                // LogCore.d(mContext,sb.toString());
                AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
                builder.setTitle("程序崩溃啦~");
                builder.setMessage(sb.toString());
                builder.setPositiveButton("我知道了", new OnClickListener() {
    
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        // TODO Auto-generated method stub
                        android.os.Process.killProcess(android.os.Process.myPid());
                        System.exit(1);
                    }
                });
    //            builder.create().show();
            } catch (Exception e) {
                Log.e(TAG, "an error occured while writing file...", e);
            }
        }
    
    }

    2.完成这个CrashHandler后,我们需要在一个Application环境中让其运行,为此,我们继承android.app.Application,添加自己的代码,CrashApplication.java代码如下:

    package com.czm.crash;  
      
    import android.app.Application;  
      
    public class CrashApplication extends Application {  
        @Override  
        public void onCreate() {  
            super.onCreate();  
            CrashHandler crashHandler = CrashHandler.getInstance();  
            crashHandler.init(getApplicationContext());  
        }  
    }  

    3.除此之外,最后,为了让上面的CrashApplication取代android.app.Application的地位,在我们的代码中生效,我们需要修改AndroidManifest.xml:

    <application android:name=".CrashApplication" ...>  
    </application> 
  • 相关阅读:
    chm文件生成
    java基础--集合
    java基础--多线程
    nexus
    java基础--IO流
    http与https
    java基础--数据结构
    mysql 优化
    maven依赖和传递
    java设计模式
  • 原文地址:https://www.cnblogs.com/JczmDeveloper/p/3848275.html
Copyright © 2020-2023  润新知