异常捕获 CustomActivityOnCrash

文档

compile 'cat.ereza:customactivityoncrash:2.2.0'
1
1
 
1
compile 'cat.ereza:customactivityoncrash:2.2.0'
This library allows launching a custom activity when the app crashes, instead of showing the hated "Unfortunately, X has stopped" dialog.
Of course, you can combine this library with any other crash handler such as Crashlytics, ACRA or Firebase, just set them up as you would normally.

Advanced setup 高级设置

You can customize the behavior of this library in several ways by setting its configuration at any moment. However, it's recommended to do it on your Application class so it becomes available as soon as possible.
Add a snippet like this to your Application class:
@Override
public void onCreate() {
    super.onCreate();
    CaocConfig.Builder.create()
        .backgroundMode(CaocConfig.BACKGROUND_MODE_SILENT) //default: CaocConfig.BACKGROUND_MODE_SHOW_CUSTOM
        .enabled(false) //default: true
        .showErrorDetails(false) //default: true
        .showRestartButton(false) //default: true
        .logErrorOnRestart(false) //default: true
        .trackActivities(true) //default: false
        .minTimeBetweenCrashesMs(2000) //default: 3000
        .errorDrawable(R.drawable.ic_custom_drawable) //default: bug image
        .restartActivity(YourCustomActivity.class) //default: null (your app's launch activity)
        .errorActivity(YourCustomErrorActivity.class) //default: null (default error activity)
        .eventListener(new YourCustomEventListener()) //default: null
        .apply();
}
17
17
 
1
@Override
2
public void onCreate() {
3
    super.onCreate();
4
    CaocConfig.Builder.create()
5
        .backgroundMode(CaocConfig.BACKGROUND_MODE_SILENT) //default: CaocConfig.BACKGROUND_MODE_SHOW_CUSTOM
6
        .enabled(false) //default: true
7
        .showErrorDetails(false) //default: true
8
        .showRestartButton(false) //default: true
9
        .logErrorOnRestart(false) //default: true
10
        .trackActivities(true) //default: false
11
        .minTimeBetweenCrashesMs(2000) //default: 3000
12
        .errorDrawable(R.drawable.ic_custom_drawable) //default: bug image
13
        .restartActivity(YourCustomActivity.class) //default: null (your app's launch activity)
14
        .errorActivity(YourCustomErrorActivity.class) //default: null (default error activity)
15
        .eventListener(new YourCustomEventListener()) //default: null
16
        .apply();
17
}

Customization options 自定义

Here is a more detailed explanation of each option that can be set using CaocConfig.Builder:
launchWhenInBackground(int);
1
1
 
1
launchWhenInBackground(int);
This method defines if the error activity should be launched when the app crashes while on background. There are three modes:
  • CaocConfig.BACKGROUND_MODE_SHOW_CUSTOM: launch the error activity even if the app is in background.
  • CaocConfig.BACKGROUND_MODE_CRASH: launch the default system error when the app is in background.
  • CaocConfig.BACKGROUND_MODE_SILENT: crash silently when the app is in background.
The default is CaocConfig.BACKGROUND_MODE_SHOW_CUSTOM.

enabled(boolean);
1
1
 
1
enabled(boolean);
默认true,设为false将阻止对崩溃的拦截,等于禁用了框架
Defines if CustomActivityOnCrash crash interception mechanism拦截机制 is enabled. Set it to true if you want CustomActivityOnCrash to intercept crashes, false if you want them to be treated as if the library was not installed. This can be used to enable or disable the library depending on flavors or buildTypes. The default is true.

showErrorDetails(boolean);
1
1
 
1
showErrorDetails(boolean);
默认true,设为false将隐藏错误活动中的“错误详细信息”按钮,从而隐藏堆栈跟踪
This method defines if the error activity must show a button with error details. If you set it to false, the button on the default error activity will disappear, thus这样的话 disabling the user from seeing the stack trace. The default is true.

trackActivities(boolean);
1
1
 
1
trackActivities(boolean);
默认false,设为true将会在错误页面中显示错误详细信息
This method defines if the library must track the activities the user visits and their lifecycle calls. This is displayed on the default error activity as part of the error details. The default is false.

showRestartButton(boolean);
1
1
 
1
showRestartButton(boolean);
默认true,是否显示重启页面按钮
This method defines if the error activity must show a "Restart app" button or a "Close app" button. If you set it to false, the button on the default error activity will close the app instead of restarting. If you set it to true and your app has no launch activity, it will still display a "Close app" button! The default is true.

