我的GitHub | 我的博客 | 我的微信 | 我的郵箱 |
---|---|---|---|
baiqiantao | baiqiantao | bqt20094 | baiqiantao@sina.com |
ACRA:安卓應用崩潰報告
Application Crash Report for Android
ACRA是一個庫,使Android應用程序能夠自動將崩潰報告
發布到報表服務器。 它針對Android應用程序開發人員,幫助他們在崩潰或行為錯誤時從應用程序中獲取數據。
ACRA is a library enabling Android Application to automatically post their crash reports to a report server. It is targeted to android applications developers to help them get data from their applications when they crash or behave erroneously.
特點:
- 開發者可配置的用戶交互: silent reports, Toast notification, status bar notification + dialog or direct dialog
- 可用於2.2以上的所有Android版本。
- 有關運行應用程序的設備的詳細崩潰報告
- 您可以將自己的變量內容或調試跟蹤[debug traces]添加到報告中
- 即使應用程序沒有崩潰,您也可以發送錯誤報告
- 適用於任何應用程序,非常適用於 Google Play 不可用的設備/地區,測試版或企業私有應用
- 如果沒有網絡覆蓋,則保留報告並在稍后應用程序重新啟動時發送
- 可以與您自己的自托管報告接收器腳本一起使用
ACRA的通知系統很干凈。如果發生崩潰,您的應用程序不會在現有系統的崩潰通知或報告功能上添加用戶通知。默認情況下,不再顯示“強制關閉”對話框,啟用它會將 allReportToAndroidFramework
設置為true。
用戶只會收到一次錯誤通知,您可以通過在 notifications/dialogs 中定義自己的文本來提高應用程序的感知質量。
請不要猶豫,在問題跟蹤器中打開缺陷/增強功能請求。
基本配置
要求 gradle 版本 3.0.0 或以上,java 8 或以上。
統一版本管理
def acraVersion = '5.1.3'
選擇報告目的地,更多信息參考 Report Destinations
implementation "ch.acra:acra-http:$acraVersion"//Http
implementation "ch.acra:acra-mail:$acraVersion"//Email
implementation "ch.acra:acra-core:$acraVersion"//Custom
選擇交互方式,更多信息參考 Interactions
implementation "ch.acra:acra-dialog:$acraVersion"//Dialog
implementation "ch.acra:acra-notification:$acraVersion"//Notification
implementation "ch.acra:acra-toast:$acraVersion"//Toast
//Silent:Add nothing.
限制器(可選),限制acra從一個設備發送的報告數量
implementation "ch.acra:acra-limiter:$acraVersion"
高級調度程序(可選),控制何時發送報告(例如僅在wifi時)並且可以在崩潰后重新啟動應用程序
implementation "ch.acra:acra-advanced-scheduler:$acraVersion"
初始化
@AcraCore(buildConfigClass = BuildConfig.class)
public class MyApplication extends Application {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
ACRA.init(this);
}
}
定義的注解
- @AcraHttpSender
- @AcraMailSender
- @AcraDialog
- @AcraNotification
- @AcraToast
- @AcraLimiter
- @AcraScheduler
可用的 Builder
- HttpSenderConfigurationBuilder
- MailSenderConfigurationBuilder
- DialogConfigurationBuilder
- NotificationConfigurationBuilder
- ToastConfigurationBuilder
- LimiterConfigurationBuilder
- SchedulerConfigurationBuilder
使用案例
依賴
def acraVersion = '5.1.3'
implementation "ch.acra:acra-http:$acraVersion"//Http
implementation "ch.acra:acra-mail:$acraVersion"//Email
implementation "ch.acra:acra-core:$acraVersion"//Custom
implementation "ch.acra:acra-dialog:$acraVersion"//Dialog
implementation "ch.acra:acra-notification:$acraVersion"//Notification
implementation "ch.acra:acra-toast:$acraVersion"//Toast
Application
@AcraCore(buildConfigClass = BuildConfig.class)
public class App extends Application {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
CoreConfigurationBuilder builder = new CoreConfigurationBuilder(this)
.setBuildConfigClass(BuildConfig.class)
.setReportFormat(StringFormat.JSON);
builder.getPluginConfigurationBuilder(ToastConfigurationBuilder.class)//吐司
.setLength(Toast.LENGTH_SHORT)
.setResText(R.string.acra_crash_tips)//或者setText
.setEnabled(true);
builder.getPluginConfigurationBuilder(DialogConfigurationBuilder.class)//彈窗
.setResIcon(R.drawable.icon)
.setResTheme(R.style.AppTheme)
.setTitle("標題")//setResTitle
.setText("內容\n\n呵呵呵呵呵呵呵呵")//setResText
.setCommentPrompt("CommentPrompt")//注釋輸入提示符的標簽。setResCommentPrompt
.setEmailPrompt("EmailPrompt")// setResEmailPrompt
.setNegativeButtonText("NegativeButtonText")// setResNegativeButtonText
.setPositiveButtonText("PositiveButtonText")// setResPositiveButtonText
//.setReportDialogClass(BaseCrashReportDialog.class)//自定義CrashReportDialog
.setEnabled(true);
builder.getPluginConfigurationBuilder(MailSenderConfigurationBuilder.class)//發郵件。測試失敗
.setMailTo("0909082401@163.com")
.setSubject("主題(崩潰日志)")//或者setResSubject
.setReportAsFile(true)
.setReportFileName("附件名稱")
.setEnabled(false);//是通過跳到系統郵箱中,在用戶預覽並確認后由用戶發出去的,而不是在后台默默發送的
builder.getPluginConfigurationBuilder(HttpSenderConfigurationBuilder.class)//HTTP請求。不知道怎么測試
.setHttpMethod(HttpSender.Method.POST)
.setConnectionTimeout(30 * 1000)
.setSocketTimeout(30 * 1000)
.setHttpHeaders(new HashMap<>())
.setBasicAuthLogin("")//認證
.setBasicAuthPassword("")
.setCertificatePath("")//證書地址。或者setResCertificate
.setCertificateType("")//證書類型
.setDropReportsOnTimeout(false)//超時是否刪除報告
.setKeyStoreFactoryClass(KeyStoreFactory.class)//該類創建了可以包含可信證書的密鑰庫
.setEnabled(false);
builder.getPluginConfigurationBuilder(NotificationConfigurationBuilder.class)//通知欄。測試失敗
.setResIcon(R.drawable.icon)
.setTitle("標題")//setResTitle
.setText("內容\n\n呵呵呵呵呵呵呵呵")
.setResSendButtonIcon(R.drawable.icon)
.setResSendButtonText(R.string.acra_crash_tips)
.setEnabled(false);
ACRA.init(this, builder);
}
}
CustomActivityOnCrash:自定義崩潰界面
該庫允許在應用程序崩潰時啟動自定義activity,而不是顯示討厭的Unfortunately, X has stopped
對話框。
當然,您可以將此庫與任何其他崩潰處理程序(如Crashlytics,ACRA或Firebase)結合使用,只需按照通常的方式進行設置即可。
基本使用
依賴:
compile 'cat.ereza:customactivityoncrash:2.2.0'
在 Application 中初始化:
@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();
}
自定義配置
以下是可以使用 CaocConfig.Builder 設置的每個選項的更詳細說明:
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);
默認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);
默認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);
默認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);
默認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);
默認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);
默認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);
默認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>);
默認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>);
默認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);
默認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();//在崩潰提示頁面關閉程序時回調
}
完全自定義錯誤 activity
如果您選擇完全創建自定義的錯誤 activity,則可以使用以下方法:
CustomActivityOnCrash.getStackTraceFromIntent(getIntent());
//Returns the stack trace堆棧跟蹤信息 that caused the error as a string.
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());
//Returns the config of the library when the crash happened. Used to call some methods.
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);
//The same as CustomActivityOnCrash.restartApplication, but allows you to specify a custom intent.
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類實例並遇到多進程問題。
工作原理
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.
不兼容性和免責聲明
- 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;
}
}
}
設置
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在崩潰提示頁面關閉程序】");
}
};
}
}
騰訊 Bugly
介紹
騰訊Bugly,為移動開發者提供專業的異常上報和運營統計,幫助開發者快速發現並解決異常,同時掌握產品運營動態,及時跟進用戶反饋。
應用集成SDK后,即可在Web站點查看應用上報的崩潰數據和聯網數據。
功能
- 異常概覽:查看今日實時統計、崩潰趨勢、崩潰排行和TOP20崩潰問題等信息
- 崩潰分析/卡頓分析/錯誤分析:查看上報問題的列表
- 問題詳情:查看上報問題的詳細信息
- 高級搜索:通過各種條件快速查找需要定位分析的異常
- 運營統計:查看應用的聯網統計信息
平台術語
- 異常:App在運行過程中發生的崩潰、卡頓、ANR、錯誤,統稱為異常。
- 崩潰:用戶在使用App過程中發生一次閃退,計為一次崩潰。
- 卡頓:用戶在使用App過程中發生卡頓現象,計為一次卡頓,卡頓時間默認是5s,也支持自定義時間。
- ANR:用戶在使用App過程中出現彈框,提示應用無響應,計為一次ANR,ANR僅用於Android平台應用。
- 錯誤:主動上報的Exception、Error,或腳本(如C#、Lua、JS等)錯誤,統稱為錯誤。
- 發生次數:一個異常發生且被記錄上報,計為一次異常發生。
- 影響用戶:一台設備發生異常,計為一個影響用戶。 在指定時間范圍內,若一個設備發生多次異常,只算一個影響用戶。
- 用戶異常率:即影響用戶/聯網用戶的比值,諸如用戶崩潰率、用戶卡頓率、用戶ANR率、用戶錯誤率等。
- 次數異常率:即發生次數/聯網次數的比值,諸如次數崩潰率、次數卡頓率、次數ANR率、次數錯誤率等。
- 聯網次數:即 啟動次數+跨天聯網次數。
- 跨天聯網:用戶沒有啟動應用,只有應用進程在后台運行,且超過零點,計為一次跨天聯網。
- 啟動次數:應用完全退出后重新啟動,計為一次啟動;應用被切換至后台后,30秒后被切換至前台,計為一次啟動,若未超過30秒切換至前台,不算一次啟動。
- 聯網用戶:以設備為判斷指標,每一個發生聯網的設備,即為一個聯網用戶;在指定時間范圍內,若一個設備重復發生聯網行為,只算一個聯網用戶。
最簡單的接入配置
配置依賴
implementation 'com.tencent.bugly:crashreport:2.6.6'
權限
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
避免混淆
-dontwarn com.tencent.bugly.**
-keep public class com.tencent.bugly.**{*;}
初始化
CrashReport.initCrashReport(this, "6c32268c59", true);//APPID、是否為調試模式
第三個參數為SDK調試模式開關,建議在測試階段建議設置成true,發布時設置為false。
調試模式的行為特性如下:
- 輸出詳細的Bugly SDK的Log
- 每一條Crash都會被立即上報
- 自定義日志將會在Logcat中輸出
測試
switch (position) {
case 0:
Log.i("bqt", "" + string.length());//空指針異常
break;
case 1:
CrashReport.testJavaCrash();//測試Java Crash
break;
case 2:
CrashReport.testANRCrash();//測試ANR Crash
break;
case 3:
CrashReport.testNativeCrash();//測試Native Crash
break;
}
高級功能
上傳開發者catch的異常
您可能會關注某些重要異常的Catch情況。我們提供了上報這類異常的接口。例:統計某個重要的數據庫讀寫問題比例。
try {
//...
} catch (Throwable thr) {
CrashReport.postCatchedException(thr); // bugly會將這個throwable上報
}
js 的異常捕獲功能
Bugly Android SDK 1.2.8及以上版本提供了Javascript的異常捕獲和上報能力,以便開發者可以感知到 WebView 中發生的 Javascript 異常。
在 WebChromeClient 的 onProgressChanged 函數中調用接口:
webView.setWebChromeClient(new WebChromeClient() {
@Override
public void onProgressChanged(WebView webView, int progress) {
CrashReport.setJavascriptMonitor(webView, true);//設置Javascript的異常監控(自動注入方式)
super.onProgressChanged(webView, progress);
}
});
- 參數:WebView webView 指定被監控的 webView
- 參數:boolean autoInject 是否自動注入 Bugly.js 文件
- 返回:true 設置成功;false 設置失敗
注意:
- Bugly.js 文件在Bugly SDK包中,可以在HTML手動嵌入;
- 如果使用自動集成SDK方式,可以使用自動注入和手動注入兩種方式。
- 由於Android 4.4以下版本存在反射漏洞,接口默認只對Android 4.4及以上版本有效;
- 接口不會設置webView的WebViewClient和Listener;
- 接口默認會開啟webView的JS執行能力;
配置用戶策略 UserStrategy
UserStrategy是Bugly的初始化擴展類,在這里您可以修改本次初始化Bugly數據的版本、渠道及部分初始化行為:
CrashReport.UserStrategy strategy = new CrashReport.UserStrategy(this)//初始化時增加上報策略
.setAppChannel("myChannel") //設置渠道,會覆蓋 AndroidManifest 里面的配置
.setAppVersion("1.0.1") //App的版本,會覆蓋 AndroidManifest 里面的配置
.setAppPackageName("com.bqt.test") //App的包名
.setAppReportDelay(20 * 1000) //設置Bugly初始化延遲時間,Bugly默認會在啟動10s后聯網同步數據
.setUploadProcess(isMainProcess);//只在主進程下上報數據
CrashReport.initCrashReport(this, "6c32268c59", true, strategy);// 初始化Bugly
設置 Crash 回調
兩個回調返回的數據將伴隨Crash一起上報到Bugly平台,並展示在附件中。
strategy.setCrashHandleCallback(new CrashReport.CrashHandleCallback() {
/**
* Crash處理.
*
* @param crashType 錯誤類型:CRASHTYPE_JAVA,CRASHTYPE_NATIVE,CRASHTYPE_U3D ,CRASHTYPE_ANR
* @param errorType 錯誤的類型名
* @param errorMessage 錯誤的消息
* @param errorStack 錯誤的堆棧
* @return 返回額外的自定義信息上報
*/
@Override
public Map<String, String> onCrashHandleStart(int crashType, String errorType, String errorMessage, String errorStack) {
LinkedHashMap<String, String> map = new LinkedHashMap<>();
map.put("Key", "Value");
return map;
}
@Override
public byte[] onCrashHandleStart2GetExtraDatas(int crashType, String errorType, String errorMessage, String errorStack) {
try {
return "Extra data.".getBytes("UTF-8");
} catch (Exception e) {
return null;
}
}
});
崩潰類型:
- public static final int CRASHTYPE_JAVA_CRASH = 0; // Java crash
- public static final int CRASHTYPE_JAVA_CATCH = 1; // Java caught exception
- public static final int CRASHTYPE_NATIVE = 2; // Native crash
- public static final int CRASHTYPE_U3D = 3; // Unity error
- public static final int CRASHTYPE_ANR = 4; // ANR
- public static final int CRASHTYPE_COCOS2DX_JS = 5; // Cocos JS error
- public static final int CRASHTYPE_COCOS2DX_LUA = 6; // Cocos Lua error
注意,需要盡量保證回調的邏輯簡單和穩定,絕對不能在回調中Kill掉進程,否則會影響Crash的上報。如果需要執行類似於Crash之后Kill掉進程並重新拉起
的動作,建議自定義一個Crash handler,並在初始化Bugly之前注冊。
使用 MultiDex 的注意事項
如果使用了MultiDex,建議通過 Gradle 的 multiDexKeepFile 配置等方式把Bugly的類放到主Dex,另外建議在Application類的 attachBaseContext 方法中主動加載非主dex:
public class MyApplication extends SomeOtherApplication {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(context);
Multidex.install(this);
}
}
上報進程控制
如果App使用了多進程且各個進程都會初始化Bugly(例如在Application類onCreate()中初始化Bugly),那么每個進程下的Bugly都會進行數據上報,造成不必要的資源浪費。為了節省流量、內存等資源,建議初始化的時候對上報進程進行控制,只在主進程下上報數據
。
String packageName = getPackageName();// 獲取當前包名
String processName = getProcessName(android.os.Process.myPid());// 獲取當前進程名
boolean isMainProcess = processName == null || processName.equals(packageName);//通過進程名是否為包名來判斷是否是主進程
strategy.setUploadProcess(isMainProcess);//只在主進程下上報數據
獲取進程號對應的進程名
/**
* 獲取進程號對應的進程名
*
* @param pid 進程號
* @return 進程名
*/
private static String getProcessName(int pid) {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader("/proc/" + pid + "/cmdline"));
String processName = reader.readLine();
if (!TextUtils.isEmpty(processName)) {
processName = processName.trim();
}
return processName;
} catch (Throwable throwable) {
throwable.printStackTrace();
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException exception) {
exception.printStackTrace();
}
}
return null;
}
其他設置
設置自定義標簽
用於標明App的某個“場景”。在發生Crash時會顯示該Crash所在的“場景”,以最后設置的標簽為准,標簽id需大於0。例:當用戶進入界面A時,打上9527的標簽:
CrashReport.setUserSceneTag(context, 9527); // 上報后的Crash會顯示該標簽
打標簽之前,需要在Bugly產品頁配置中添加標簽,取得標簽ID后在代碼中上報。
設置自定義Map參數
自定義Map參數可以保存發生Crash時的一些自定義的環境信息。在發生Crash時會隨着異常信息一起上報並在頁面展示。
CrashReport.putUserData(context, "userkey", "uservalue");
最多可以有9對自定義的key-value(超過則添加失敗);
key限長50字節,value限長200字節,過長截斷;key必須匹配正則:[a-zA-Z[0-9]]+。
設置開發設備
在開發測試階段,可以在初始化Bugly之前通過以下接口把調試設備設置成“開發設備”。
CrashReport.setIsDevelopmentDevice(context, true);
ADT 17增加了BuildConfig特性,可以通過獲取BuildConfig類的DEBUG變量來設置:
CrashReport.setIsDevelopmentDevice(context, BuildConfig.DEBUG);
設置用戶ID
您可能會希望能精確定位到某個用戶的異常,我們提供了用戶ID記錄接口。例:網游用戶登錄后,通過該接口記錄用戶ID,在頁面上可以精確定位到每個用戶發生Crash的情況。
CrashReport.setUserId("9527"); //該用戶本次啟動后的異常日志用戶ID都將是9527
上傳自定義日志
我們提供了自定義Log的接口,用於記錄一些開發者關心的調試日志
,可以更全面地反應App異常時的前后文環境。使用方式與 android.util.Log
一致。用戶傳入TAG和日志內容。該日志將在Logcat輸出,並在發生異常時上報。
BuglyLog.i(tag, log)
在使用BuglyLog
接口時,為了減少磁盤IO次數,我們會先將日志緩存在內存
中。當緩存大於一定閾值(默認10K),會將它持久化至文件
。您可以通過 setCache 接口設置緩存大小,范圍為0-30K。
BuglyLog.setCache(12 * 1024) //將Cache設置為12K
PS:
- 如果您沒有使用 BuglyLog 接口,且初始化 Bugly 時 isDebug 參數設置為 false,該 Log 功能將不會有新的資源占用。
- 為了方便開發者調試,當初始化 Bugly 的 isDebug 參數為 true 時,異常日志同時還會記錄 Bugly 本身的日志。
- 請在 App 發布時將其設置為false。
- 上報Log最大30K。
2018-6-6