全局异常捕捉并上传log到服务器

来源:互联网 发布:淘宝为啥不能买彩票了 编辑:程序博客网 时间:2024/06/02 08:56

一个项目的完工后,我们也应给APP加上全局的异常捕捉,并将异常log上传到服务器。有些朋友可能会遇到这样的问题,异常是捕捉到了,但是还没等到上传到服务器上APP就挂了。下面我们一起来看一下我在应用中的使用。


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.ArrayList;import java.util.Date;import java.util.HashMap;import java.util.List;import java.util.Map;import org.apache.http.HttpEntity;import org.apache.http.HttpResponse;import org.apache.http.client.HttpClient;import org.apache.http.client.methods.HttpPost;import org.apache.http.entity.mime.HttpMultipartMode;import org.apache.http.entity.mime.MultipartEntityBuilder;import org.apache.http.entity.mime.content.FileBody;import org.apache.http.impl.client.DefaultHttpClient;import org.apache.http.params.BasicHttpParams;import org.apache.http.params.HttpConnectionParams;import org.apache.http.params.HttpParams;import org.apache.http.util.EntityUtils;import org.json.JSONObject;import android.app.AlarmManager;import android.app.PendingIntent;import android.content.Context;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.Environment;import android.os.Looper;import android.util.Log;import android.widget.Toast;import com.wish.becomeeasy.activity.MainActivity;import com.wish.becomeeasy.constant.Constant;import com.wish.becomeeasy.utils.MyUtils;/** *  * @类名称: CrashHandler.java * @创建人:Mr.ladeng (zbl704@yeah.net) * @创建时间: 2015-8-14下午1:22:15 * @修改备注:     * @version 1.0    * @类描述:捕捉全局异常类 *  * 在application类中onCreate下调用  *  *      CrashHandler crashHandler = CrashHandler.getInstance();   *      crashHandler.init(getApplicationContext());   *  */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 DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");private String path;        /** 证只有一个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(3000);              } catch (InterruptedException e) {                  Log.e(TAG, "error : ", e);              }              //退出程序              android.os.Process.killProcess(android.os.Process.myPid());              System.exit(1);          }      }        /**      * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.      *       * @param ex      * @return true:如果处理了该异常信息;否则返回false.      */      private boolean handleException(Throwable ex) {          if (ex == null) {              return false;          }          //收集设备参数信息           collectDeviceInfo(mContext);          //保存日志文件           String crashInfoFile = saveCrashInfo2File(ex);  //        String substring = crashInfoFile.substring(0, crashInfoFile.indexOf("."));//去后缀        final List<File> crashFile = new ArrayList<File>();        File file = new File(path+crashInfoFile);        crashFile.add(file);       Log.e(TAG, path+crashInfoFile);                //使用Toast来显示异常信息          new Thread() {              @Override              public void run() {                  Looper.prepare();                  MyUtils.showToast(mContext, "亲!让我休息一下吧!");                String uploadMessage = UploadMessage(CrashHandler.this, "crashExp" , crashFile );                if (uploadMessage.equals("success")) {                    Log.e(TAG, "上传日志成功!");}else {Log.e(TAG, "上传日志失败!");}                Looper.loop();              }          }.start();            Intent intent = new Intent(mContext , MainActivity.class);          PendingIntent restartIntent = PendingIntent.getActivity(mContext.getApplicationContext(), 0, intent, Intent.FLAG_ACTIVITY_NEW_TASK);                                                         //退出程序                                                  AlarmManager mgr = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);            mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000,  restartIntent); // 1秒钟后重启应用          // mContext.finishActivity();        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  返回文件名称,便于将文件传送到服务器      */      private String saveCrashInfo2File(Throwable ex) {                    StringBuffer sb = new StringBuffer();          for (Map.Entry<String, String> entry : infos.entrySet()) {              String key = entry.getKey();              String value = entry.getValue();              sb.append(key + "=" + value + "\n");          }                    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 {              long timestamp = System.currentTimeMillis();              String  time   = formatter.format(new Date());              String  fileName  = "crash-" + time + "-" + timestamp + ".log";              if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {                  path = "/sdcard/crash/";                  File dir = new File(path);                  if (!dir.exists()) {                      dir.mkdirs();                  }                  FileOutputStream fos = new FileOutputStream(path + fileName);                  fos.write(sb.toString().getBytes());                  fos.close();              }              return fileName ;          } catch (Exception e) {              Log.e(TAG, "an error occured while writing file...", e);          }          return null;      }          /*****************  把捕捉的异常发送给服务器  *********************/public  String UploadMessage(CrashHandler crashHandler,  String crashExp , List<File> files) {HttpParams connParams = new BasicHttpParams();HttpConnectionParams.setConnectionTimeout(connParams, 5 * 1000);HttpConnectionParams.setSoTimeout(connParams, 5 * 1000);HttpClient client = new DefaultHttpClient(connParams);/*** HttpClient client=new DefaultHttpClient();// 开启一个客户端 HTTP 请求**//** 创建 HTTP POST请求*//** 请求地址***/HttpPost post = new HttpPost("异常接口");MultipartEntityBuilder  builder = MultipartEntityBuilder.create();/** 设置浏览器兼容模式**/builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);/** 添加文件,添加的是实体内容 */for (File file : files) {/*** 把文件转换成流对象FileBody***/FileBody fileBody = new FileBody(file);builder.addPart("errorLog" , fileBody);}/*** 添加文本内容,后面要添加格式 ***///try {//builder.addPart("crashExp",new StringBody(crashExp, Charset.forName("UTF-8")));//} catch (UnsupportedEncodingException e1) {//e1.printStackTrace();//}/** 生成 HTTP POST 实体**/HttpEntity entity = builder.build();/** 设置请求参数***/post.setEntity(entity);try {/***client.execute(post);//发起请求 并返回请求的响应**/HttpResponse response = client.execute(post);if (response.getStatusLine().getStatusCode() == 200) {HttpEntity json  = response.getEntity();if (json != null) {String data  = EntityUtils.toString(json, "utf-8").trim();JSONObject  jsonObject = new JSONObject(data);String flag = jsonObject.getString("flag");if (flag.equals("1")) {return "success";}}}} catch (Exception e) {Log.e(TAG, e.getMessage());}return "";}}  


还是上代码比较实在。网上的异常捕捉类都差不多,我这个也是参考了别人的。另外优化了一下。并且添加了异常上传至服务器

1 0
原创粉丝点击