zoukankan      html  css  js  c++  java
  • 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> 
  • 相关阅读:
    BZOJ 1391: [Ceoi2008]order
    BZOJ 4504: K个串
    2019 年百度之星·程序设计大赛
    POJ 2398 Toy Storage (二分 叉积)
    POJ 2318 TOYS (二分 叉积)
    HDU 6697 Closest Pair of Segments (计算几何 暴力)
    HDU 6695 Welcome Party (贪心)
    HDU 6693 Valentine's Day (概率)
    HDU 6590 Code (判断凸包相交)
    POJ 3805 Separate Points (判断凸包相交)
  • 原文地址:https://www.cnblogs.com/JczmDeveloper/p/3848275.html
Copyright © 2011-2022 走看看