Androidはプログラムがクラッシュして異常をキャプチャした後にログを記録して終了します
7730 ワード
CashHandler
MyApplication
LifeCycleCallbacks
public class CrashHandler implements Thread.UncaughtExceptionHandler {
private static CrashHandler sInstance = null;
private Thread.UncaughtExceptionHandler mDefaultHandler;
private Context mContext;
private Map mMessage = new HashMap<>();
private String crashTip = " , ";
public static CrashHandler getInstance() {
if (sInstance == null) {
synchronized (CrashHandler.class) {
if (sInstance == null) {
synchronized (CrashHandler.class) {
sInstance = new CrashHandler();
}
}
}
}
return sInstance;
}
public void init(Context context) {
mContext = context;
//
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
// CrashHandler
Thread.setDefaultUncaughtExceptionHandler(this);
}
@Override
public void uncaughtException(Thread t, Throwable e) {
if (!handleException(e)) {
// ,
if (mDefaultHandler != null) {
mDefaultHandler.uncaughtException(t, e);
}
} else {
// , app
try {
Thread.sleep(3000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
MyApplication.getInstance().exit();
}
}
/**
*
*
* @param e Throwable
* @return true: false:
*/
private boolean handleException(Throwable e) {
if (e == null) {
return false;
}
new Thread() {
@Override
public void run() {
Looper.prepare();
Toast.makeText(mContext, crashTip, Toast.LENGTH_LONG).show();
Looper.loop();
}
}.start();
collectErrorMessages();
saveErrorMessages(e);
return true;
}
// app
private void collectErrorMessages() {
PackageManager pm = mContext.getPackageManager();
try {
// app
PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES);
if (pi != null) {
String versionName = TextUtils.isEmpty(pi.versionName) ? "null" : pi.versionName;
String versionCode = "" + pi.versionCode;
mMessage.put("versionName", versionName);
mMessage.put("versionCode", versionCode);
}
//
Field[] fields = Build.class.getFields();
if (fields != null && fields.length > 0) {
for (Field field : fields) {
field.setAccessible(true);
try {
mMessage.put(field.getName(), field.get(null).toString());
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
//
private String saveErrorMessages(Throwable e) {
StringBuilder sb = new StringBuilder();
for (Map.Entry entry : mMessage.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
sb.append(key).append("=").append(value).append("
");
}
Writer writer = new StringWriter();
PrintWriter pw = new PrintWriter(writer);
e.printStackTrace(pw);
Throwable cause = e.getCause();
// Cause
while (cause != null) {
cause.printStackTrace(pw);
cause = cause.getCause();
}
pw.close();
String result = writer.toString();
sb.append(result);
String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(new Date());
String fileName = "crash-" + time + "-" + System.currentTimeMillis() + ".log";
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
String path = Environment.getExternalStorageDirectory().getPath() + "/crash/";
File dir = new File(path);
if (!dir.exists()) {
dir.mkdirs();
}
FileOutputStream fos = null;
try {
fos = new FileOutputStream(path + fileName);
fos.write(sb.toString().getBytes());
return fileName;
} catch (Exception e1) {
e1.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
return "";
}
}
MyApplication
public class MyApplication extends Application{
private static Context mContext;
private List activitys = null;
private static MyApplication instance;
@Override
public void onCreate() {
super.onCreate();
CrashHandler.getInstance().init(this);
LifecycleCallbacks.init(this);
}
public static Context getContext() {
return mContext;
}
public static MyApplication getInstance() {
if (null == instance) {
instance = new MyApplication();
}
return instance;
}
// Activity finish
public void exit() {
activitys = LifecycleCallbacks.getActivitys();
if (activitys != null && activitys.size() > 0) {
for (Activity activity : activitys) {
activity.finish();
}
}
System.exit(0);
}
}
LifeCycleCallbacks
public class LifecycleCallbacks implements Application.ActivityLifecycleCallbacks {
/**
* Activity List
*/
private static List mActivitys = Collections.synchronizedList(new LinkedList());
private static LifecycleCallbacks instance;
public static LifecycleCallbacks init(Application application){
if (instance == null) {
instance = new LifecycleCallbacks();
application.registerActivityLifecycleCallbacks(instance);
}
return instance;
}
public static List getActivitys(){
return mActivitys;
}
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
if (null == mActivitys) {
return;
}
mActivitys.add(activity);
}
@Override
public void onActivityStarted(Activity activity) {
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
if (null == activity && mActivitys.isEmpty()) {
return;
}
if (mActivitys.contains(activity)) {
mActivitys.remove(activity);
}
}
}