mPaaS方式部署
SDK 目录结构
nbs-newlens-android-sdk
--> tingyun-ea-agent-android-version.aar
--> nbs.newlens.nativecrash-version.aar
--> nbs.newlens.android.log-version.aar
--> tingyun-javaleak-version.aar
--> tingyun-basemonitor-version.aar
--> tingyun-android-base-version.aar
--> tingyun-dump-version.aar
--> shark-verison.jar
--> bcpkix-jdk15to18-version.jar
--> bcprov-jdk15to18-version.jar
--> rewriter
--> nbs.newlens.class.rewriter-version.jar
--> nbs.newlens.so.parser-version.jar
--> agent-gradle-plugin-version.jar
--> json.jar
壳项目(portal)添加依赖
在 project 级别的 build.gradle 文件中添加以下内容。
buildscript {
dependencies {
classpath fileTree(dir: 'rewriter', include: ['*.jar'])//将 sdk 的 rewriter 文件夹解压到 project 级别的 build.gradle 文件同级目录下,rewriter 文件夹中的 jar 包仅在编译时使用,不会打包到 apk 中
}
}
allprojects {
repositories {
flatDir {
dirs 'libs'
}
}
}
在 app 级别的 build.gradle 文件中添加以下内容。
apply plugin: 'newlens'
dependencies {
// 将 sdk 复制到 portal 项目 libs 目录下
//请将「Version」更改具体版本号
implementation(name: 'tingyun-ea-agent-android-version', ext: 'aar')
implementation(name: 'nbs.newlens.nativecrash-version', ext: 'aar') // 采集 natvie crash 需集成此包
implementation(name: 'nbs.newlens.android.log-version', ext: 'aar') // 日志回捞需集成此包
// 采集 OOM 数据需要 kotlin-gradle-plugin 插件 1.3+ ,并依赖 androidx.core:core-ktx、androidx.appcompat:appcompat、androidx.lifecycle:lifecycle-process、com.squareup.okio:okio 等库
implementation(name: 'tingyun-javaleak-version.aar', ext: 'aar') // 采集OOM 需集成此包
implementation(name: 'tingyun-basemonitor-version.aar', ext: 'aar') // 采集 OOM 需集成此包
implementation(name: 'tingyun-android-base-version', ext: 'aar') // 采集OOM 需集成此包
implementation(name: 'tingyun-dump-version', ext: 'aar') // 采集 OOM 需集成此包
implementation files('libs/shark-version.jar') // 采集 OOM 需集成此包
implementation files('libs/bcpkix-jdk15to18-version.jar') // 启用国密加密需集成此包
implementation files('libs/bcprov-jdk15to18-version.jar') // 启用国密加密需集成此包
}
子项目(bundle)添加依赖
每个 bundle 都需要配置嵌码,在 project 级别的 build.gradle 文件中添加以下内容。
buildscript {
dependencies {
classpath fileTree(dir: 'rewriter', include: ['*.jar'])//将 sdk 的 rewriter 文件夹解压到 project 级别的 build.gradle 文件同级目录下,rewriter 文件夹中的 jar 包仅在编译时使用,不会打包到 apk 中
}
}
在 app 级别的 build.gradle 文件中添加以下内容。
apply plugin: 'newlens'
若插件中需要调用 SDK 中的方法,在 app 级别的 build.gradle 文件中添加以下内容。
dependencies {
// 将 tingyun-ea-agent-android-version.aar 复制到 bundle 项目 libs 目录下
compileOnly fileTree(include: ['*.aar'], dir: 'libs')
}
设置 Application
在 portal 中需使用自定义的 Application。
public class MyApp extends com.alipay.mobile.quinox.LauncherApplication {
@Override
public void onCreate() {
super.onCreate();
}
}
在 portal 的 AndroidMainfest 中配置 Application。
<application
android:name=".MyApp"
>
添加 SDK
获取 AppKey
初始化 SDK
在 Application 中的 onCreate() 方法初始化 SDK。
//"Appkey" 请从基调听云平台获取
//"Host" 为基调听云平台「Redirect」服务器地址,无需添加协议头
NBSAppAgent.setLicenseKey("AppKey").setRedirectHost("Host").startInApplication(this.getApplicationContext());
SDK 默认以 Https 上传数据,若服务端只支持 Http,需设置 「setHttpEnabled(true)」。
NBSAppAgent.setLicenseKey("AppKey").setRedirectHost("Host").setHttpEnabled(true) .startInApplication(this.getApplicationContext());
权限配置说明
SDK 为了与服务端交互「网络权限」为必要权限。
<!--必要权限,用以与服务端交互-->
<uses-permission android:name="android.permission.INTERNET"/>
<!--非必要权限,用以获取当前设备的网络状态和WiFi状态,如:3G、4G、5G、WiFi,建议添加-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!--非必要权限,用以获取 targetSdkVersion 29 及以上、 Android 10 及以上设备的网络状态-->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!--非必要权限,用以使用「可视化操作命名功能」-->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW"/>
<!--非必要权限,用以获取当前移动网络连接的基站信息-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
首次启动开启模块功能开关
出于兼容性考虑, 首次启动 SDK 仅在调试模式下开启全部功能模块,非调试模式下仅开启崩溃模块,可通过以下接口开启 SDK 的模块开关。
- 模块功能开关接口
/*
SDK首次初始化由于尚未与基调听云平台交互,默认模块开关仅开启「崩溃模块」,可以通过本接口自定义首次启动开启的模块。
@warning:调用该接口设置启动选项,SDK首次启动不受基调听云平台开关控制
*/
NBSAppAgent.setStartOption(int option);
- 代码示例
//在SDK初始化时调用, 首次启动全部功能模块
NBSAppAgent.setLicenseKey("AppKey").setRedirectHost("Host").setStartOption(511).start(this.getApplicationContext());//首次初始化开启全部功能
网络插码
项目需实现自定义的 RpcInterceptor,并在各个方法中添加听云 NBSInterceptorHelper 的对应方法。
// mpaas rpc 只能添加一个拦截器,若项目中已存在拦截器,可以直接在拦截器的回调方法中调用 NBSInterceptorHelper 相应方法即可。
rpcService.addRpcInterceptor(OperationType.class, new CommonInterceptor());
public class CommonInterceptor implements RpcInterceptor {
private Handler handler = new Handler(Looper.getMainLooper());
@Override
public boolean preHandle(Object o, ThreadLocal<Object> threadLocal, byte[] bytes, Class<?> aClass, Method method, Object[] objects, Annotation annotation, ThreadLocal<Map<String, Object>> threadLocal1) throws RpcException {
RpcInvocationHandler rpcInvocationHandler = (RpcInvocationHandler) Proxy.getInvocationHandler(o);
RpcInvokeContext rpcInvokeContext = rpcInvocationHandler.getRpcInvokeContext();
com.networkbench.agent.impl.instrumentation.NBSInterceptorHelper.preHandle(annotation, rpcInvokeContext);
return true;
}
@Override
public boolean postHandle(Object o, ThreadLocal<Object> threadLocal, byte[] bytes, Class<?> aClass, Method method, Object[] objects, Annotation annotation) throws RpcException {
RpcInvocationHandler rpcInvocationHandler = (RpcInvocationHandler) Proxy.getInvocationHandler(o);
RpcInvokeContext rpcInvokeContext = rpcInvocationHandler.getRpcInvokeContext();
com.networkbench.agent.impl.instrumentation.NBSInterceptorHelper.postHandle(annotation, rpcInvokeContext);
return true;
}
@Override
public boolean exceptionHandle(Object o, ThreadLocal<Object> threadLocal, byte[] bytes, Class<?> aClass, Method method, Object[] objects, final RpcException e, Annotation annotation) throws RpcException {
//SDK 定义了部分网络错误码,如,未知主机901、建连失败902、连接超时903、SSL错误908等,未定义的错误码报表不会展示,您可以根据需要需对 mpaas 的错误码进行转换
int errorCode = e == null ? 0 : e.getCode();
switch (errorCode) {
case 0 :
errorCode= 900;break;
case 1 :
errorCode= 900;break;
case 2 :
errorCode= 901;break;
case 3 :
errorCode= 908;break;
case 4 :
errorCode= 903;break;
case 5 :
errorCode= 903;break;
case 6 :
errorCode= 900;break;
case 7 :
errorCode= 900;break;
case 8 :
errorCode= 900;break;
case 9 :
errorCode= 902;break;
case 10 :
errorCode= 900;break;
case 13 :
errorCode= 900;break;
case 15 :
errorCode= 902;break;
case 16 :
errorCode= 901;break;
case 18 :
errorCode= 900;break;
}
com.networkbench.agent.impl.instrumentation.NBSInterceptorHelper.exceptionHandle(annotation, errorCode);
return true;
}
}
内嵌 WebView 插码
SDK 支持对 MPNebula.startUrl() 、MPNebula.startApp() 等方法自动采集 H5 数据,无需额外配置。
若项目使用内嵌 WebView 方式,需要手动埋点。
- 相关接口
/**
* @param h5Page H5Page 对象
* @param apWebViewClient 若存在自定义的 APWebViewClient 实现类,传入该对象,否则传 null
* @param apWebChromeClient 若存在自定义的 APWebChromeClient 实现类,传入该对象,否则传 null
*/
NBSNebulaWebViewConfig.configWebView(H5Page h5Page, APWebViewClient apWebViewClient, APWebChromeClient apWebChromeClient);
- 代码示例
MPNebula.getH5ViewAsync(this, param, new H5PageReadyListener() {
@Override
public void getH5Page(H5Page h5Page) {
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
// 不存在自定义的 APWebViewClient 或 APWebChromeClient 时,只需传入 h5Page 对象
NBSNebulaWebViewConfig.configWebView(h5Page, null, null);
mLayout.addView(h5Page.getContentView(), lp);
}
});
获取用户标识
通过添加「用户标识」可在基调听云报表平台通过该标识检索到具体用户的性能问题。
- 相关接口
//userIdentifier 最多包含64个字符,支持中文、英文、数字、下划线,但不能包含空格或其他的转义字符
NBSAppAgent.setUserIdentifier(String userIdentifier);
- 代码示例
public class MainActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String userIdentifier = getUserID();
NBSAppAgent.setLicenseKey("AppKey").withLocationServiceEnabled(true)
.start(this.getApplicationContext());
//用户标识可为邮箱、手机号等能够标识用户身份的信息,如:xxx@tingyun.com
NBSAppAgent.setUserIdentifier(userIdentifier);
}
}
启用国密加密
SDK 支持国密加密方式发送数据。
注意:
国密加密只支持 Android 6.0 及以上版本,启用国密加密后,安卓 5.x 及以下版本 SDK 将不采集数据。
启用国密需集成 bcpkix-jdk15to18-version.jar 和 bcprov-jdk15to18-version.jar。
服务端也需要同步开启国密加密功能。
- 相关接口
//isEncryptionRequired 默认 false,设置为 true 启用国密加密
NBSAppAgent.encryptionRequired(boolean isEncryptionRequired)
- 代码示例
NBSAppAgent.setLicenseKey("AppKey").setRedirectHost("Host")
.encryptionRequired(true)// 启用国密加密
.start(this.getApplicationContext());
配置混淆
在proguard混淆配置文件中增加以下内容,以免 SDK不可用。
# ProGuard configurationsfor NetworkBench Lens
-keep class com.networkbench.** { *; }
-dontwarn com.networkbench.**
-keepattributes Exceptions, Signature, InnerClasses
# End NetworkBench Lens
若项目使用了 OkHttp 3,请在 proguard.cfg 中添加以下内容,以免影响网络指标采集。
-keep class okhttp3.** { *;}
-dontwarn okhttp3.**
若项目启用了国密,请在 proguard.cfg 中添加以下内容,以免影响数据采集。
-keep class org.bouncycastle.**{ *;}
-dontwarn org.bouncycastle.**
若需要保留行号信息,请在proguard.cfg 中添加以下内容。
-keepattributes SourceFile,LineNumberTable
打包编译
先打包子项目 bundle,再打包壳项目 portal。
嵌码验证
嵌码完成后可通过 “LogCat” 查看听云 SDK 日志输出结果,用以进行数据收集服务器校验TAG为NBSAgent,标准日志输出结果如下所示:
NBSAgent start
NBSAgent enabled
NBSAgent V “TingYun_Version” //TingYun_Version 为当前SDK的版本号
connect success
附录(可选配置)
开启可视化命名
开启可视化命名功能,可以通过在 App 应用内点选的方式为「原生页面」和「操作」进行重命名并在用户体验模块中展示。
获取 Scheme。
在应用「设置」中的「修改设置」中选择【URL Scheme】。
在 AndroidMainfest.xml 文件的「LAUNCHER Actvitiy」中增加 scheme 配置,如下所示:
<activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <!--请添加这里的整个intent-filter区块,并确保其中只有一个data字段--> <intent-filter> <data android:scheme="tingyun.xxxx" /> <!--请将 scheme 中的“tingyun.xxxx”替换为基调听云报表设置页面中的 URL Scheme--> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.BROWSABLE"/> </intent-filter> <!--请添加这里的整个intent-filter区块,并确保其中只有一个data字段--> </activity>