logErrorOnRestart(boolean);
1
1
 
1
logErrorOnRestart(boolean);
默认true,是否可以在 Logcat 中显示崩溃的堆栈轨迹
This controls if the stack trace must be relogged必须重新记录堆栈跟踪 when the custom error activity is launched. This functionality exists because the Android Studio default Logcat view only shows the output for the current process. This makes it easier to see the stack trace of the crash崩溃的堆栈轨迹. You can disable it if you don't want an extra log. The default is true.

minTimeBetweenCrashesMs(int);
1
1
 
1
minTimeBetweenCrashesMs(int);
默认3000。定义应用程序崩溃之间的最短时间,以确定我们不在崩溃循环中。比如:在规定的时间内再次崩溃,框架将不处理,让系统处理!
Defines the time that must pass between app crashes to determine that we are not in a crash loop. If a crash has occurred less that this time ago, the error activity will not be launched and the system crash screen will be invoked. The default is 3000.

errorDrawable(int);
1
1
 
1
errorDrawable(int);
默认null ,崩溃页面显示的图标
This method allows changing the default upside-down上下翻转 bug image with an image of your choice. You can pass a resource id for a drawable or a mipmap. The default is null (the bug image is used).

restartActivity(Class<? extends Activity>);
1
1
 
1
restartActivity(Class<? extends Activity>);
默认null,重新启动后的页面
This method sets the activity that must be launched by the error activity when the user presses the button to restart the app. If you don't set it (or set it to null), the library will use the first activity on your manifest that has an intent-filter with action cat.ereza.customactivityoncrash.RESTART, and if there is none, the default launchable activity on your app. If no launchable activity can be found and you didn't specify any, the "restart app" button will become a " close app" button, even if showRestartButton is set to true.

errorActivity(Class<? extends Activity>);
1
1
 
1
errorActivity(Class<? extends Activity>);
默认null,程序崩溃后显示的页面
This method allows you to set a custom error activity to be launched, instead of the default one. Use it if you need further customization进一步定制 that is not just不只是 strings, colors or themes (see below). If you don't set it (or set it to null), the library will use the first activity on your manifest that has an intent-filter with action cat.ereza.customactivityoncrash.ERROR, and if there is none, a default error activity from the library. If you use this, the activity must be declared in your AndroidManifest.xml, with process set to :error_activity.

eventListener(EventListener);
1
1
 
1
eventListener(EventListener);
默认null,设置监听
This method allows you to specify an event listener in order to get notified when the library shows the error activity, restarts or closes the app. The EventListener you provide can not be an anonymous匿名 or non-static inner class, because it needs to be serialized by the library. The library will throw an exception if you try to set an invalid class. If you set it to null, no event listener will be invoked. The default is null.

CustomEventListener 监听

监听程序崩溃/重启
public interface EventListener extends Serializable {
	void onLaunchErrorActivity();//程序崩溃回调
	void onRestartAppFromErrorActivity();//重启程序时回调
	void onCloseAppFromErrorActivity();//在崩溃提示页面关闭程序时回调
}
5
5
 
1
public interface EventListener extends Serializable {
2
    void onLaunchErrorActivity();//程序崩溃回调
3
    void onRestartAppFromErrorActivity();//重启程序时回调
4
    void onCloseAppFromErrorActivity();//在崩溃提示页面关闭程序时回调
5
}

Completely custom error activity

If you choose to create your own completely custom error activity, you can use these methods:
CustomActivityOnCrash.getStackTraceFromIntent(getIntent());
1
1
 
1
CustomActivityOnCrash.getStackTraceFromIntent(getIntent());
Returns the stack trace堆栈跟踪信息 that caused the error as a string.

CustomActivityOnCrash.getAllErrorDetailsFromIntent(getIntent());
1
1
 
1
CustomActivityOnCrash.getAllErrorDetailsFromIntent(getIntent());
Returns several error details including the stack trace that caused the error, as a string. This is used in the default error activity error details dialog.

CustomActivityOnCrash.getConfigFromIntent(getIntent());
1
1
 
1
CustomActivityOnCrash.getConfigFromIntent(getIntent());
Returns the config of the library when the crash happened. Used to call some methods.

CustomActivityOnCrash.restartApplication(activity, config);
1
1
 
