CrashLog

异常处理类
javaThread中有一个UncaughtExceptionHandler接口,该接口的作用主要是为了
Thread 因未捕获的异常而突然终止时,调用处理程序。
 接口下面有setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
 方法,方法主要作用为设置当线程由于未捕获到异常而突然终止,并且没有为该线程定义其他处理程序时所调用的默认处理程序
 自定义系统的Crash捕捉类,用Toast替换系统的对话框
* 将软件版本信息,设备信息,出错信息保存在sd卡中,你可以上传到服务器中

(1)MyActivity类
package com.ncs.CustomCrash;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

public class MyActivity extends Activity {
    /**
     * 存在空指针异常
     * Called when the activity is first created.
     */
    TextView mTextView;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

//        mTextView.setText("crash");
    }
    public void tosubactivity(View v){
        Intent it = new Intent(this,SubActivity.class);
        Student data = new Student();
        it.putExtra("data",data);
        this.startActivity(it);
    }
}

(2)CrashApplication类
package com.ncs.CustomCrash;

import android.app.Application;

/**
 * Created by yeyy on 6/17/2015.
 */
public class CrashApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        CustomCrashHandler mCustomCrashHandler = CustomCrashHandler.getInstance();
        mCustomCrashHandler.setCustomCrashHanler(getApplicationContext());
    }
}
(3)CustomCrashHandler类
 
  
package com.ncs.CustomCrash;

import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;

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;

/**
 * Created by yeyy on 6/17/2015.
 */
/**
 * 异常处理类
 * java的Thread中有一个UncaughtExceptionHandler接口,该接口的作用主要是为了
 * 当 Thread 因未捕获的异常而突然终止时,调用处理程序。
 * 接口下面有setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
 * 方法,方法主要作用为设置当线程由于未捕获到异常而突然终止,并且没有为该线程定义其他处理程序时所调用的默认处理程序
 * 自定义系统的Crash捕捉类,用Toast替换系统的对话框
 * 将软件版本信息,设备信息,出错信息保存在sd卡中,你可以上传到服务器中
 */
public class CustomCrashHandler implements Thread.UncaughtExceptionHandler{
    private static final String TAG = "Activity";
    private Context mContext;//程序的context对象
    private static final String SDCARD_ROOT = Environment.getExternalStorageDirectory().toString();
    //CrashHandler实例
    private static CustomCrashHandler mInstance = new CustomCrashHandler();

    private CustomCrashHandler(){}
    /**
     * 单例模式,保证只有一个CustomCrashHandler实例存在
     * @return
     */
    public static CustomCrashHandler getInstance(){
        return mInstance;
    }
    /**
     * 异常发生时,系统回调的函数,我们在这里处理一些操作
     */
    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        //将一些信息保存到SDcard中
        savaInfoToSD(mContext, ex);

        //提示用户程序即将退出
        showToast(mContext, "很抱歉,程序遭遇异常,即将退出!");
        try {
            thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
//      android.os.Process.killProcess(android.os.Process.myPid());
//        System.exit(1);

        //完美退出程序方法
        ExitAppUtils.getInstance().exit();
    }
    /**
     * 为我们的应用程序设置自定义Crash处理
     */
    public void setCustomCrashHanler(Context context){
        mContext = context;
        Thread.setDefaultUncaughtExceptionHandler(this);
    }
    /**
     * 显示提示信息,需要在线程中显示Toast
     * @param context
     * @param msg
     */
    private void showToast(final Context context, final String msg){
        new Thread(new Runnable() {

            @Override
            public void run() {
                Looper.prepare();
                Toast.makeText(context, msg, Toast.LENGTH_LONG).show();
                Looper.loop();
            }
        }).start();
    }
    /**
     * 获取一些简单的信息,软件版本,手机版本,型号等信息存放在HashMap中
     * @param context
     * @return
     */
    private HashMap obtainSimpleInfo(Context context){
        HashMap map = new HashMap();
        PackageManager mPackageManager = context.getPackageManager();
        PackageInfo mPackageInfo = null;
        try {
            mPackageInfo = mPackageManager.getPackageInfo(context.getPackageName(), PackageManager.GET_ACTIVITIES);
        } catch (NameNotFoundException e) {
            e.printStackTrace();
        }

        map.put("versionName", mPackageInfo.versionName);
        map.put("versionCode", "" + mPackageInfo.versionCode);

        map.put("MODEL", "" + Build.MODEL);
        map.put("SDK_INT", "" + Build.VERSION.SDK_INT);
        map.put("PRODUCT", "" +  Build.PRODUCT);

        return map;
    }
    /**
     * 获取系统未捕捉的错误信息
     * @param throwable
     * @return
     */
    private String obtainExceptionInfo(Throwable throwable) {
        StringWriter mStringWriter = new StringWriter();
        PrintWriter mPrintWriter = new PrintWriter(mStringWriter);
        throwable.printStackTrace(mPrintWriter);
        mPrintWriter.close();

        Log.e(TAG, mStringWriter.toString());
        return mStringWriter.toString();
    }

    /**
     * 保存获取的 软件信息,设备信息和出错信息保存在SDcard中,但是看不到?
     * @param context
     * @param ex
     * @return
     */
    private String savaInfoToSD(Context context, Throwable ex){
        String fileName = null;
        StringBuffer sb = new StringBuffer();

        for (Map.Entry entry : obtainSimpleInfo(context).entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            sb.append(key).append(" = ").append(value).append("\n");
        }

        sb.append(obtainExceptionInfo(ex));

        if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
            File dir = new File(SDCARD_ROOT + File.separator + "crash" + File.separator);
            if(! dir.exists()){
                dir.mkdir();
            }

            try{
                fileName = dir.toString() + File.separator + paserTime(System.currentTimeMillis()) + ".log";
                FileOutputStream fos = new FileOutputStream(fileName);
                fos.write(sb.toString().getBytes());
                fos.flush();
                fos.close();
            }catch(Exception e){
                e.printStackTrace();
            }
        }
        return fileName;
    }
    /**
     * 将毫秒数转换成yyyy-MM-dd-HH-mm-ss的格式
     * @param milliseconds
     * @return
     */
    private String paserTime(long milliseconds) {
        System.setProperty("user.timezone", "Asia/Shanghai");
        TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai");
        TimeZone.setDefault(tz);
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
        String times = format.format(new Date(milliseconds));

        return times;
    }
}


(4)AndroidManifest.xml
 
  


    
    
    
    
        
            
                
                
            
        
        

    

(5)Layout文件


    

源码下载地址:http://download.csdn.net/detail/csdnyuandaimaxuexi/8968317

log文件的保存位置如图显示

你可能感兴趣的:(Android学习)