永不闪退的app

package com.emptech.nigeriafinancial.utils;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by xubaipei on 2017/2/21.
 * @function 全局异常捕获获取的日志文件路径为getExternalCacheDir的路径 /storage/sdcard0/Android/packageName/cache/error_log.txt
 */

public class CrashHandler implements Thread.UncaughtExceptionHandler {

    private static CrashHandler INSTANCE = new CrashHandler();

    private Context mContext = null;
    /**log tag; 日志标签**/
    private final String TAG = "error_log";

    /**log file name; 日志文件的文件名**/
    private final String mFileName = "error_log.txt";

    /***/
    private ExceptionHandler mExceptionHandler = null;

    Thread.UncaughtExceptionHandler mDefaultExceptionHandler = null;

    public static CrashHandler getInstance(){
        return INSTANCE;
    }

    /**
     * @param context
     * @functionsinit applicatin crash handler; 初始化应用异常处理
     */
    public void init(Context context) {
        this.mContext = context;
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                while (true){
                    try {
                        Looper.loop();
                    }catch (Exception e){
                        if (e instanceof ExitMessage){
                            break;
                        }
                        handleException(e);
                    }
                }
            }
        });

        mDefaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler(); // get default handler
        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    /**
     *
     * @param handler Exception handling by external inject 外部注入的异常处理;
     */
    public void setErrorHandler(ExceptionHandler handler){
        mExceptionHandler = handler;
    }

    /**
     * @functin: exit main crash; 退出主线程异常处理
     */
    public void exit(){
        Thread.setDefaultUncaughtExceptionHandler(this);

        new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                throw new ExitMessage();
            }
        });
    }


    private boolean handleException(Throwable e){
        if (e == null||mContext == null) {
            return false;
        }
        if (mExceptionHandler != null){
            mExceptionHandler.onError(e);
        }
        collectLog(e);
        return true;
    }

    private String collectLog(Throwable e){
        StackTraceElement[] elements = e.getStackTrace();
        StringBuilder sb = new StringBuilder();

        getPackagetInfo(sb);
        for (StackTraceElement element : elements){
            sb.append(element.toString()+"\n");
        }

        Log.e(TAG,sb.toString());
        uploadLog(saveLog(sb.toString()));
        return sb.toString();
    }

    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        if (!handleException(ex)&&mDefaultExceptionHandler != null){
            mDefaultExceptionHandler.uncaughtException(thread, ex);
        }
    }

    public void getPackagetInfo(StringBuilder sb){
        PackageInfo info = null;
        try {
            info = mContext.getPackageManager().getPackageInfo(
                    mContext.getPackageName(), 0);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace(System.err);
        }
        if (info == null)
            info = new PackageInfo();

        SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyy--HH:mm:ss");
        Date date = new Date(System.currentTimeMillis());
        String dateStr = format.format(date);
        sb.append("-------------------------------------------------------------------\n");
        sb.append("Version: " + info.versionName + "(" + info.versionCode + ")\n");
        sb.append("Android: " + Build.VERSION.RELEASE + "(" + Build.MODEL + ")\n");
        sb.append("Exception: " + info.toString()+ "\n");
        sb.append("Time: " + dateStr+ "\n");
    }

    /**
     *
     * @param log
     * @return
     */
    private File saveLog(String log){
        File file = new File(mContext.getExternalCacheDir(),mFileName);
        try {
            if (!file.exists()){
                file.getParentFile().mkdirs();
                file.createNewFile();
            }
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }

        try {
            FileInputStream inputStream = new FileInputStream(file);
            byte[] data = new byte[inputStream.available()];
            inputStream.read(data);
            log = new String(data)+"\n"+log;


            FileOutputStream fileWirter = new FileOutputStream(file);
            fileWirter.write(log.getBytes());
            fileWirter.flush();
            fileWirter.close();
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
        return file;
    }

    /**
     * @function log upload; 日志上传
     * @param file
     */
    public void uploadLog(File file) {
        //TODO upload bug log to server 上传日志文件到服务器
    }

    public interface ExceptionHandler{
        void onError(Throwable e);
    }

    private class ExitMessage extends RuntimeException{
        public ExitMessage() {
            super("daemon had been exit");
        }
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值