1
CustomActivityOnCrash.restartApplication(activity, config);
Kills the current process and restarts the app again with a startActivity() to the passed intent. You MUST call this to restart the app, or you will end up having several Application class instances and experience multiprocess issues.否则你最终将拥有多个Application类实例并遇到多进程问题。

CustomActivityOnCrash.restartApplicationWithIntent(activity, intent, config);
1
1
 
1
CustomActivityOnCrash.restartApplicationWithIntent(activity, intent, config);
The same as CustomActivityOnCrash.restartApplication, but allows you to specify a custom intent.

CustomActivityOnCrash.closeApplication(activity, eventListener);
1
1
 
1
CustomActivityOnCrash.closeApplication(activity, eventListener);
Closes the app and kills the current process. You MUST call this to close the app, or you will end up having several Application class instances and experience multiprocess issues.否则你最终将拥有多个Application类实例并遇到多进程问题。

Inner workings 工作原理

This library relies on the Thread.setDefaultUncaughtExceptionHandler method. When an exception is caught by the library's UncaughtExceptionHandler it does the following:
  • Captures捕获 the stack trace that caused the crash
  • Launches a new intent to the error activity in a new process passing the crash info as an extra.
  • Kills the current process.
The inner workings are based on ACRA's dialog reporting mode报告模式 with some minor tweaks小的调整. Look at the code if you need more detail about how it works.

Incompatibilities & Disclaimers

兼容性和免责声明
  • CustomActivityOnCrash will not work in these cases:
    • With any custom UncaughtExceptionHandler set after initializing the library, that does not call back to the original handler.
    • With ACRA enabled and reporting mode set to TOAST or DIALOG.
  • If your app initialization or error activity crash, there is a possibility of entering an infinite restart loop无限重启循环 (this is checked by the library for the most common cases, but could happen in rarer罕见的 cases).
  • The library has not been tested with multidex enabled. It uses Class.forName() to load classes, so maybe that could cause some problem in API<21. If you test it with such configuration, please provide feedback反馈!
  • The library has not been tested with multiprocess apps. If you test it with such configuration, please provide feedback too!
  • Disclaimers  免责声明
    • This will not avoid ANRs from happening.
    • This will not catch native errors.
    • There is no guarantee保证 that this will work on every device.
    • This library will not make you toast for breakfast :)

测试代码

自定义崩溃Activity

public class CustomErrorActivity extends ListActivity {
	private CaocConfig config;//配置对象
	
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		Toast.makeText(this, "程序崩溃了!", Toast.LENGTH_SHORT).show();
		
		String errorDetails = CustomActivityOnCrash.getAllErrorDetailsFromIntent(this, getIntent());// 获取所有的信息
		String stackTrace = CustomActivityOnCrash.getStackTraceFromIntent(getIntent());//获取堆栈跟踪信息
		String activityLog = CustomActivityOnCrash.getActivityLogFromIntent(getIntent()); //获取错误报告的Log信息
		config = CustomActivityOnCrash.getConfigFromIntent(getIntent());//获得配置信息
		TextView textView = new TextView(this);
		textView.setText("【errorDetails】\n" + errorDetails + "\n\n\n【stackTrace】\n" + stackTrace + "\n\n\n【activityLog】\n" + activityLog);
		textView.setTextColor(Color.BLUE);
		getListView().addFooterView(textView);
		
		String[] array = {"重启程序", "关闭页面"};
		setListAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, new ArrayList<>(Arrays.asList(array))));
	}
	
	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		switch (position) {
			case 0:
				if (config != null && config.getRestartActivityClass() != null) {
					CustomActivityOnCrash.restartApplication(this, config);
				}
				break;
			case 1:
				CustomActivityOnCrash.closeApplication(this, config);
				break;
		}
	}
}
34
34
 
1
public class CustomErrorActivity extends ListActivity {
2
    private CaocConfig config;//配置对象
3
    
4
    protected void onCreate(Bundle savedInstanceState) {
5
        super.onCreate(savedInstanceState);
6
        Toast.makeText(this, "程序崩溃了!", Toast.LENGTH_SHORT).show();
7
        
8
        String errorDetails = CustomActivityOnCrash.getAllErrorDetailsFromIntent(this, getIntent());// 获取所有的信息
9
        String stackTrace = CustomActivityOnCrash.getStackTraceFromIntent(getIntent());//获取堆栈跟踪信息
10
        String activityLog = CustomActivityOnCrash.getActivityLogFromIntent(getIntent()); //获取错误报告的Log信息
11
        config = CustomActivityOnCrash.getConfigFromIntent(getIntent());//获得配置信息
12
        TextView textView = new TextView(this);
13
        textView.setText("【errorDetails】\n" + errorDetails + "\n\n\n【stackTrace】\n" + stackTrace + "\n\n\n【activityLog】\n" + activityLog);
14
        textView.setTextColor(Color.BLUE);
15
        getListView().addFooterView(textView);
16
        
17
        String[] array = {"重启程序", "关闭页面"};
18
        setListAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, new ArrayList<>(Arrays.asList(array))));
