保存错误日志回传服务器之回传错误“信息文件”

主要源码:

package com.demo.uploaderrorinfofile.common;



import java.io.File;

import java.io.FileOutputStream;

import java.io.PrintWriter;

import java.lang.Thread.UncaughtExceptionHandler;

import java.util.ArrayList;

import java.util.Date;

import java.util.HashMap;

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.uploaderrorinfofile.Utils.FileNameUtils;

import com.demo.uploaderrorinfofile.Utils.FilePathUtils;

import com.demo.uploaderrorinfofile.Utils.HttpClientUpLoadTask;

import com.demo.uploaderrorinfofile.Utils.JsonUtils;

import com.demo.uploaderrorinfofile.Utils.PackageManagerUtils;



import android.content.Context;

//import android.content.pm.PackageInfo;

import android.text.format.DateFormat;

import android.util.Log;



/**

 * 在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);

        //得到错误信息所保存的文件的绝对路径

        String errorLogFilePath = this.saveToErrorLogFile(errorInfo);

        if(StringUtils.isNotBlank(errorLogFilePath)){

            Log.d(logTag, "error saved in file " + errorLogFilePath);

            

            //服务器的接口位置  yxg

//          String url = URLFactory.getInstance(this.context).getServicesURL().getUploadErrorLogURL();

              String url = "http://192.168.18.126:8080/test/upload";

            Map<String, Object> upLoadMsgFile=new HashMap<String, Object>();

            upLoadMsgFile.put("files",errorLogFilePath);

            

            //假如文件路径不为空,就将错误文件上传到服务器上

             HttpClientUpLoadTask uploadFileTask = new HttpClientUpLoadTask();

             uploadFileTask.execute(url,JsonUtils.toJson(upLoadMsgFile));

             

             String resultData;

             try {

                 resultData = uploadFileTask.get();

                 uploadFileCallBack(resultData, errorLogFilePath);

             } 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 String saveToErrorLogFile(String errorInfo){

        //错误文件的名字

        String fileName = CrashHandler.this.genErrorFileName();

        //错误文件的目录

        String fileDir = CrashHandler.this.getLogDir();

        try {

            File errorLogFile = new File(fileDir, fileName);

            

            Log.d(CrashHandler.logTag, String.format("save error file is:%s", errorLogFile.getAbsolutePath()));

            //将错误信息写到文件里面

            PrintWriter pw = new PrintWriter(new FileOutputStream(errorLogFile,true));

            pw.println(errorInfo);

            pw.flush();

            pw.close();

            //getAbsolutePath()得到绝对路径、全路径

            return errorLogFile.getAbsolutePath();

        } catch (Exception e) {

            Log.e(logTag, "write file error.", e);

        }

        

        return null;

    }

  //错误文件的目录

    private String getLogDir(){

        String logDir = FilePathUtils.getFilePath(this.context);

        try {

            File logDirFile = new File(logDir);

            if (!logDirFile.exists()) {

                logDirFile.mkdirs();

                Log.d(logTag, String.format("make dir success<%s>", logDirFile.getAbsolutePath()));

            }

            Log.d(logTag, String.format("log dir is:%s", logDirFile.getAbsolutePath()));

        } catch (Exception e) {

            Log.e(logTag, "make dir error.", e);

        }

        return logDir;

    }

    

    //将app的名字作为错误文件的名字(包含错误时间)

    private String genErrorFileName(){

        String fileName = PackageManagerUtils.getInstance(this.context).getAppName();

        fileName += "-";

        fileName += "error";

        fileName += "-";

        fileName += FileNameUtils.genFileNameByDateTime();//获取当前的时间

        fileName += ".log";

        

        return fileName;

    }

    

    //根据服务器返回值判定是否上传成功。(resultCode==0表示上传成功)

    private final void uploadFileCallBack(String resultData, String  errorLogFilePath ){

        if(StringUtils.isBlank(resultData) || StringUtils.isBlank( errorLogFilePath)){

            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){

            File f = new File( errorLogFilePath);

            if(f.exists()){

                f.delete();

                Log.d(logTag, "delete errorlog file ok. "+  errorLogFilePath);

            }else{

                Log.d(logTag, "errorlog file not exists. "+  errorLogFilePath);

            }

        }else{

            Log.d(logTag, "uploadFileCallBack resultCode=" + resultCode);

        }

    }

}

 

你可能感兴趣的:(服务器)