Android日志打印与处理 UncaughtExceptionHandler 提交服务器



第一:添加权限 sd卡读写权限

    <!-- 从SDCard读取数据权限 -->    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />    <!-- 往SDCard写入数据权限 -->    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

第二:注册App extends Application

 <application        android:name="com.ui.app.App"

第三:创建CrashHandler

package com.ui.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.Date;import java.util.HashMap;import java.util.Map;import android.content.Context;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;/** * UncaughtException处理类,当程序发生Uncaught异常的时候,有该类来接管程序,并记录发送错误报告. *  * @author user *  */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");/** 保证只有一个CrashHandler实例 */private static class UCrashHandler {private final static CrashHandler CRASH_HANDLER = new CrashHandler();}/** 获取CrashHandler实例 ,单例模式 */public static CrashHandler getInstance() {return UCrashHandler.CRASH_HANDLER;}/** * 初始化 *  * @param context */public void init(Context context) {mContext = context;// 获取系统默认的UncaughtException处理器mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();// 设置该CrashHandler为程序的默认处理器Thread.setDefaultUncaughtExceptionHandler(this);}/** * 当UncaughtException发生时会转入该函数来处理 */@Overridepublic 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;}// 使用Toast来显示异常信息new Thread() {@Overridepublic void run() {Looper.prepare();Toast.makeText(mContext, "很抱歉,程序出现异常,即将退出.", Toast.LENGTH_LONG).show();Looper.loop();}}.start();<span style="color:#990000;">// 收集设备参数信息</span>collectDeviceInfo(mContext);<span style="color:#990000;">// 保存日志文件</span>saveCrashInfo2File(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 返回文件名称,便于将文件传送到服务器 */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)) {String path = "/sdcard/crash/";<span style="color:#CC0000;">// 日志文件路径</span>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;}}
第四:App调用

package com.ui.app;import java.util.ArrayList;import java.util.List;import com.android.volley.Request;import com.android.volley.RequestQueue;import com.android.volley.toolbox.ImageLoader;import com.android.volley.toolbox.Volley;import com.ui.image.LruBitmapCache;import android.app.Activity;import android.app.Application;import android.content.Context;import android.text.TextUtils;public class App extends Application {public static final String TAG = App.class.getSimpleName();private RequestQueue mRequestQueue;private ImageLoader mImageLoader;private List<Activity> mainActivity = new ArrayList<Activity>();private static class UApp {private final static App APP = new App();}public final static synchronized App getInstance() {return UApp.APP;}<span style="color:#CC0000;">@Overridepublic void onCreate() {// TODO Auto-generated method stubsuper.onCreate();CrashHandler.getInstance().init(getApplicationContext());}</span>/** * @return instance of the queue * @throws IllegalStatException *             if init has not yet been called */public RequestQueue getRequestQueue(Context context) {if (mRequestQueue != null) {return mRequestQueue;} else {mRequestQueue = Volley.newRequestQueue(context);return mRequestQueue;}}public ImageLoader getImageLoader(Context context) {if (mImageLoader == null) {mImageLoader = new ImageLoader(getRequestQueue(context), new LruBitmapCache());}return mImageLoader;}public <T> void addToRequestQueue(Context context, Request<T> req, String tag) {req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);getRequestQueue(context).add(req);}public <T> void addToRequestQueue(Context context, Request<T> req) {req.setTag(TAG);getRequestQueue(context).add(req);}public void cancelPendingRequests(Object tag) {if (mRequestQueue != null) {mRequestQueue.cancelAll(tag);}}public void addActivity(Activity act) {if (mainActivity != null) {mainActivity.add(act);} else {mainActivity = new ArrayList<Activity>();mainActivity.add(act);}}public void removeActivity(Activity act) {if (mainActivity != null && mainActivity.size() != 0) {if (mainActivity.contains(act)) {mainActivity.remove(act);}}}public void finishAll() {if (mainActivity != null) {for (Activity act : mainActivity) {if (!act.isFinishing()) {act.finish();// 从虚拟机中清掉这个应用的所有信息System.exit(0);}}}mainActivity = null;}}
写到这大家往服务器提交也应该会吧,只需在下一次打开软件时写个文件上传服务器就可以了


更多相关文章

  1. Android兼容android7.0、及Android8.0以上apk安装权限问题(二)
  2. Android菜鸟的成长笔记(11)——Android中的事件处理
  3. Android(安卓)为【apk】文件签名,增加修改系统时间等权限
  4. Android(安卓)的提权 (root) 原理是什么?
  5. 《Android面试宝典》学习笔记(第四章:对话框、信息提示和菜单)
  6. Android之权限管理
  7. Android开机广播和关机广播
  8. Android(安卓)Shell命令dumpsys
  9. 基于Apache mina 的android 客户端tcp长连接实现

随机推荐

  1. android相机调试
  2. Gradle-jar-aar
  3. android中ColorStateList及StateListDraw
  4. Android进阶之代码应用技巧
  5. Android(安卓)GPS架构分析
  6. 4种必须知道的Android屏幕自适应解决方案
  7. Android(安卓)TextView字体颜色等样式详
  8. Android(安卓)Sqlite Failed to open dat
  9. 做android 开发遇到的问题及解决办法记录
  10. Android(安卓)主动获取电量的方法