一、说明
笔记主要是记录一些本人在开发当中的学习和使用笔记。笔记内容包含一些本人觉得重要的知识点、本人易犯的错误等。
由于本人水平有限,其中出现的错误或者不合理的地方望各位读者多多包含,并指出其中不合理和错误的地方,以便我来修正。谢谢!
二、笔记时间
2018年10月17日
三、简述
本文主要讲述Android APP为什么需要奔溃捕获和奔溃捕获的方式。
四、详情
1、简介
在开发Android APP当中,难免会有一些无法预期的错误,或者在特殊环境下和操作下才会出现的错误。当这些错误发生时,会导致APP奔溃并且出现不友好的界面,影响APP的体验。
那么我们程序员GG怎么解决这些错误,还给用户一个体验完美的APP呢?这个时候奔溃捕获的作用就体现出来了,我们通过奔溃捕获获取奔溃日志,并把奔溃日志保存到本地或者发送到日志服务器,以便程序员GG来查看和解决错误。
2、奔溃捕获示例
2.1、实现UncaughtExceptionHandler
//CrashHandler.java
package com.lipy.demo.crashhandler;
import android.app.AlarmManager;
import android.app.Application;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.io.StringWriter;
import java.io.Writer;
import java.text.SimpleDateFormat;
/**
* 创建人: lipy
* 创建时间: 2017/8/4
* 修改人:lipy
* 修改时间:2017/8/4
* 修改内容:
*
* 功能描述:捕获奔溃并重启
*/
public class CrashHandler implements Thread.UncaughtExceptionHandler {
private final String PATH = "/storage/sdcard0/crash_logger.txt";
public static CrashHandler mAppCrashHandler;
private Thread.UncaughtExceptionHandler mDefaultHandler;
private Application mAppContext;
public static CrashHandler getInstance() {
if (mAppCrashHandler == null) {
mAppCrashHandler = new CrashHandler();
}
return mAppCrashHandler;
}
public void initCrashHandler(Application application) {
this.mAppContext = application;
// 获取系统默认的UncaughtException处理器
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this);
}
@Override
public void uncaughtException(Thread thread, Throwable ex) {
if (!handleException(ex) && mDefaultHandler != null) {
// 如果用户没有处理则让系统默认的异常处理器来处理
//mDefaultHandler.uncaughtException(thread, ex);
}
//设置重启定时器
AlarmManager mgr = (AlarmManager) mAppContext.getSystemService(Context.ALARM_SERVICE);
//1秒后重启
Intent intent = new Intent(mAppContext, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent restartIntent = PendingIntent.getActivity(mAppContext, 0, intent, PendingIntent.FLAG_ONE_SHOT);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, restartIntent); // 1秒钟后重启应用
//杀死进程
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(0);
System.gc();
}
/**
* 错误处理,收集错误信息、发送错误报告等操作均在此完成.
*
* @param ex 错误信息
* @return true:如果处理了该异常信息;否则返回false.
*/
private boolean handleException(Throwable ex) {
if (ex == null) {
return false;
}
//收集奔溃日志
Writer writer = new StringWriter();
PrintWriter printWriter = new PrintWriter(writer);
ex.printStackTrace(printWriter);
Throwable cause = ex.getCause();
while (cause != null) {
cause.printStackTrace(printWriter);
cause = cause.getCause();
}
printWriter.close();
String result = writer.toString();
//保存日志
saveInfo(result);
// 自定义处理错误信息
return true;
}
/**
* 保存错误信息到本地文件
*
* @param msg String
*/
private void saveInfo(String msg) {
try {
String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(System.currentTimeMillis());
String info = time + ":\n\r" + msg + "\n\r\n\r";
RandomAccessFile log = new RandomAccessFile(PATH, "rw");
log.skipBytes((int) log.length());
log.write(info.getBytes());
log.close();
} catch (Exception e) {
Log.e("CrashHandler", "save crash info err !!" + e.toString());
}
}
}
2.2、自定义Application
//MyApplication.java
package com.lipy.demo.crashhandler;
import android.app.Application;
/**
* 创建人: lipy
* 创建时间: 2018/10/18
* 修改人:lipy
* 修改时间:2018/10/18
* 修改内容:
*
* 功能描述:自定义Application
*/
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
//异常捕获初始化
CrashHandler.getInstance().initCrashHandler(this); // 一定要初始化
}
}
2.3、注册清单
在AndroidManifest.xml中注册MyApplication,通过android:name=".MyApplication" 使APP的Application使用自定义的MyApplication。
<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round">
</application>
由于中示例的MyApplication中的奔溃日志是保存到本地文件当中,因此需要添加文件读写权限。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
2.4、示例源码
示例源码:https://github.com/lipyhui/android_app_demo/tree/master/CrashHandler
网友评论