zoukankan      html  css  js  c++  java
  • 保存错误日志回传服务器之回传错误“信息”

    近期领导交给我个任务,即已经上线的一个android产品出现Bug,但只是个别手机出现Bug,主流手机都没事,但是我们不可能把所有出现问题的手机都搜集过来测试开发(实际上出现问题的手机都比较难拿到机型,例如:红米定制版,索尼等),因此只能想个办法:在项目中加上保存错误日志,并将错误信息回传到服务器的方法,然后通过错误日志分析Bug,因此我在参考了网上的一些解决方案后,自己修改写了两种方式:一、直接将错误信息+手机信息发送到服务器  二、将错误信息+手机信息保存到一个文件,将文件上传到服务器。不过说实话,这些还没试验过,不知道能不能用,暂且先写出来,以后有问题再修改:

    参考文章:

    1.http://www.jb51.net/article/41112.htm

    2.http://www.cnblogs.com/stay/archive/2011/07/21/2113167.html

    3.http://onewayonelife.iteye.com/blog/1147533

    4.http://chenkechao123.blog.163.com/blog/static/1383326482012924238251/

    源码:

    package com.demo.uploaderrorinfo.common;
    
    import java.lang.Thread.UncaughtExceptionHandler;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;
    import java.util.Map;
    
    import org.apache.commons.collections.MapUtils;
    import org.apache.commons.collections.map.CaseInsensitiveMap;
    import org.apache.commons.lang.StringUtils;
    
    import com.demo.uploaderrorinfo.Utils.HttpClientUpLoadTask;
    import com.demo.uploaderrorinfo.Utils.JsonUtils;
    import com.demo.uploaderrorinfo.Utils.PackageManagerUtils;
    
    import android.content.Context;
    //import android.content.pm.PackageInfo;
    import android.text.format.DateFormat;
    import android.util.Log;
    
    /**
     * @author LHG<br/>
     * 在Application中统一捕获异常,并上传到服务器上
     * 自定义异常类实现UncaughtExceptionHandler接口,当某个页面出现
     * 异常就会调用uncaughtException这个方法,我们可以在这个方法中获取
     * 异常信息、时间等,然后将获取到的信息发送到我们指定的服务器
     */
    public class CrashHandler implements UncaughtExceptionHandler {
        private static final String logTag = CrashHandler.class.getSimpleName();
    //    private PackageInfo packageInfo;
        
        /** 系统默认的UncaughtException处理类 */ 
        private Thread.UncaughtExceptionHandler defaultHandler;
        
        /** CrashHandler实例 */ 
        private static CrashHandler INSTANCE;
        
        /** 程序的Context对象 */ 
        private Context context;
        
        /** 保证只有一个CrashHandler实例 */ 
        private CrashHandler() {}  
        
        /** 获取CrashHandler实例 ,单例模式*/ 
        public static CrashHandler getInstance() {  
            if (INSTANCE == null) {  
                INSTANCE = new CrashHandler();  
            }
            
            return INSTANCE;  
        }  
       
        /** 
         * 初始化,注册Context对象, 
         * 获取系统默认的UncaughtException处理器, 
         * 设置该CrashHandler为程序的默认处理器 
         *  
         * @param ctx 
         */ 
        public void register(Context ctx) {  
            this.context = ctx;  
            
            //获取默认的handler
            defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
            
            //设置自己的handler
            Thread.setDefaultUncaughtExceptionHandler(this);  
        }  
       
        /** 
         * 当UncaughtException发生时会转入该函数来处理 
         */ 
        @Override 
        public void uncaughtException(Thread thread, Throwable ex) {
            Log.d(logTag, "Now enter CrashHandler. In somewhere occur error. I try to save the error.");
            boolean isProcessed = handleException(thread, ex);
            
            if (!isProcessed && defaultHandler != null) {  
                //如果用户没有处理则让系统默认的异常处理器来处理  
                defaultHandler.uncaughtException(thread, ex);  
            } else {
                //如果自己处理了异常,则不会弹出错误对话框,则需要手动退出程序
                try {  
                    Thread.sleep(3000);
                } catch (InterruptedException e) {  
                }
                //干掉自己
                android.os.Process.killProcess(android.os.Process.myPid());
                //退出程序
                System.exit(10);  
            }  
        }  
       
        /** 
         * 自定义错误处理,收集错误信息 
         * 发送错误报告等操作均在此完成. 
         * true代表处理该异常,不再向上抛异常,
         * false代表不处理该异常(可以将该log信息存储起来)然后交给上层(这里就到了系统的异常处理)去处理,
         * 简单来说就是true不会弹出那个错误提示框,false就会弹出
         */ 
        private boolean handleException(final Thread thread, final Throwable ex) {        
            if (ex == null) {
                Log.d(logTag, "no exception info.");
                return false;  
            }
            //得到详细的错误信息
            final String errorInfo = this.getErrorInfo(ex);
            Log.d(logTag, errorInfo);
            
            if(StringUtils.isNotBlank(errorInfo)){
                Log.d(logTag, "error saved in file " + errorInfo);
    
                
                //服务器的接口
    //            String url = URLFactory.getInstance(this.context).getServicesURL().getUploadErrorLogURL();
                String url = "http://192.168.18.126:8080/test/upload";
                //将保存的错误信息上传到服务器
                HttpClientUpLoadTask uploadFileTask = new HttpClientUpLoadTask();
                uploadFileTask.execute(url, errorInfo);
                
                String resultData;
                try {
                    resultData = uploadFileTask.get();
                    uploadFileCallBack(resultData);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                
            }
            
            return false;
        }
        
        //获取详细的错误信息、应用程序的信息、手机型号版本
        private String getErrorInfo(Throwable ex) {
            List<String> errorContents = new ArrayList<String>();
            StackTraceElement[] sts = ex.getStackTrace();//获取错误代码的位置和信息
            if(null != sts){
                for(StackTraceElement st : sts){
                    if(null != st && null != st.toString()){
                        errorContents.add(st.toString());
                    }
                }
            }
            
            @SuppressWarnings("unchecked")
            Map<String,Object> errorInfoMap = new CaseInsensitiveMap();
            //发生错误的时间
            errorInfoMap.put("errortime", DateFormat.format("yyyy-MM-dd kk:mm:ss", new Date(System.currentTimeMillis())));
            //手机型号
            errorInfoMap.put("phonetype", android.os.Build.MODEL);
            errorInfoMap.put("androidsdkversion", android.os.Build.VERSION.SDK);
            errorInfoMap.put("androidreleaseversion", android.os.Build.VERSION.RELEASE);
            String localVersion =PackageManagerUtils.getInstance(this.context).getVersionName();
            errorInfoMap.put("appversion", localVersion);
            errorInfoMap.put("errormessage", ex.getMessage());
            errorInfoMap.put("errorcontent", errorContents); //上面得到的错误信息 (String)
            
            return JsonUtils.toJson(errorInfoMap);  
        }
        
        private final void uploadFileCallBack(String resultData){
            if(StringUtils.isBlank(resultData) ){
                Log.d(logTag, "uploadFileCallBack occur error.");
                return;
            }
            Log.d(logTag, "uploadFileCallBack receive resultData: "+ resultData);
            Map resultMap = JsonUtils.fromJsonToCaseInsensitiveMap(resultData);
            int resultCode = MapUtils.getIntValue(resultMap, "resultCode", -1);
            if(0 == resultCode){
                Log.d(logTag, "successful. ");
            }else{
                Log.d(logTag, "false ");
            }
            
    }
    }

    这些是主要的源码,一些辅助性的代码和项目文件等我学会怎么上传博客中后,就直接放项目了! 

       下面一篇文章是介绍怎么把 “错误信息和手机信息保存成文件上传服务器”的源码

    我是刚刚进入公司的Android实习生,菜鸟一枚,博客记录我犯过的错,收获的东西,学到的知识和技术,可能里面会有很多错误的地方,幼稚的地方,欢迎大家指出来,帮助我进步,但请别伤害我,我只是菜鸟一枚,我在努力争取进步。
  • 相关阅读:
    关于oracle小数和整数混合排序错误问题
    oracle 格式转换 <行转列列转行>
    Postgresql 配置文件详解
    Postgresql 同步流复制
    Postgresql 安装
    mongodb 复制集 维护小结
    mongodb 角色总结
    mongodb 安全认证
    SqlServer实时数据同步到mysql
    批量修改在索引中增加字段
  • 原文地址:https://www.cnblogs.com/smilefortoday/p/3974475.html
Copyright © 2011-2022 走看看