19
    }
20
    
21
    @Override
22
    protected void onListItemClick(ListView l, View v, int position, long id) {
23
        switch (position) {
24
            case 0:
25
                if (config != null && config.getRestartActivityClass() != null) {
26
                    CustomActivityOnCrash.restartApplication(this, config);
27
                }
28
                break;
29
            case 1:
30
                CustomActivityOnCrash.closeApplication(this, config);
31
                break;
32
        }
33
    }
34
}

设置

public class SettingActivity extends ListActivity {
	private int backgroundMode = CaocConfig.BACKGROUND_MODE_SHOW_CUSTOM;
	private boolean enabled = true;
	private boolean showErrorDetails = true;
	private boolean showRestartButton = true;
	private boolean logErrorOnRestart = true;
	private boolean trackActivities = false;
	private int minTimeBetweenCrashesMs = 3000;
	private Integer errorDrawable = null;
	private Class<? extends Activity> errorActivityClass = null;
	private Class<? extends Activity> restartActivityClass = null;
	private CustomActivityOnCrash.EventListener eventListener = null;
	
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		String[] array = {"0、backgroundMode",
				"1、enabled",
				"2、showErrorDetails",
				"3、showRestartButton",
				"4、logErrorOnRestart",
				"5、trackActivities",
				"6、errorDrawable",
				"7、errorActivityClass",
				"8、restartActivityClass",
				"9、eventListener",
				"【自定义一个异常】",};
		setListAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, new ArrayList<>(Arrays.asList(array))));
	}
	
	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		switch (position) {
			case 0:
				backgroundMode = CaocConfig.BACKGROUND_MODE_CRASH;
				break;
			case 1:
				enabled = !enabled;
				break;
			case 2:
				showErrorDetails = !showErrorDetails;
				break;
			case 3:
				showRestartButton = !showRestartButton;
				break;
			case 4:
				logErrorOnRestart = !logErrorOnRestart;
				break;
			case 5:
				trackActivities = !trackActivities;
				break;
			case 6:
				errorDrawable = R.drawable.icon;
				break;
			case 7:
				errorActivityClass = CustomErrorActivity.class;
				break;
			case 8:
				restartActivityClass = MainActivity.class;
				break;
			case 9:
				initListener();
				break;
			case 10:
				throw new RuntimeException("自定义一个异常");
		}
		config();
	}
	
	private void config() {
		CaocConfig.Builder.create()
				.backgroundMode(backgroundMode)
				.enabled(enabled) //这阻止了对崩溃的拦截,false表示阻止。用它来禁用customactivityoncrash框架
				.showErrorDetails(showErrorDetails) //这将隐藏错误活动中的“错误详细信息”按钮,从而隐藏堆栈跟踪
				.showRestartButton(showRestartButton) //是否可以重启页面
				.trackActivities(trackActivities) //错误页面中显示错误详细信息
				.logErrorOnRestart(logErrorOnRestart)
				.minTimeBetweenCrashesMs(minTimeBetweenCrashesMs) //定义应用程序崩溃之间的最短时间,以确定我们不在崩溃循环中
				.errorDrawable(errorDrawable) //崩溃页面显示的图标
				.restartActivity(restartActivityClass) //重新启动后的页面
				.errorActivity(errorActivityClass) //这种程序崩溃后显示的页面
				.eventListener(eventListener)//设置监听
				.apply();
	}
	
	private void initListener() {
		eventListener = new CustomActivityOnCrash.EventListener() {
			@Override
			public void onLaunchErrorActivity() {
				Log.i("bqt", "【onLaunchErrorActivity程序崩溃】");
			}
			
			@Override
			public void onRestartAppFromErrorActivity() {
				Log.i("bqt", "【onRestartAppFromErrorActivity重启程序】");
			}
			
			@Override
			public void onCloseAppFromErrorActivity() {
				Log.i("bqt", "【onCloseAppFromErrorActivity在崩溃提示页面关闭程序】");
			}
		};
	}
}
103
103
 
