APP的错误收集产品有很多,例如友盟统计、阿里云等。本文讨论的是由腾讯开发的Bugly。在使用的时候在网上找了一下,发现有一个插件(https://github.com/canyara/react-native-bugly)。至于这个插件的使用,我估计我的道行不够吧,总之搞不通。然后在直接按照官方的文档配置的,可以统计了。
本文分三部分:第一部分是讲解原理、第二部分是原理讲解、第三部分是配置并演示。
在 ReactNative 的程序中,实际上运行的是 Js 的代码,而它也是分 Debug 和 Release 的。
在 Debug 模式下,会从本地开启一个 Packager 服务,然后 App 运行起来之后,直接从服务里拉取最新的编译后的 JS 代码,这样可以在开发阶段,做到代码实时更新的效果,只需要在设备上,重新 Load 一下即可。
在 Release 模式下,ReactNative 会将 JS 代码,整体打包,然后放到 assets 目录下,然后从这里去加载 JS 代码。
这样的逻辑被封装在 ReactInstanceManager 类的 recreateReactContextInBackgroundInner()
方法中,有兴趣可以自行看看。
ReactNative 在 Debug 的情况下,如果出现崩溃的 Bug,会直接出现红屏,提示你崩溃的栈的具体信息,这些内容可以帮助你快速的定位问题。如果在Release模式下,则出现闪退(或者ANR)。
Android 举例:
Android打包时会把,所有的JS文件,混淆并且压缩到asstes文件夹下的index.android.bundle中。图:2.2-1
该文件生成的原理是ReactNative使用了如下命令处理(node/modules/react.gradle 代码片段)
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
commandLine("cmd", "/c", *nodeExecutableAndArgs, cliPath, bundleCommand, "--platform", "android", "--dev", "${devEnabled}",
"--reset-cache", "--entry-file", entryFile, "--bundle-output", jsBundleFile, "--assets-dest", resourcesDir, *extraArgs)
} else {
commandLine(*nodeExecutableAndArgs, cliPath, bundleCommand, "--platform", "android", "--dev", "${devEnabled}",
"--reset-cache", "--entry-file", entryFile, "--bundle-output", jsBundleFile, "--assets-dest", resourcesDir, *extraArgs)
}
对于Debug模式下,报错了直接红屏并显示报错的地方。但是Release模式应用程序报错则程序就崩溃了,无法查得原因。因此集成Bugly进行Bug收集。而使用Bugly收集Bug时得到是混淆并压缩版的错误,这样无法定位到错误的地方。
从图中可以看出报错的是344行、868列(value@334:868),报错原因是找不到变量(Can't find variable...),然后我们找到3.2步骤的压缩文件相应的地方。
可以在文件中找到了此处,这里能看到是Button找不到,但是这只是一个演示Demo当,内容不懂。当项目大了内容就多了,一个一个Button的找?所以得找到映射文件。细节将在第三章讲解。
切入正题,配置项目,集成Bugly。
(使用QQ登录,然后配置APP信息获取APP ID,傻瓜式的操作很容易)
地址:https://bugly.qq.com
android {
...
defaultConfig {
...
ndk {
abiFilters "armeabi-v7a", "x86"
}
packagingOptions {
exclude "lib/arm64-v8a/libimagepipeline.so"
}
}
...
dependencies {
...
compile 'com.tencent.bugly:crashreport:latest.release' //其中latest.release指代最新Bugly SDK版本号,也可以指定明确的版本号,例如2.2.0
compile 'com.tencent.bugly:nativecrashreport:latest.release' //其中latest.release指代最新Bugly NDK版本号,也可以指定明确的版本号,例如3.0
}
导入包
import com.tencent.bugly.crashreport.CrashReport;
在onCreate()方法中添加:
@Override
public void onCreate() {
super.onCreate();
CrashReport.initCrashReport(getApplicationContext(), "f7b76b8463", false); //添加此句话 f7b76b8463 为App Id
...
}
此处使用的测试Demo,大家可以自行搞一个报错的进行演示。在DetailsScreen下使用Button组件,在此我将,Button不引入,导致报错
将此APP签名打包,运行时点击详情页,程序闪退。 打开Bugly的控制台,可以看到如下错误,在@342:1028 (分别表示行列)。
然后在项目的根目录执行如下命令:(此处是生成映射文件)
$ react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res/ --sourcemap-output android-release.bundle.map
此时你会发现在项目的根目录中出现android-release.bundle.map文件,打开可以看到里面就是assets下的index.android.bundle映射文件。
在项目根部新建文件analyze/analyzeAndroid.js(此处的目的是使用node自带的解析功能个)
在文件中添加内容如下:
var sourceMap = require('source-map');
var fs = require('fs');
fs.readFile('../android-release.bundle.map', 'utf8', function (err, data) {
var smc = new sourceMap.SourceMapConsumer(data);
console.log(smc.originalPositionFor({
line: 344, //报错的行
column: 868 //报错的列
}));
});
运行JS会得到如下的内容:
可以看到定位到报错的地方。
填入如下内容:
target:"NavigationActions" do
pod 'Bugly'
end
NavigationActions为项目名,Bugly为添加的依赖,然后进入ios目录下,运行命令:$ pod install (注意:执行此命令时请关闭所有Xcode的会话,模拟器一并关闭,防止撞鬼)
打开项目后点击Product --> Clean 然后 再 Product --> Build (注意此步非常重要,因为新增了Bugly库,不Build的项目会报错)
Build后会提示错误:Library not fount for -LPods-项目名称 例如下图。
解决方案:
移除报错的Library,然后重新Clean Build即可。
打开AppDelegate.m文件
在图中的位置添加图中的内容,#import
在Xcode的菜单栏中,选择Product --> Schame --> Edit Schame ...
运行Release版本。运行设备上,同样点击详情按钮,出现闪退。
在Bugly控制台中可以看到如下的错误:
可以看到报错的行列分别是 344行 868列。
在项目的根目录下运行命令(此处是生成映射文件)
$ react-native bundle --platform ios --dev false --entry-file index.js --bundle-output ios-release.bundle --sourcemap-output ios-release.bundle.map
在项目的根目录中可以看到多了个文件ios-release.bundle,接着在项目根部新建文件analyze/analyzeIOS.js(此处的目的是使用node自带的解析功能个)
在文件中添加内容如下:
var sourceMap = require('source-map');
var fs = require('fs');
fs.readFile('../ios-release.bundle.map', 'utf8', function (err, data) {
var smc = new sourceMap.SourceMapConsumer(data);
console.log(smc.originalPositionFor({
line: 344, //报错的行
column: 868 //报错的列
}));
});
运行JS会得到如下的内容:
可以看到定位到报错的地方。
为了方便打击更快集成Bugly所以写下了这篇文章。创作不易,如果这边文章对您有所帮助,就帮我点个赞,鼓励下我吧。
最后感谢@承香墨影的博客的博客,本文很多地方出自他的内容,谢谢作者。
传送门:
@承香墨影的博客的文章:https://blog.csdn.net/plokmju88/article/details/78519317#commentBox
Bugly的首页:https://bugly.qq.com
Android配置指南:https://bugly.qq.com/docs/user-guide/instruction-manual-android/?v=20180709165613
IOS配置指南:https://bugly.qq.com/docs/user-guide/instruction-manual-ios/?v=20180713114028