移动端接入指引
1 移动端CrashSight接入说明
本文是介绍移动端SDK的详细文档,内容包含了iOS和Android两个平台SDK接入的内容,并详细介绍 了两个平台所支持的接口. 如果想快速接入,验证平台和SDK功能,建议查看项目菜单中的“接入指南”。引导中已经按项目具体的信息(平台,引擎,国内/海外,AppID)生成了针对此项目的初始化代码,可以直接复制使用。如下图所示:
项目创建:公司外部项目支持自助创建项目,但有免费试用时长。公司内部项目,企业微信联系“CrashSight小助手”开通。
2 iOS SDK集成
2.1 CocoaPods集成
-
在Podfile中添加 pod 'CrashSight'
-
运行pod install 或 pod update 命令
-
从.xcworkspace文件进入工程(而非.xcodeproj文件)
2.2 手动集成
- 在平台成功创建项目后,在侧边栏的“接入指南”中,选择接入方式,然后在“SDK下载及接入”页中下载SDK。如下图所示:
- iOS SDK依赖添加
- 拖拽CrashSight.framework文件到Xcode工程内(请勾选"Copy items if needed"选项)
- 添加依赖库
- libc++.dylib 或 libc++.tdb 用于引入c++标准库
- libz.dylib 或 libz.tdb 用于对上报的数据进行压缩
- Security.framework 用于存储keychain
- SystemConfiguration.framework 用于读取异常发生时的系统信息
- MetricKit.framework 用于获取apple提供的app诊断信息(弱引用,请选择“optional”)
- OSLog.framework 用于获取NSLog日志信息(弱引用,请选择“optional”)
- CFNetwork.framework 用于获取VPN状态
2.3 SDK初始化
2.3.1 Objective-C初始化
-
在工程的AppDelegate.m文件导入头文件
#import <CrashSight/CrashSight.h>
-
初始化 在工程AppDelegate.m文件的
application:didFinishLaunchingWithOptions:
方法中初始化
CrashSightConfig* config = [[CrashSightConfig alloc] init];
// 自定义设置上报域名(可选)
config.crashServerUrl = @"http://xxxx";
config.debugMode = true;//打开debug mode
NSString* appId = @"appId";
[CrashSight startWithAppId:appId config:config];
2.3.2 Swift初始化
- 创建一个Objective-C Bridging Header(如果项目中原来没有的话) · 新建一个.h文件 · 找到Build Settings->Swift Compiler-General->Objective-C Bridging Header,将刚刚创建的.h文件的路径填入
- 在Objective-C Bridging Header中导入头文件
#import <CrashSight/CrashSight.h>
- 在XXXApp.swift中添加初始化代码
@main
struct XXXApp: App {
init() {
let config = CrashSightConfig();
config.crashServerUrl = "http://xxxx";
config.debugMode = true;
let appId = "appId";
CrashSight.start(withAppId:appId,config:config);
}
...
上报域名
2.4 接入结果测试
在初始化CrashSight的之后,通过按键触发崩溃。 当前iOS移动端还没有添加崩溃测试接口(后续会补充),可以编写一个简单的崩溃触发代码,如非法内存访问:
int* a = NULL;
a[10000] = 5;
- a. 开启Debug模式,初始化CrashSight,并给定合适的配置参数
- b. 联网上报:检查测试设备日志中是否打印“begin to upload <CSAnalyticsLogic” 或者 “cmd: 641”
- c. 崩溃捕获:检查测试设备日志中是否打印“Handle the crash scene in callback”
- d. 上报异常:检查测试设备日志中是否打印“begin to upload <CSCrashLogic” 或者 “cmd: 631”
3 iOS 接口说明
3.1 使用指定配置初始化CrashSight
类:CrashSight
方法:+ (void)startWithAppId:(NSString * CS_NULLABLE)appId
developmentDevice:(BOOL)development
config:(CrashSightConfig * CS_NULLABLE)config;
参数 | 类型 | 说明 |
---|---|---|
appid | NSString * | 从CrashSight后台申请的appid |
development | BOOL | 是否是开发设备 |
config | CrashSightConfig * | 详情参考CrashSightConfig.h 头文件 |
3.2 设置用户标识
类:CrashSight
方法:+ (void)setUserIdentifier:(NSString *)userId;
参数 | 类型 | 说明 |
---|---|---|
userId | NSString * | 用户标识 |
3.3 设置应用版本信息
类:CrashSight
方法:+ (void)updateAppVersion:(NSString *)version;
参数 | 类 型 | 说明 |
---|---|---|
version | NSString * | 应用版本 |
3.4 设置关键数据,随崩溃信息上报
说明:设置用户自定义的 Key-Value 数据,将在发送 Crash 时随异常信息一起上报,单个key长度限制100字符,单个value限制1000字符,总长度(所有key+value)限制128KB
页面查看:崩溃详情页->附件下载->CustomizedData.txt
类:CrashSight
方法:+ (void)setUserValue:(NSString *)value
forKey:(NSString *)key;
参数 | 类型 | 说明 |
---|---|---|
key | NSString * | 键 |
value | NSString * | 值 |
3.5 设置场景标记
类:CrashSight
方法:+ (void)setUserSceneTag:(NSString *)userSceneTag;
参数 | 类型 | 说明 |
---|---|---|
userSceneTag | NSString * | 场景标记 |
3.6 上报自定义错误
类:CrashSight
方法:+ (void)reportExceptionWithCategory:(NSUInteger)category
name:(NSString *)aName
reason:(NSString *)aReason
callStack:(NSArray *)aStackArray
extraInfo:(NSDictionary *)info
terminateApp:(BOOL)terminate;
参数 | 类型 | 说明 |
---|---|---|
category | NSUInteger | 错误类型:ocoa=3,CSharp=4,JS=5,Lua=6 |
aName | NSString * | 名称 |
aReason | NSString * | 错误原因 |
aStackArray | NSArray * | 堆栈 |
info | NSDictionary * | 附加数据,不应超过500对,总长度不超过1Mb |
terminate | BOOL | 上报后是否退出应用进程 |
页面查看:
info:崩溃详情页->附件下载->extraMessage.txt
3.7 设置上报日志级别
类:CrashSightLog
方法:+ (void)initLogger:(CrashSightLogLevel) level consolePrint:(BOOL)printConsole;
参数 | 类型 | 说明 |
---|---|---|
level | CrashSightLogLevel | 上报日志的最低级别限制 |
printConsole | BOOL | 是否在控制台打印 |
3.8 自定义上报日志
说明:限制30KB
类:CrashSightLog
方法:+ (void)level:(CrashSightLogLevel) level log:(NSString *)format, ... NS_FORMAT_FUNCTION(2, 3);
参数 | 类型 | 说明 |
---|---|---|
level | CrashSightLogLevel | 日志级别 |
format | NSString * | 日志format |
... | 可变参数 |
3.9 设置异常回调
类:CrashSightDelegate
代理属性:delegate
代理协议:CrashSightDelegate
代理协议方法:- (NSString * CS_NULLABLE)attachmentForException:(NSException * CS_NULLABLE)exception callbackType:(CSCallbackType)callbackType;
说明:代理协议方法返回的结果,随异常上报一起上报 页面 查看:崩溃详情页->附件下载->CrashAttach.log
callback type对照表:
callback type | 异常类型 |
---|---|
0 | Java crash |
2 | Native crash |
3 | c# exception |
4 | ANR |
5 | JS exception |
6 | lua exception |
8 | custom error |
4 Android SDK 集成
CrashSight Android SDK接入流程如下:
4.1 maven集成
a. 项目build.gradle里添加腾讯maven镜像(Gradle7.0以下):
allprojects {
repositories {
maven {
url "https://mirrors.tencent.com/nexus/repository/maven-public"
}
}
}
如果使用Gradle7.0及以上版本,则在setting.gradle中添加:
dependencyResolutionManagement {
repositories {
maven {
url "https://mirrors.tencent.com/nexus/repository/maven-public"
}
}
}
b. 模块build.gradle里添加依赖:
dependencies {
implementation 'net.crashsight:crashsight-android:4.2.14'
}
4.2 手动集成
在平台成功创建项目后,在侧边栏的“接入指南”中,选择接入方式,然后在“SDK下载及接入”页中下载SDK。如下图所示:
- 如果您的工程有Native代码(C/C++)或者集成了其他第三方SO库,建议集成CrashSight的NDK动态库。 CrashSight NDK包含多个架构的SO库:
- armeabi
- armeabi-v7a
- arm64-v8a
- x86
- x86_64
在集成CrashSight SO库时,请注意只保留支持的架构SO库。
Android Studio工程
- 将CrashSight库文件复制到工程的libs目录下;
- 如果集成CrashSight NDK,则在Module的buid.gradle文件中添加SO库目录配置:
android {
sourceSets {
main.jniLibs.srcDirs = ['libs']
}
}
- 点击Sync,同步配置。
为了使APP Crash堆栈的可读性更高,建议您配置符号表文件,更准确地定位问题:
- 纯Java代码的工程:只需要配置混淆后生成的Mapping文件即可;
- 含有Native代码的工程:建议配置符号表工具从Debug SO中提取的Symbol符号表文件。 CrashSight支持手动和自动配置两种方式,具体的配置方法请参考:《CrashSight Android符号表配置》
4.3 参数 配置
- 在AndroidManifest.xml中添加权限:
<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" />
注:如果您的App需要上传到 google play store,您需要将READ_PHONE_STATE 权限屏蔽掉或者移除,否则可能会被下架。
- 请避免混淆CrashSight,在Proguard混淆文件中增加以下配置:
-dontwarn com.uqm.crashsight.**
-keep public class com.uqm.crashsight.**{*;}
4.4 简单的初始化
获取APP ID并将以下代码复制到项目Application类onCreate()中,CrashSight会为自动检测环境并完成配置:(为了保证运营数据的准确性,建议不要在异步线程初始化CrashSight。 )
// 设置上报地址
CrashReport.setServerUrl(serverUrl);
//初始化
CrashReport.initCrashReport(getApplicationContext(), "注册时申请的APPID", false);
第三个参数为SDK调试模式开关,调试模式的行为特性如下:
- 输出详细的CrashSight SDK的Log;
- 每一条Crash都会被立即上报;
- 自定义日志将会在Logcat中输出;
- 关闭错误合并功能,所有错误逐条上报。
建议在测试阶段建议设置成true,发布时设置为false。
上报地址
- 国内公有云 https://android.crashsight.qq.com/pb/async
- 海外公有云 https://android.crashsight.wetest.net/pb/async
4.5 MultiDex注意事项
如果使用了MultiDex,建议通过Gradle的"multiDexKeepFile"配置等方式把CrashSight的类放到主Dex,另外建议在Application类的"attachBaseContext"方法中主动加载非主dex:
public class MyApplication extends SomeOtherApplication {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(context);
Multidex.install(this);
}
}
4.6 配置native库提取
未提取的native库会导致获取的崩溃堆栈无法还原。这种情况的表现为,堆栈中的崩溃模块是xx.apk而非xx.so,不能定位到具体的库。 为了避免未提取的native库对堆栈还原造成影响,请做如下配置:
- 打包APK时,在AndroidManifest.xml中配置android:extractNativeLibs="true"
<application
...
android:extractNativeLibs="true">
- 打包AAB时,在gradle.properties文件中添加:
enableUncompressedNativeLibs = false
通过添加此参数,操作系统可以在应用程序崩溃时提供额外的信息,以帮助分析崩溃的原因。
4.7 接入结果测试
现在您可以制造一个Crash(建议通过“按键”来触发),来体验CrashSight的能力了。在初始化CrashSight的之后,调用CrashSight测Java Crash接口。
CrashReport.testJavaCrash();
执行到这段代码时会发生一个Crash,Logcat的TAG=CrashSightReport中输出为:
现在您已经可以在“崩溃”页面看到刚才触发的Crash issue了(延迟一般在10s以内)。 如果项目包含了Native工程或者使用了代码混淆,建议配置符号表文件。
4.8 开启Javascript异常捕获功能
CrashSight Android SDK 4.2.12及以上版本提供了Javascript的异常捕获和上报能力,以便开发者可以感 知到 WebView中发生的Javascript异常。
/**
* 设置Javascript的异常监控
*
* @param webView 指定被监控的webView
* @param autoInject 是否自动注入crashsight.js文件
* @return true 设置成功;false 设置失败
*/
CrashReport.setJavascriptMonitor(WebView webView, boolean autoInject)
- “crashsight.js”文件在CrashSight SDK包中, 可以在HTML手动嵌入;
- 如果使用自动集成SDK方式,可以使用自动注入和手动注入两种方式。如果使用自动集成+手动注入的方式 需要下载“crashsight.js”文件;
- 由于Android 4.4以下版本存在反射漏洞,接口默认只对Android 4.4及以上版本有效;
- 接口不会设置webView的WebViewClient和Listener;
- 接口默认会开启webView的JS执行能力;
如果使用了非Android官方的WebView(例如使用X5内核),需要按照以下方法使用:
CrashReport.WebViewInterface webView = new CrashReport.WebViewInterface() {
/**
* 获取WebView URL.
*
* @return WebView URL
*/
@Override
public String getUrl() {
// 下面仅为例子,请用真正逻辑代替
return <第三方WebView对象>.getUrl();
}
/**
* 开启JavaScript.
*
* @param flag true表示开启,false表示关闭
*/
@Override
public void setJavaScriptEnabled(boolean flag) {
// 下面仅为例子,请用真正逻辑代替
WebSettings webSettings = <第三方WebView对象>.getSettings();
webSettings.setJavaScriptEnabled(flag);
}
/**
* 加载URL.
*
* @param url 要加载的URL
*/
@Override
public void loadUrl(String url) {
// 下面仅为例子,请用真正逻辑代替
<第三方WebView对象>.loadUrl();
}
/**
* 添加JavaScript接口对象.
*
* @param jsInterface JavaScript接口对象
* @param name JavaScript接口对象名称
*/
@Override
public void addJavascriptInterface(H5JavaScriptInterface jsInterface, String name) {
// 下面仅为例子,请用真正逻辑代替
<第三方WebView对象>.addJavascriptInterface(jsInterface, name);
}
/**
* 获取WebView的内容描述.
*
* @return WebView的内容描述.
*/
@Override
public CharSequence getContentDescription() {
// 下面仅为例子,请用真正逻辑代替
return <第三方WebView对象>.getContentDescription();
}
};
// 调用CrashSight设置JS异常捕获接口时传入创建的WebView接口对象即可
4.8.1 自动注入
建议在WebChromeClient的onProgressChanged函数中调用接口:
CrashReport.setJavascriptMonitor(webView, true);
例子如下:
WebView webView = new WebView(this);
// 设置WebChromeClient
webView.setWebChromeClient(new WebChromeClient() {
@Override
public void onProgressChanged(WebView webView, int progress) {
// 增加Javascript异常监控
CrashReport.setJavascriptMonitor(webView, true);
super.onProgressChanged(webView, progress);
}
});
// 加载HTML
webView.loadUrl(url);
4.8.2 手动注入
下载crashsight.js文件并添加到需要监控Javascript异常的HTML中:
<html>
<script src="crashsight.js" ></script>
<body>
...
</body>
</html>
在WebView加载完该HTML后设置Javascript的异常捕获功能:
WebView webView = new WebView(this);
// 加载HTML
webView.loadUrl(url);
// 增加Javascript异常监控
CrashReport.setJavascriptMonitor(webView, false);
在CrashSight Android SDK捕获到Javascript异常后,默认会上报以下信息:
- Android设备的相关信息;
- Javascript异常堆栈和其他信息;
- Java堆栈;
- WebView的信息,目前只包括ContentDescription。
5 Android 接口说明
5.1 上报错误
public static void postException(int category, String errorType, String errorMsg, String stack, Map<String, String> extraInfo)
说明:主动上报错误信息
参数 | 类型 | 说明 |
---|---|---|
category | int | 异常类型, C#: 4, js: 5, lua: 6 (Java错误上报用4即可) |
errorType | String | 异常名称 |
errorMsg | String | 异常信息 |
stack | String | 堆栈 |
extraInfo | Map<String, String> | 其他信息,不应超过500对,总长度不超过1Mb |
页面查看:
extraInfo:崩溃详情页->附件下载->extraMessage.txt
5.2 设置用户ID
public static void setUserId(String userId)
说明:设置用户ID,请在初始化之后调用。
参数 | 类型 | 说明 |
---|---|---|
userId | String | 用户ID |
5.3 标记场景
public static void setUserSceneTag(int tagId)
说明: 设置用户ID
参数 | 类型 | 说明 |
---|---|---|
tagId | int | 场景ID |
5.4 添加自定义数据
public static void putUserData(Context context, String key, String value)
设置用户自定义的 Key-Value 数据,将在发送 Crash 时随异常信息一起上报,单个key长度限制100字符,单个value限制1000字符,总长度(所有key+value)限制64KB。支持在回调中使用。
页面查看:
崩溃详情页->附件下载->valueMapOthers.txt
参数 | 类型 | 说明 |
---|---|---|
key | String | 键 |
value | String | 值 |
5.5 自定义日志
import com.uqm.crashsight.crashreport.CrashSightLog;
Verbose级别log:
public static void v(String tag, String content)
Debug级别log
public static void d(String tag, String content)
info级别log
public static void i(String tag, String content)
warn级别log
public static void w(String tag, String content)
error级别log
public static void e(String tag, String content)
说明:自定义日志,限制30KB。安卓不支持在崩溃回调中写入自定义日志。
参数 | 类型 | 说明 |
---|---|---|
tag | String | 标签 |
content | String | 内容 |
5.6 设置回调
说明:设置崩溃、错误上报回调函数。 onCrashHandleStart返回的map键值不应超过500对,总长度不超过1Mb。
页面查看:
onCrashHandleStart:崩溃详情页->附件下载->extraMessage.txt
onCrashHandleStart2GetExtraDatas: 崩溃详情页->附件下载->userExtraByteData
CrashReport.UserStrategy strategy = new CrashReport.UserStrategy(MainActivity.this);
// 设置 CrashSight 回调
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 synchronized Map<String, String> onCrashHandleStart(int crashType, String errorType, String errorMessage, String errorStack) {
// 获得父类的自定义信息 Map
Map<String, String> userDatas = super.onCrashHandleStart(crashType, errorType, errorMessage, errorStack);
if (userDatas == null) {
userDatas = new HashMap<>();
}
for (String k : extraMap.keySet()) {
userDatas.put(k, extraMap.get(k));
}
return userDatas;
}
@Override
public synchronized byte[] onCrashHandleStart2GetExtraDatas(int crashType,
String errorType, String errorMessage, String errorStack) {
// 返回需要上传的byte数组
return "Bytes to return!".getBytes("UTF-8");
}
});
CrashReport.initCrashReport(MainActivity.this, appId, true, strategy);
callback type对照表:
callback type | 异常类型 |
---|---|
0 | Java crash |
2 | Native crash |
3 | c# exception |
4 | ANR |
5 | JS exception |
6 | lua exception |
8 | custom error |