1
public class SettingActivity extends ListActivity {
2
    private int backgroundMode = CaocConfig.BACKGROUND_MODE_SHOW_CUSTOM;
3
    private boolean enabled = true;
4
    private boolean showErrorDetails = true;
5
    private boolean showRestartButton = true;
6
    private boolean logErrorOnRestart = true;
7
    private boolean trackActivities = false;
8
    private int minTimeBetweenCrashesMs = 3000;
9
    private Integer errorDrawable = null;
10
    private Class<? extends Activity> errorActivityClass = null;
11
    private Class<? extends Activity> restartActivityClass = null;
12
    private CustomActivityOnCrash.EventListener eventListener = null;
13
    
14
    protected void onCreate(Bundle savedInstanceState) {
15
        super.onCreate(savedInstanceState);
16
        String[] array = {"0、backgroundMode",
17
                "1、enabled",
18
                "2、showErrorDetails",
19
                "3、showRestartButton",
20
                "4、logErrorOnRestart",
21
                "5、trackActivities",
22
                "6、errorDrawable",
23
                "7、errorActivityClass",
24
                "8、restartActivityClass",
25
                "9、eventListener",
26
                "【自定义一个异常】",};
27
        setListAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, new ArrayList<>(Arrays.asList(array))));
28
    }
29
    
30
    @Override
31
    protected void onListItemClick(ListView l, View v, int position, long id) {
32
        switch (position) {
33
            case 0:
34
                backgroundMode = CaocConfig.BACKGROUND_MODE_CRASH;
35
                break;
36
            case 1:
37
                enabled = !enabled;
38
                break;
39
            case 2:
40
                showErrorDetails = !showErrorDetails;
41
                break;
42
            case 3:
43
                showRestartButton = !showRestartButton;
44
                break;
45
            case 4:
46
                logErrorOnRestart = !logErrorOnRestart;
47
                break;
48
            case 5:
49
                trackActivities = !trackActivities;
50
                break;
51
            case 6:
52
                errorDrawable = R.drawable.icon;
53
                break;
54
            case 7:
55
                errorActivityClass = CustomErrorActivity.class;
56
                break;
57
            case 8:
58
                restartActivityClass = MainActivity.class;
59
                break;
60
            case 9:
61
                initListener();
62
                break;
63
            case 10:
64
                throw new RuntimeException("自定义一个异常");
65
        }
66
        config();
67
    }
68
    
69
    private void config() {
70
        CaocConfig.Builder.create()
71
                .backgroundMode(backgroundMode)
72
                .enabled(enabled) //这阻止了对崩溃的拦截,false表示阻止。用它来禁用customactivityoncrash框架
73
                .showErrorDetails(showErrorDetails) //这将隐藏错误活动中的“错误详细信息”按钮,从而隐藏堆栈跟踪
74
                .showRestartButton(showRestartButton) //是否可以重启页面
75
                .trackActivities(trackActivities) //错误页面中显示错误详细信息
76
                .logErrorOnRestart(logErrorOnRestart)
77
                .minTimeBetweenCrashesMs(minTimeBetweenCrashesMs) //定义应用程序崩溃之间的最短时间,以确定我们不在崩溃循环中
78
                .errorDrawable(errorDrawable) //崩溃页面显示的图标
79
                .restartActivity(restartActivityClass) //重新启动后的页面
80
                .errorActivity(errorActivityClass) //这种程序崩溃后显示的页面
81
                .eventListener(eventListener)//设置监听
82
                .apply();
83
    }
84
    
85
    private void initListener() {
86
        eventListener = new CustomActivityOnCrash.EventListener() {
87
            @Override
88
            public void onLaunchErrorActivity() {
89
                Log.i("bqt", "【onLaunchErrorActivity程序崩溃】");
90
            }
91
            
92
            @Override
93
            public void onRestartAppFromErrorActivity() {
94
                Log.i("bqt", "【onRestartAppFromErrorActivity重启程序】");
95
            }
96
            
97
            @Override
98
            public void onCloseAppFromErrorActivity() {
99
                Log.i("bqt", "【onCloseAppFromErrorActivity在崩溃提示页面关闭程序】");
100
            }
101
        };
102
    }
103
}
2018-5-31

猜你喜欢

转载自www.cnblogs.com/baiqiantao/p/30528bfddd638903f4e4250a349bb3f7.html
今日推荐