• 获取Android崩溃crash信息并写入日志发送邮件


    一、实现Thread.UncaughtExceptionHandler
    UnChecked异常发生时,由于没有相应的try…catch处理该异常对象,所以Java运行环境将会终止,程序将退出,也就是我们所说的Crash。Java API提供了一个全局异常捕获处理器,Android应用在Java层捕获Crash依赖的就是Thread.UncaughtExceptionHandler处理器接口,通常我们只需实现这个接口,并重写其中的uncaughtException方法,在该方法中可以读取Crash的堆栈信息

    public class CrashManager implements Thread.UncaughtExceptionHandler {
    
    
        private Thread.UncaughtExceptionHandler mDefaultHandler;
        private Map<String, String> infos;
        private MyApplication application;
        private static SimpleDateFormat logfile = new SimpleDateFormat("yyyy-MM-dd");// 日志文件格式
    
    
        public CrashManager(MyApplication application){
            //获取系统默认的UncaughtExceptionHandler
            mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
            this.application = application;
        }
    
        private boolean handleException(final Throwable exc){
            if (exc == null) {
                return false;
            }
            new Thread(new Runnable() {
                @Override
                public void run() {
                    Looper.prepare();//准备
                    Log.i("Urmytch","崩溃正在写入日志");
                    flushBufferedUrlsAndReturn();
                    //处理崩溃
                    collectDeviceAndUserInfo(application);
                    writeCrash(exc);
                    Looper.loop();
                }
            }).start();
            return true;
        }
    
        /**
         * 把未存盘的url和返回数据写入日志文件
         */
        private void flushBufferedUrlsAndReturn(){
            //TODO 可以在请求网络时把url和返回xml或json数据缓存在队列中,崩溃时先写入以便查明原因
        }
    
        /**
         * 采集设备和用户信息
         * @param context 上下文
         */
        private void collectDeviceAndUserInfo(Context context){
            PackageManager pm = context.getPackageManager();
            infos = new HashMap<String, String>();
            try {
                PackageInfo pi = pm.getPackageInfo(context.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);
                    infos.put("crashTime",new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                }
            } catch (PackageManager.NameNotFoundException e) {
                Log.e("Urmytch",e.getMessage());
            }
            Field[] fields = Build.class.getDeclaredFields();
            try {
                for (Field field : fields) {
                    field.setAccessible(true);
                    infos.put(field.getName(), field.get(null).toString());
                }
            } catch (IllegalAccessException e) {
                Log.e("Urmytch",e.getMessage());
            }
        }
    
        /**
         * 采集崩溃原因
         * @param exc 异常
         */
    
        private void writeCrash(Throwable exc){
            StringBuffer sb = new StringBuffer();
            sb.append("------------------crash----------------------");
            sb.append("
    ");
            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 pw = new PrintWriter(writer);
            exc.printStackTrace(pw);
            Throwable excCause = exc.getCause();
            while (excCause != null) {
                excCause.printStackTrace(pw);
                excCause = excCause.getCause();
            }
            pw.close();
            String result = writer.toString();
            sb.append(result);
            sb.append("
    ");
            sb.append("-------------------end-----------------------");
            sb.append("
    ");
            if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
            {
                String sdcardPath = Environment.getExternalStorageDirectory().getPath();
                Log.i("路径:",""+Environment.getExternalStorageDirectory().getPath());
                //String filePath = sdcardPath + "//Urmytch/crash/";
                String filePath = sdcardPath + "//kantu/crash/";
                writeLog(sb.toString(), filePath);
    
    
            }
        }
        /**
         *
         * @param log 文件内容
         * @param name 文件路径
         * @return 返回写入的文件路径
         * 写入Log信息的方法,写入到SD卡里面
         */
        private String writeLog(String log, String name)
        {
            Date nowtime = new Date();
            String needWriteFiel = logfile.format(nowtime);
            //String filename = name + "mycrash"+ ".log";
            String filename = name + "mycrash"+ needWriteFiel+".txt";
            File file =new File(filename);
            if(!file.getParentFile().exists()){
                Log.i("Urmytch","新建文件");
                file.getParentFile().mkdirs();
            }
            if (file != null && file.exists() && file.length() + log.length() >= 64 * 1024) {
                //控制日志文件大小
                file.delete();
            }
            try
            {
                file.createNewFile();
                FileWriter fw=new FileWriter(file,true);
                BufferedWriter bw = new BufferedWriter(fw);
                //写入相关Log到文件
                bw.write(log);
                bw.newLine();
                bw.close();
                fw.close();
                //发送邮件
                SendMailUtil.send(file,"changyiqiang123@126.com");
                return filename;
            }
            catch(IOException e)
            {
                Log.w("Urmytch",e.getMessage());
                return null;
            }
    
    
        }
        @Override
        public void uncaughtException(Thread thread, Throwable exc) {
            if(!handleException(exc) && mDefaultHandler != null){
                //如果用户没有处理则让系统默认的异常处理器来处理
                mDefaultHandler.uncaughtException(thread, exc);
                Log.i("打印:","1111");
            }else{
                Log.i("打印:","222");
    
                try{
                    Thread.sleep(2000);
                }catch (InterruptedException e){
                    Log.w("Urmytch",e.getMessage());
                }
                Intent intent = new Intent(application.getApplicationContext(), LoginActivity.class);
                PendingIntent restartIntent = PendingIntent.getActivity(application.getApplicationContext(), 0, intent, 0);
                //退出程序
                AlarmManager mgr = (AlarmManager)application.getSystemService(Context.ALARM_SERVICE);
                //1秒后重启应用
                mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, restartIntent);
                android.os.Process.killProcess(android.os.Process.myPid());
            }
    
    
            ////这里可以上传异常信息到服务器,便于开发人员分析日志从而解决Bug
            //        uploadExceptionToServer();
        }
    
    
        /**
         * 将错误信息上传至服务器
         */
        private void uploadExceptionToServer() {
            File file = new File(Environment.getExternalStorageDirectory()+File.separator+"test.txt");
            OutputStream os = null;
            try {
                os = new FileOutputStream(file);
                String str = "hello world";
                byte[] data = str.getBytes();
                os.write(data);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }finally{
                try {
                    if (os != null)os.close();
                } catch (IOException e) {
                }
            }
            SendMailUtil.send(file,"changyiqiang123@126.com");
        }
    
    }
    

      

    二、在Application中注册

    public class MyApplication extends Application {
        @Override
        public void onCreate() {
            super.onCreate();
            CrashManager crashHandler = new CrashManager(this);
            Thread.setDefaultUncaughtExceptionHandler(crashHandler);
        }
    }
    

    最后权限:

    <uses-permission android:name="android.permission.INTERNET"/>
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    

      

      完成 

    参考于:https://blog.csdn.net/urmytch/article/details/53642945

  • 相关阅读:
    java集合 (hashmap,hashtable,list,set)
    struts2+hibernate+spring 事物控制
    eclipse 添加xml文件提示功能
    myeclipse 快捷键 收藏
    设置ORACLE客户端字符集
    批处理删除文件夹
    java作用域public,private,protected ,default区别
    CCV所用资料资源汇总
    总序
    数字图像处理第一次作业
  • 原文地址:https://www.cnblogs.com/changyiqiang/p/11224971.html
Copyright © 2020-2023  润新知