无所适从的Crash管理,Bugly的集成
- How To Config
- 常规初始化
- 其他方式初始化(可跳过)
- How To Use
- 注意事项
Bugly?
腾讯Bugly,为移动开发者提供专业的异常上报和运营统计,帮助开发者快速发现并解决异常,同时掌握产品运营动态,及时跟进用户反馈。还可以通过bugly的更新组件,提供自动检查更新和应用下发。
How To Config
常规初始化
- 引入依赖
implementation 'com.tencent.bugly:crashreport:3.4.4'
implementation 'com.tencent.bugly:nativecrashreport:3.7.700'
- ndk引入
android {
***
defaultConfig {
//ndk支持架构
ndk {
//设置支持的SO库架构。在集成Bugly SO库时,请注意只保留支持的架构SO库。
abiFilters 'armeabi' , 'x86', 'armeabi-v7a', 'x86_64', 'arm64-v8a'
}
}
}
NDK integration is deprecated in the current plugin. Consider trying the new experimental plugin.
则在项目根目录的gradle.properties文件中添加:android.useDeprecatedNdk=true
- 混淆配置
-dontwarn com.tencent.bugly.**
-keep public class com.tencent.bugly.**{*;}
- 权限配置
<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" />
<uses-permission android:name="android.permission.READ_LOGS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
注:如果您的App需要上传到google play store,您需要将READ_PHONE_STATE权限屏蔽掉或者移除,否则可能会被下架。
配置FileProvider
如果您想兼容Android N或者以上的设备,必须要在AndroidManifest.xml文件中配置FileProvider来访问共享路径的文件。 这里要注意一下,FileProvider类是在support-v4或androidx包中的,检查你的工程是否引入该类库。
- AndroidMenifest.xml
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="你的应用包名.fileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
- 新建res/xml目录:xml/provider_paths的编写
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="beta_external_path" path="Download/"/>
<external-path name="beta_external_files_path" path="Android/data/"/>
</paths>
其他方式初始化(可跳过)
其他的配置方法AndroidMenifest.xml
此外,Bugly2.0及以上版本还支持通过“AndroidManifest.xml”来配置APP信息。如果同时又通过代码中配置了APP信息,则最终以代码配置的信息为准。
- AndroidMenifest.xml
<application
<!-- 配置APP ID -->
<meta-data
android:name="BUGLY_APPID"
android:value="<APP_ID>" />
<!-- 配置APP版本号 -->
<meta-data
android:name="BUGLY_APP_VERSION"
android:value="<APP_Version>" />
<!-- 配置APP渠道号 -->
<meta-data
android:name="BUGLY_APP_CHANNEL"
android:value="<APP_Channel>" />
<!-- 配置Bugly调试模式(true或者false)-->
<meta-data
android:name="BUGLY_ENABLE_DEBUG"
android:value="<isDebug>" />
</application>
- Application的初始化变为
CrashReport.initCrashReport(getApplicationContext());
How To Use
- 初始化
class MainApplication : Application() {
override fun onCreate() {
super.onCreate()
CrashReport.initCrashReport(this, "你的APPID", false)
}
}
- 建议在测试阶段建议设置成true,发布时设置为false。
- 为了保证运营数据的准确性,建议不要在异步线程初始化Bugly。
- 测试
- 测试Crash
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
...
CrashReport.testJavaCrash()
}
}
- 测试Throwable,主动上报功能
CrashReport.postCatchedException(Throwable("1111"))
注意事项
- 分包
如果使用了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都会进行数据上报,造成不必要的资源浪费。
因此,为了节省流量、内存等资源,建议初始化的时候对上报进程进行控制,只在主进程下上报数据:判断是否是主进程(通过进程名是否为包名来判断),并在初始化Bugly时增加一个上报进程的策略配置。
Context context = getApplicationContext();
// 获取当前包名
String packageName = context.getPackageName();
// 获取当前进程名
String processName = getProcessName(android.os.Process.myPid());
// 设置是否为上报进程
UserStrategy strategy = new UserStrategy(context);
strategy.setUploadProcess(processName == null || processName.equals(packageName));
// 初始化Bugly
CrashReport.initCrashReport(context, "注册时申请的APPID", isDebug, strategy);
// 如果通过“AndroidManifest.xml”来配置APP信息,初始化方法如下
// CrashReport.initCrashReport(context, strategy);
- 其中获取进程名的方法“getProcessName”有多种实现方法,推荐方法如下:
/**
* 获取进程号对应的进程名
*
* @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;
}