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


Android日志打印与处理 UncaughtExceptionHandler 提交服务器_第1张图片Android日志打印与处理 UncaughtExceptionHandler 提交服务器_第2张图片Android日志打印与处理 UncaughtExceptionHandler 提交服务器_第3张图片

第一:添加权限 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程序版本控制工具类
  2. Android调用系统自带的下载程序进行下载。
  3. Android API 28 访问服务器失败 提示CLEARTEXT
  4. Android AM命令行启动程序的方法
  5. 获取Android设备电池信息
  6. Android 程序退出的办法
  7. android4.3应用程序隐藏状态栏和标题栏
  8. android 利用 git 信息区分 apk 版本

随机推荐

  1. 那些你不知道的Android小事儿
  2. Android Gradle使用详解(三) 之 Android
  3. unable to access android sdk add-on li
  4. Android Studio(七)Android Studio 如何D
  5. android:layout_alignleft layout_tolefto
  6. Android常用设计模式(二)
  7. Android(安卓)单元测试和日志输出
  8. [置顶] android activity返回键被dialog
  9. Android应用启动后自动创建桌面快捷方式
  10. Android中的消息机制