Android 捕捉app崩潰信息,友好的提示用戶應用發生故障。

每個應用在所難免會有bug,崩潰的時候一閃而過,這樣的話交互非常的差。在此,我為大家介紹一種捕捉崩潰信息,并且友好的提示用戶的方式。
Thread類中有這樣一個函數

/**
     * Set the default handler invoked when a thread abruptly terminates
     * due to an uncaught exception, and no other handler has been defined
     * for that thread.
     *
     * <p>Uncaught exception handling is controlled first by the thread, then
     * by the thread's {@link ThreadGroup} object and finally by the default
     * uncaught exception handler. If the thread does not have an explicit
     * uncaught exception handler set, and the thread's thread group
     * (including parent thread groups)  does not specialize its
     * <tt>uncaughtException</tt> method, then the default handler's
     * <tt>uncaughtException</tt> method will be invoked.
     * <p>By setting the default uncaught exception handler, an application
     * can change the way in which uncaught exceptions are handled (such as
     * logging to a specific device, or file) for those threads that would
     * already accept whatever "default" behavior the system
     * provided.
     *
     * <p>Note that the default uncaught exception handler should not usually
     * defer to the thread's <tt>ThreadGroup</tt> object, as that could cause
     * infinite recursion.
     *
     * @param eh the object to use as the default uncaught exception handler.
     * If <tt>null</tt> then there is no default handler.
     *
     * @throws SecurityException if a security manager is present and it
     *         denies <tt>{@link RuntimePermission}
     *         ("setDefaultUncaughtExceptionHandler")</tt>
     *
     * @see #setUncaughtExceptionHandler
     * @see #getUncaughtExceptionHandler
     * @see ThreadGroup#uncaughtException
     * @since 1.5
     */
    public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
         defaultUncaughtExceptionHandler = eh;
     }

通過注釋我們可以看出這個函數是用于設置當線程由于未捕獲的異常突然終止而調用的默認處理程序,下面我們通過代碼來熟知這個函數的作用。
我們先定義一個CrashHandler類,這個類實現Thread.UncaughtExceptionHandler接口,重寫uncaughtException方法來捕捉未處理的異常信息并通過Log打印出來。代碼如下:

  package com.zzw.TestCrashHandler;

import android.util.Log;

/**
 * Created by zzw on 2017/4/28.
 */

public class CrashHandler implements Thread.UncaughtExceptionHandler {

    private static final String TAG = "CrashHandler";
    private static CrashHandler instance;


    private CrashHandler() {
    }

    public static CrashHandler getInstance() {

        if (instance == null) {
            instance = new CrashHandler();
        }

        return instance;
    }

    @Override
    public void uncaughtException(Thread t, Throwable e) {
        Log.e(TAG, e.toString());
    }

    public void init() {
        Thread.setDefaultUncaughtExceptionHandler(this);
    }
}

接下來我們在ApplicationonCreate()里面初始化:

  package com.zzw.TestCrashHandler;

import android.app.Application;

/**
 * Created by zzw on 2017/4/28.
 */

public class MyApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        CrashHandler.getInstance().init();
    }
}

我們接著制造一個bug出來:

  package com.zzw.TestCrashHandler;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.crash_bt).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.crash_bt:
                String nullStr = null;
                Log.e("zzz", nullStr);
                break;
        }
    }
}
image.png

異常捕捉到了,但是卻卡主了,然后就是ANR,看來是造成線程堵塞了,所以我們必須把這個給處理了。

  package com.zzw.TestCrashHandler;

import android.content.Context;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;

/**
 * Created by zzw on 2017/4/28.
 */

public class CrashHandler implements Thread.UncaughtExceptionHandler {

    private static final String TAG = "CrashHandler";
    private static CrashHandler instance;
    private Thread.UncaughtExceptionHandler defaultHandler;//系統默認的UncaughtException處理器
    private Context context;


    private CrashHandler() {
    }

    public static CrashHandler getInstance() {

        if (instance == null) {
            instance = new CrashHandler();
        }

        return instance;
    }

    @Override
    public void uncaughtException(Thread t, Throwable e) {
        if (!handleException(e) && defaultHandler != null) {  //如果用戶沒有處理則讓系統默認的異常處理器來處理
            defaultHandler.uncaughtException(t, e);
        } else {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException ex) {
                Log.e(TAG, "error : ", ex);
            }
            //退出程序
            android.os.Process.killProcess(android.os.Process.myPid());
            System.exit(1);
        }
    }

    public void init(Context context) {
        this.context = context;
        //獲取系統默認的UncaughtException處理器
        defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(this);
    }


    private boolean handleException(Throwable e) {
        if (e == null)
            return false;

        //使用Toast來顯示異常信息
        new Thread() {
            @Override
            public void run() {
                Looper.prepare();
                Toast.makeText(context, "程序發生意外情況,即將關閉,我們深感抱歉!我們將會盡快修復!", Toast.LENGTH_LONG).show();
                Looper.loop();
            }
        }.start();

        saveException(e);

        return true;
    }

    /**
     * 一般在這是把崩潰信息保存下來,然后等wifi的時候上傳到服務器
     *
     * @param e 異常信息
     */
    private void saveException(Throwable e) {
        Log.e(TAG, e.toString());
    }

}

這樣的話我們就能夠提示用戶,然后把異常信息保存下來,等待有Wifi的時候上傳就可以了。
效果如下:

這篇文章到這,Demo就不上傳了,希望大家有所收獲,有什么建議在下方評論,謝謝。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容