zoukankan      html  css  js  c++  java
  • 捕android程序崩溃日志

    主要类别:

    package com.example.callstatus;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.PrintWriter;
    import java.io.StringWriter;
    import java.lang.Thread.UncaughtExceptionHandler;
    import java.lang.reflect.Field;
    import java.net.UnknownHostException;
    import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Map;
    
    import android.annotation.SuppressLint;
    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.telephony.TelephonyManager;
    import android.text.TextUtils;
    import android.util.Log;
    import android.widget.Toast;
    
    /**
     * 捕获android程序崩溃日志<br>
     * UncaughtException处理类,当程序发生Uncaught异常的时候,有该类来接管程序.
     * 
     * @author PMTOAM
     * 
     */
    @SuppressLint("SimpleDateFormat")
    public class CrashHandler implements UncaughtExceptionHandler
    {
    
    	public static final String TAG = CrashHandler.class.getCanonicalName();
    
    	// 系统默认的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("yyyyMMdd_HHmmss");
    
    	/**
    	 * 保证仅仅有一个实例
    	 */
    	private 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;
    		}
    
    		// 使用Toast来显示异常信息
    		new Thread()
    		{
    			@Override
    			public void run()
    			{
    				Looper.prepare();
    				Toast.makeText(mContext, "非常抱歉。程序出现异常。

    ", Toast.LENGTH_LONG) .show(); Looper.loop(); } }.start(); // 收集设备參数信息 collectDeviceInfo(mContext); // 保存日志文件 String str = saveCrashInfo2File(ex); Log.e(TAG, str); return false; } /** * 收集设备參数信息 * * @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 返回文件名称称,便于将文件传送到server */ 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 + "] "); } sb.append(" " + getStackTraceString(ex)); try { String time = formatter.format(new Date()); TelephonyManager mTelephonyMgr = (TelephonyManager) mContext .getSystemService(Context.TELEPHONY_SERVICE); String imei = mTelephonyMgr.getDeviceId(); if (TextUtils.isEmpty(imei)) { imei = "unknownimei"; } String fileName = "CRS_" + time + "_" + imei + ".txt"; File sdDir = null; if (Environment.getExternalStorageState().equals( android.os.Environment.MEDIA_MOUNTED)) sdDir = Environment.getExternalStorageDirectory(); File cacheDir = new File(sdDir + File.separator + "dPhoneLog"); if (!cacheDir.exists()) cacheDir.mkdir(); File filePath = new File(cacheDir + File.separator + fileName); FileOutputStream fos = new FileOutputStream(filePath); 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 static String getStackTraceString(Throwable tr) { if (tr == null) { return ""; } Throwable t = tr; while (t != null) { if (t instanceof UnknownHostException) { return ""; } t = t.getCause(); } StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); tr.printStackTrace(pw); return sw.toString(); } }



    用法:


    package com.example.callstatus;
    
    import android.app.Application;
    
    public class MyApplication extends Application
    {
    	@Override
    	public void onCreate()
    	{
    		super.onCreate();
    		
    		CrashHandler crashHandler = CrashHandler.getInstance();
    		crashHandler.init(getApplicationContext());
    	}
    }
    


    所需权限:


    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />


    版权声明:本文博主原创文章。博客,未经同意不得转载。

  • 相关阅读:
    JSP学习
    Maven
    Android开发环境搭建
    Java Spring MVC
    you don't know js -- Scope and Closures学习笔记——第五章(闭包) 下篇
    you don't know js -- Scope and Closures学习笔记——第五章(闭包) 上篇
    you don't know js -- Scope and Closures学习笔记——第四章(声明提升 Hoisting)
    you don't know js -- Scope and Closures学习笔记——第三章(函数VS块作用域)
    you don't know js -- Scope and Closures学习笔记——第二章(词法作用域)
    you don't know js -- Scope and Closures学习笔记——第一章(什么是作用域)
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/4876932.html
Copyright © 2011-2022 走看看