Android使用UncaughtExceptionHandler获取crash信息

来源:互联网 发布:中国教育现状数据分析 编辑:程序博客网 时间:2024/06/05 06:13

Android应用崩溃时如何获取crash信息及处理后续操作。

Android提供了处理此类问题的方法,Thread类中有这样一个方法

    /**     * 设置线程突然终止时调用的默认处理程序     * @param eh     */    public static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh) {        defaultUncaughtExceptionHandler = eh;    }

通用上面的方法,可以看到要传入一个Thread.UncaughtExceptionHandler对象到此方法中。

    public interface UncaughtExceptionHandler {        /**         * Method invoked when the given thread terminates due to the         * given uncaught exception.         * <p>Any exception thrown by this method will be ignored by the         * Java Virtual Machine.         * @param t the thread         * @param e the exception         */        void uncaughtException(Thread t, Throwable e);    }

UncaughtExceptionHandler是一个接口,首先要继承这个接口,实现我们的Crash处理

public class MyCrashExceptionHandler implements Thread.UncaughtExceptionHandler {    private static final String TAG = "MyCrashExceptionHandler";    private static MyCrashExceptionHandler instance;    private Thread.UncaughtExceptionHandler mDefaultExceptionHandler;    private Context mContext;    private MyCrashExceptionHandler() {    }    public static MyCrashExceptionHandler getInstance() {        if (instance == null) {            synchronized (MyCrashExceptionHandler.class) {                if (instance == null) {                    instance = new MyCrashExceptionHandler();                }            }        }        return instance;    }    public void init(Context context) {        if (context == null) {            throw new IllegalArgumentException("Context is null!!!");        }        mContext = context.getApplicationContext();        mDefaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();//获取系统的默认异常处理程序        Thread.setDefaultUncaughtExceptionHandler(this);//设置系统的默认异常处理    }    @Override    public void uncaughtException(Thread t, Throwable e) {        new Thread(new Runnable() {            @Override            public void run() {                Looper.prepare();                Toast.makeText(mContext, "程序发生异常,即将重启", Toast.LENGTH_SHORT).show();                Looper.loop();            }        }).start();        SystemClock.sleep(2000);        Intent intent = new Intent(mContext, MainActivity.class);        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);        mContext.startActivity(intent);        Process.killProcess(Process.myPid());    }}

MainActivity代码

public class MainActivity extends AppCompatActivity {    ImageView img = null;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        Button btn = new Button(this);        btn.setText("崩溃");        btn.setLayoutParams(new ViewGroup.LayoutParams(-1, -2));        setContentView(btn);        MyCrashExceptionHandler myCrashExceptionHandler = MyCrashExceptionHandler.getInstance();        myCrashExceptionHandler.init(this);        btn.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                img.setImageResource(R.mipmap.ic_launcher);//异常            }        });    }}

MyCrashExceptionHandler应该在Application类中初始化,这里为了方便演示,直接写在MainActivity类中了
这里写图片描述

点击崩溃按钮,提示程序发生异常,即将重启,然后重新启动MainActivity界面

上述只是演示了发生异常时重启APK,接下来我们来获取Crash信息

  • 修改后的代码如下
public class MyCrashExceptionHandler implements Thread.UncaughtExceptionHandler {    private static final String TAG = "MyCrashExceptionHandler";    private static MyCrashExceptionHandler instance;    private Thread.UncaughtExceptionHandler mDefaultExceptionHandler;    private Context mContext;    private final String mCrashFileName = "crash";    private MyCrashExceptionHandler() {    }    public static MyCrashExceptionHandler getInstance() {        if (instance == null) {            synchronized (MyCrashExceptionHandler.class) {                if (instance == null) {                    instance = new MyCrashExceptionHandler();                }            }        }        return instance;    }    public void init(Context context) {        if (context == null) {            throw new IllegalArgumentException("Context is null!!!");        }        mContext = context.getApplicationContext();        mDefaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();//获取系统的默认异常处理程序        Thread.setDefaultUncaughtExceptionHandler(this);//设置系统的默认异常处理    }    @Override    public void uncaughtException(Thread t, Throwable e) {        new Thread(new Runnable() {            @Override            public void run() {                Looper.prepare();                Toast.makeText(mContext, "程序发生异常,即将退出", Toast.LENGTH_SHORT).show();                Looper.loop();            }        }).start();        printCrashInfo(e);        SystemClock.sleep(2000);////        Intent intent = new Intent(mContext, MainActivity.class);//        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//        mContext.startActivity(intent);        Process.killProcess(Process.myPid());    }    public void printCrashInfo(Throwable ex) {        File path = mContext.getCacheDir();        long time = System.currentTimeMillis();        File crashFile = new File(path, mCrashFileName + time + ".trace");        String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(time));        try {            PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(crashFile)));            pw.println(date);            PackageManager pm = mContext.getPackageManager();            PackageInfo packageInfo = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES);            pw.println("packageName:" + mContext.getPackageName());            pw.println("APK Ver:" + packageInfo.versionName + " _ " + packageInfo.versionCode);            //TODO 这里为了演示就不打印更多的信息了            pw.println("---------------------------------------------------");            ex.printStackTrace(pw);            pw.close();        } catch (Exception e) {        }    }    /**     * 联网上传crash文件     */    public void uploadCrashFile() {        //TODO    }}

点击崩溃后通过ADM查看包名下的cache目录可以看到crash文件已经保存成功了
这里写图片描述
导出后可以看到详细的崩溃信息
这里写图片描述
还可以根据需要上传crash信息文件,后台做到上线APK崩溃反馈崩溃信息,更好的完善APK。

原创粉丝点击