文档

Android SDK

更新时间:

SDK接入流程

步骤

集成内容

本文中的位置

是否必选

附加说明

第一步

引入SDK

查看文档「第一步引入SDK」

必选

第二步

配置权限

查看文档 [第二步配置权限」

必选

第三步

混淆配置

查看文档 [第三步混淆配置

必选

第四步

域名设置

查看文档 [第四步域名配置

必选

第五步

用户账号统计

查看文档 [第五步设置用户标识」

可选

自定义用户ID,设置后在产品后台会同展示用户账号

第六步

初始化

查看文档 [第六步初始化」

必选

第七步

日志打印

查看文档「第七步日志打印」

必选

第八步

功能模块配置

查看文档「第八步功能模块配置」-> 8.1崩溃分析

必选

集成且开关未关闭后自动采集,无需额外配置

查看文档「第八步功能模块配置」-> 8.2 自定义异常接口

必选

上报自定义类型的崩溃上报

查看文档「第八步功能模块配置」-> 8.3 卡顿分析

必选

集成开关未关闭,默认提供,如不需要卡顿分析则需要关闭此功能开关

查看文档「第八步功能模块配置」-> 8.4 网络分析

必选

查看文档「第八步功能模块配置」-> 8.5 启动分析

必选

查看文档「第八步功能模块配置」-> 8.6 内存分析

必选

查看文档「第八步功能模块配置」-> 8.7 APP 打通H5

必选

H5页面分析 APP端需要做的打通操作说明

查看文档「第八步功能模块配置」-> 8.8 原生页面

必选

查看文档「第八步功能模块配置」-> 8.9 采集开关

必选

可关闭崩溃分析、启动分析、网络分析

、内存分析、应用内H5页面分析;不配置默认为开启

查看文档「第八步功能模块配置」-> 8.10 符号表

必选

崩溃问题需要上传符号表才能进行堆栈解析,本文档描述如何获取符号表并上传

附件

DEMO

附录

SDK上报策略

第一步引入SDK

1.Maven地址配置

在工程 build.gradle 配置脚本中 buildscript 和 allprojects 段中添加 sdk maven 仓库地址

buildscript {
	repositories {
                maven { setUrl("https://maven.aliyun.com/repository/central") }
		google()
		jcenter()
	}
	dependencies {
		classpath 'com.android.tools.build:gradle:3.4.0'
                // 按需引入apm性能分析gradle插件
                classpath 'com.lydaas.qtsdk:apm-plugin:1.0.1'
	}
}
allprojects {
	repositories {
                maven { setUrl("https://maven.aliyun.com/repository/central") }
		google()
		jcenter()
		
	}
}

2.组件引用

在工程App对应build.gradle配置脚本dependencies段中添加组件库依赖

dependencies {
	implementation fileTree(include:['*.jar'], dir:'libs')
        //集成统计分析SDK
	implementation 'com.lydaas.qtsdk:qt-px-common:1.6.1.PX'
  
        //apm稳定性SDK库
        implementation 'com.lydaas.qtsdk:apm-crash:1.5.2.1.0.0.3_guomi'
 
        //apm性能SDK库
        implementation 'com.lydaas.qtsdk:apm-efs:1.6.0.001.210_guomi'

}

第二步配置权限

统计SDK需要宿主APP授予如下权限:

权限

用途

ACCESS_NETWORK_STATE

检测联网方式,在网络异常状态下避免数据发送,节省流量和电量。

ACCESS_WIFI_STATE

获取WIFI mac地址,在平板设备或电视盒子上,无法通过IMEI标识设备,我们会将WIFI mac地址作为用户的唯一标识,以便正常提供统计分析服务。

INTERNET

允许应用程序联网和发送统计数据的权限,以便提供统计分析服务。

READ_PHONE_STATE(可选)

获取用户设备的IMEI,通过IMEI对用户进行唯一标识,以便提供统计分析服务。

下面给出AndroidManifest.xml清单文件示例:

<manifest ……>
<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_PHONE_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<application ……>

第三步混淆配置

如果您的应用使用了代码混淆,请添加如下配置,以避免 SDK被错误混淆导致SDK不可用。

-keep class com.umeng.** {*;}
-keep class com.uc.** { *; }
-keep class com.efs.** { *; }

-keepclassmembers class * {
 public <init> (org.json.JSONObject);
}
-keepclassmembers enum * {
 public static **[] values();
 public static ** valueOf(java.lang.String);
}

SDK需要引用导入工程的资源文件,通过了反射机制得到资源引用文件R.java,但是在开发者通过proguard等混淆/优化工具处理apk时,proguard可能会将R.java删除,如果遇到这个问题,请添加如下配置:

-keep public class [您的应用包名].R$*{
public static final int *;
}

第四步域名设置

在预初始化之前,开发者需要在调用SDK任意其它接口之前最先调用QtConfigure.setCustomDomain()接口设置私有化环境收数域名。

/**
 * 设置上传统计日志的主域名和备用域名。此函数必须在SDK预初始化/初始化函数调用之前调用。SDK会优先将统计数据上报到主域名,失败的情况下会再尝试将数据上报到备用域名。
 * 主域名primaryDomain或不能传入null或者空串,如果传入null或者空串,SDK预初始化函数会抛出SdkDomainUndefined运行时异常。
 * @param standbyDomain 备用域名可以传入null或者空串,此时SDK认为备用域名和主域名完全相同。SDK上传数据失败后第二次也会向主域名上报数据。
 	 * 传入的域名参数应该包含"https://" 前缀。	 
*/
public static void setCustomDomain(String primaryDomain, String standbyDomain)

参数

含义

primaryDomain

上传日志的主域名收集地址。

standbyDomain

上传日志备用域名收集地址。

APM稳定性库相关域名接口:

public static void setCustomDomainCrash(String url)

参数

含义

URL

上传日志的域名收数地址。

APM性能库相关的域名接口:

public static void setCustomDomainCrash(String url)

参数

含义

URL

上传日志的域名收数地址。

示例:

public class MainApplication extends Application {
  
 @Override
 public void onCreate() {
 super.onCreate();

 QtConfigure.setCustomDomain("xxxxxx", null); // 请传入您自己的收数域名
 UMEfs.setCustomDomainEfs("xxxxxx");// 请传入您自己的性能库的收数域名
 UMCrash.setCustomDomainCrash("xxxxxx");// 请传入您自己的稳定性库的收数域名
 
 //打开调试log
 QtConfigure.setLogEnabled(true);
 QtConfigure.preInit(this,"您的appkey","应用商店名称");
 QtTrackAgent.disableActivityPageCollection();

如果数据统计和性能体验使用的是一个收数域名,那么仅需要设置"QtConfigure.setCustomDomain"即可。

第五步用户账号统计

可选功能,与统计分析使用同一套接口,设置后在产品后台会同展示用户账号

1、默认在统计用户时以设备为标准,如果需要统计应用自身的账号,请使用以下接口:

public static void onProfileSignIn(String ID);
public static void onProfileSignIn(String Provider, String ID);

参数

含义

ID

用户账号ID,长度小于64字节

Provider

账号来源。如果用户通过第三方账号登录,可以调用此接口进行统计。支持自定义, 不能以下划线"_"开头,使用大写字母和数字标识,长度小于32 字节; 如果是上市公司,建议使用股票代码。

2、账号登出时需调用此接口,调用之后不再发送账号相关内容。

public static void onProfileSignOff();

第六步初始化

6.1 初始化接口

由于工信部的合规要求,App在用户同意隐私政策前不可以获取任何个人信息,所以初始化为以下操作:

1.预初始化

请在宿主App的Application.onCreate函数中调用基础组件库初始化函数。

// SDK预初始化函数不会采集设备信息,也不会上报数据。 
// preInit预初始化函数耗时极少,不会影响App首次冷启动用户体验
QtConfigure.preInit(this,"您的AppKey","Channel");

2.初始化

请务必在用户同意隐私政策后,再初始化SDK。

// 正式初始化SDK,务必调用 
QtConfigure.init(this,"您的AppKey",QtConfigure.DEVICE_TYPE_PHONE, "");

6.2 Appkey获取

在产品的“管理控制台”——》“应用管理”中,找到您的应用获取。

第七步日志打印

可通过QtConfigure.setLogEnabled(boolean)接口控制LOG的输出。

注意:

  • App正式上线前请关闭SDK运行调试日志。避免无关Log输出。

7.1 日志开关

可以通过调用如下方法控制SDK运行调试日志是否输出,默认情况下SDK运行调试日志关闭。需要用户手动打开。

/**
* 设置组件化的Log开关
* 参数: boolean 默认为false,如需查看LOG设置为true
*/
QtConfigure.setLogEnabled(true);

注意:

  • 如果查看初始化过程中的LOG,一定要在调用初始化方法前将LOG开关打开。

7.2 日志等级

  • 日志分为四种等级,方便用户查看:

  • Error(打印SDK集成或运行时错误信息)。

  • Warn(打印SDK警告信息)。

  • Info(打印SDK提示信息)。

  • Debug(打印SDK调试信息)。

第八步功能模块配置

8.1 崩溃分析

通用崩溃

如您完成common和apm插件的接入,即可使用Java、Native崩溃分析、ANR分析功能,无需额外其他接入操作。

如果您使用我们的SDK捕获native崩溃后,其他捕获工具无法捕获到native 崩溃,可以使用如下方法在初始化SDK后进行设置,使其他SDK可以捕获到native 崩溃

final Bundle customInfo = newBundle();
customInfo.putBoolean("mCallNativeDefaultHandler",true);
CrashApi.getInstance().updateCustomInfo(customInfo);

崩溃回调(自定义字段)

当崩溃发生时,您可以在该回调方法中返回string类型的业务自定义数据,该数据会写入到崩溃文件中并上传到服务器展示。注意:崩溃回调中返回string类型数据的长度限制为256个字符。

接口示例:

UMCrash.registerUMCrashCallback(newUMCrashCallback(){
  
     @Override
     publicString onCallback(){
         return"崩溃时register的自定义内容字符串";
    }
});

上传后即可在错误详情-自定义字段中查看到回调信息

image

8.2自定义异常接口

如果开发者自己捕获了错误,需要手动上传到【QuickTracking】服务器可以调用下面两种方法:

方法一:

public static void UMCrash.generateCustomLog(Throwable e,String type)

参数

含义

e

错误异常

type

自定义错误的类型

方法一示例:

try{ 
 // 抛出异常的代码 
}  catch(Exception e){ 
   UMCrash.generateCustomLog(e,"UmengException"); 
}

方法二:

public static void UMCrash.generateCustomLog(String e,String type)

参数

含义

e

错误异常

type

自定义错误的类型

方法二示例:

String e ="自定义异常代码"; UMCrash.generateCustomLog(e,"UmengException");

使用自定义错误,查看时请在错误列表页面选择【自定义异常】。

8.3卡顿分析

卡顿分析无法做额外配置,默认为开启,如果您需要关闭此采集功能,请参考本文中的采集开关

安卓卡顿分析默认的值为超过2秒计为卡顿,如果您需要设置不同的阈值,可以通过下方的API进行设置,API和示例如下:

/** 设置卡顿阈值的API是通过UMEfs.initConfig(Bundle bundle)方法设置,
 *  bundle对象中传入对应的key为UMEfs.KEY_PA_TIMEOUT_TIME,
 *  对应的值为您设置的卡顿的阈值 *
 **/
Bundle bundle = new Bundle();
bundle.putLong(UMEfs.KEY_PA_TIMEOUT_TIME, 2000L);//设置卡顿阈值为2000L
UMEfs.initConfig(bundle);

注意1: 阈值限制为大于0且小于等于4,非法值无效SDK取默认值2秒设置;

注意2: 需要在初始化之前设置。

8.4网络分析

警告:

请务必在此操作前,完成APM相关功能组件的集成,此操作仅代表自动集成网络监控的方法。

适用范围

  1. 目前网络监控仅支持监控OkHttp网络请求 ,并且需要手动设置eventListenerFactory和NetworkInterceptor

  2. 需要使用OKHttp的最低版本是3.11.0

手动集成

手动集成监控即需要您手动将网络监控 SDK 相关 API 预埋到您项目工程的OkHttp中。

1、设置eventListenerFactory和NetworkInterceptor。

在您build OkHttpClient时,通过OkHttp的eventListenerFactory方法和addNetworkInterceptor方法分别设置事件监听器和拦截器,示例如下:

OkHttpClient okHttpClient = newOkHttpClient.Builder()
//设置事件监听器,OkHttpListener.get()为SDK API
.eventListenerFactory(OkHttpListener.get())
//设置拦截器,new OkHttpInterceptor()为SDK API
.addNetworkInterceptor(new OkHttpInterceptor())
.build();

日志查看是否集成

被采样的状态:打开SDK Log开关,通过NetTrace过滤Logcat信息,可以查看整个网络监控的状态信息,如下:

image

没有被采样的状态:

image

8.5启动分析

概述

启动监控用于监控、还原C端用户启动您App时的真实感知情况。分类如下:

首次启动:App安装后的第一次启动

冷启动:App进程被"杀死"(包括手动方式、被动系统回收等),再次触发启动的过程

热启动:App进程存活,再次触发启动的过程(包括前后台切换、back退出再次进入等)

其中,首次启动和冷启动会对启动过程中进行启动时间的分解监控,包括初始化时长、构建时长、页面加载时长三个指标,热启动则只监控启动时长,监控指标说明如下:

首次启动或冷启动时长:从Application的attachbaseContext()开始到第一个Activity的onResume()结束;

热启动时长:如果退出时的Activity存在则从恢复该Activity的onRestart()开始到onResume()结束,如果退出时的Activity不存在则从Activity的onCreate()开始到onResume()结束。

集成方式

说明

请务必在此操作前,完成U-APM相关功能组件的集成,此操作仅代表自动集成启动监控的方法。

手动集成方式

手动集成监控即需要您手动将启动监控 SDK 相关 API 预埋到您项目工程中。

1、在自定义 Application 的 attachBaseContext()方法开始添加如下代码:

LaunchManager.onTraceApp(this, LaunchManager.APP_ATTACH_BASE_CONTEXT, true);

2、在自定义 Application 的 attachBaseContext()方法最后添加如下代码:

LaunchManager.onTraceApp(this, LaunchManager.APP_ATTACH_BASE_CONTEXT, false);

3、在自定义 Application 的 onCreate()方法最后添加如下代码:

LaunchManager.onTraceApp(this, LaunchManager.APP_ON_CREATE, false);

4、在启动阶段页面展示的 Activity 的 onCreate()方法开始添加如下代码:

LaunchManager.onTracePage(this, LaunchManager.PAGE_ON_CREATE, true);

5、在启动阶段页面展示的 Activity 的 onRestart()方法开始添加如下代码:

LaunchManager.onTracePage(this, LaunchManager.PAGE_ON_RE_START, true);

6、在启动阶段页面展示的 Activity 的 onStart()方法开始添加如下代码:

LaunchManager.onTracePage(this, LaunchManager.PAGE_ON_START, true);

7、在启动阶段页面展示的 Activity 的 onResume()方法最后添加如下代码:

LaunchManager.onTracePage(this, LaunchManager.PAGE_ON_RESUME, false);

8、在启动阶段页面展示的 Activity 的 onStop()方法开始添加如下代码:

LaunchManager.onTracePage(this, LaunchManager.PAGE_ON_STOP, true);

自动集成方式

1、依赖插件。

打开您工程根目录的build.gradle,在dependencies中添加如下:

classpath "com.lydaas.qtsdk:apm-plugin:1.0.1"

注意:确保您已在工程根目录的build.gradle中添加Maven地址。

示例如下:

buildscript {
  repositories {
    //配置 quicktracking sdk maven地址
    maven { setUrl("https://maven.aliyun.com/repository/central") }
    google()
    jcenter()
  }

  dependencies {
      //引入apm性能分析插件 
      classpath 'com.lydaas.qtsdk:apm-plugin:1.0.1' 
  }
}

...

allprojects {
  repositories {
    //配置 quicktracking sdk maven地址
    maven { setUrl("https://maven.aliyun.com/repository/central") }
    google()
    jcenter()
  }
}

2、配置插件。

打开您App的build.gradle添加使用插件,在文件头添加代码如下:

apply plugin: 'com.efs.sdk.plugin'

同时添加插件的相关配置,代码如下:

efs {
    //是否对启动过程进程插桩的开关,如果使用自动集成监控则必须开启,false则不开启启动插件
    enable = true
    //白名单,支持包力度,必须填写,如填写自己应用的包名
    whiteList = [
        "您的包名路径"
    ]
    //⽩名单中包名下配置的Activity,如果有继承关系,例如App内有BaseActivity,其他Activity部
    //分或者全部继承于BaseActivity,需要将BaseActivity配置到⿊名单中,避免插件重复插桩。
    blackList = [
        "您的包名路径"
    ]
}

完整示例:

image

自定义启动阶段数据

概念

如果您想在启动监控过程中加入自定义的监控阶段,比如初始化业务数据(initData)、初始化页面组件(initView)等,您可以使用自定义启动阶段API加入您自定义的启动阶段数据。

注意:

说明

1、自定义启动阶段只支持冷启动阶段,热启动不支持

2、如果自定义启动阶段超过SDK所定义的启动结束时间点,则会被SDK丢弃

方法

在您自定义阶段开始处添加如下API:

注:自定义阶段key长度不可以超过10个字符

/**
* 参数1:上下文
* 参数2:自定义阶段key,需要和onTraceEnd配对使用
* 参数3:时间戳
*/
LaunchManager.onTraceBegin(context, "自定义阶段key_2", System.currentTimeMillis());

在您自定义阶段结束处添加如下API:

注:自定义阶段key长度不可以超过10个字符

/**
* 参数1:上下文
* 参数2:自定义阶段key,需要和onTraceBgin配对使用
* 参数3:时间戳
*/
LaunchManager.onTraceEnd(context, "自定义阶段key_1", System.currentTimeMillis());

代码示例:

//监控initData()方法在启动阶段的耗时
 LaunchManager.onTraceBegin(MainActivity.this, "initData", System.currentTimeMillis());
 initData();
 LaunchManager.onTraceEnd(MainActivity.this, "initData", System.currentTimeMillis());

结果验证

集成完成启动App,过滤efs.px.api,可以看到如下启动数据发送成功相关信息,即表示启动数据成功上报。

image

8.6内存分析

内存分析支持OOM异常和内存占用指标。

OOM异常是崩溃分析的子集,因此不单独提供开关配置,是否采集OOM与是否采集Crash同步,如您需要关闭某类崩溃,可通过【集成接入】-【采集开关】调整。

内存占用,需要接入U-APM SDK 1.4.0及以上版本,并建议搭配最新版本Common接入, 如您不希望采集内存占用相关指标,可通过【集成接入】-【采集开关】调整。

8.7App 打通 H5

集成QuickTracking JS SDK的网页在嵌入到App后,JS SDK采集到的数据可以通过App端上传到服务器,该功能默认关闭。如果开启,需要在每一个webview loadUrl前调用如下方法:

//以下方法仅支持U-APM Android 1.6.0.001及以上版本
H5Manager.enableJavaScriptBridge(webView);
webView.loadUrl("https://www.demo.com");

注意:

在API 16及以下版本中,注入JavaScript有安全漏洞,请谨慎使用。

8.8 原生页面

自动集成

1、依赖插件。

打开您工程根目录的build.gradle,在dependencies中添加如下:

classpath "com.lydaas.qtsdk:apm-plugin:1.0.1"

注意:确保您已在工程根目录的build.gradle中添加Maven地址。

示例如下:

buildscript {
  repositories {
    //配置 quicktracking sdk maven地址
    maven { setUrl("https://maven.aliyun.com/repository/central") }
    google()
    jcenter()
  }

  dependencies {
      //引入apm性能分析插件 
      classpath 'com.lydaas.qtsdk:apm-plugin:1.0.1' 
  }
}

...

allprojects {
  repositories {
    //配置 quicktracking sdk maven地址
    maven { setUrl("https://maven.aliyun.com/repository/central") }
    google()
    jcenter()
  }
}

2、配置插件。 打开您App的build.gradle添加使用插件,在文件头添加代码如下:

apply plugin: 'com.efs.sdk.plugin'

同时添加插件的相关配置,代码如下:

efs {
    //是否对启动过程进程插桩的开关,如果使用自动集成监控则必须开启,false则不开启启动插件
    enable = true
    //白名单,支持包力度,必须填写,如填写自己应用的包名
    whiteList = [
        "您的包名路径"
    ]
    //⽩名单中包名下配置的Activity,如果有继承关系,例如App内有BaseActivity,其他Activity部
    //分或者全部继承于BaseActivity,需要将BaseActivity配置到⿊名单中,避免插件重复插桩。
    blackList = [
        "您的包名路径"
    ]
}

示例如下:

image

自定义页面阶段数据

概念 如果您想在页面监控过程中加入自定义的监控阶段,比如初始化业务数据(initData)、初始化页面组件(initView)等,您可以使用自定义页面阶段API加入您自定义的页面阶段数据。

方法 在您自定义阶段开始处添加如下API: 注:1、自定义阶段key长度不可以超过10个字符;2、key的名称不能以"UM_"开头;3、单个页面使用上限为6个,超出则过滤。

 /**
 * 参数1: 当前activity对象
 * 参数2: 自定义阶段key,需要和onTracePageEnd配对使用
 */
 PageManger.onTracePageBegin(MainActivity.this, "initView");

在您自定义阶段结束处添加如下API: 注:自定义阶段key长度不可以超过10个字符;2、key的名称不能以"UM_"开头;3、单个页面使用上限为6个,超出则过滤。

 /**
 * 参数1: 当前activity对象
 * 参数2: 自定义阶段key,需要和onTracePageBegin配对使用
 */
 PageManger.onTracePageEnd(MainActivity.this, "initView");

代码示例:
//监控initView()方法在页面阶段的耗时
PageManger.onTracePageBegin(MainActivity.this, "initView");
initView();
PageManger.onTracePageEnd(this, "initView");

8.9采集开关

注:您在产品后台「开关与采样配置」中设置的开关和采样率优先级高于在SDK中设置的开关,SDK会间隔8小时同步是否有开关和采样配置更新的请求

本采集开关适用于开发者在不想使用某个U-APM 监控模块时可灵活自定义采集范围。如目前提供功能都需要采集,则不需要使用该开关,如需要调整某个模块,可按照下面bundle控制说明,选择key进行设置。

注意

此API需要在调用初始化方法前使用

/**
* 通过Bundle中指定的key和key的value值(boolean类型)来控制该key对应APM模块的关闭
*/
UMCrash.initConfig(Bundle args)	
 //用于控制UMCrash.KEY_ENABLE_CRASH_JAVA
 //UMCrash.KEY_ENABLE_CRASH_NATIVE
 //UMCrash.KEY_ENABLE_ANR
UMEfs.initConfig(Bundle args)
 //用于控制UMEfs.KEY_ENABLE_PA
 //UMEfs.KEY_ENABLE_LAUNCH
 //UMEfs.KEY_ENABLE_MEM
 //UMEfs.KEY_ENABLE_NET
 //UMEfs.KEY_ENABLE_H5PAGE
 //UMEfs.KEY_ENABLE_PAGE

Bundle控制说明:

key

说明

开关级别

UMCrash.KEY_ENABLE_CRASH_JAVA

用于关闭java crash捕获,默认为true可设置为false进行关闭

二级

UMCrash.KEY_ENABLE_CRASH_NATIVE

用于关闭native crash捕获,默认为true可设置为false进行关闭

二级

UMCrash.KEY_ENABLE_ANR

用于关闭ANR捕获,默认为true可设置为false进行关闭

一级

UMEfs.KEY_ENABLE_PA

用于关闭卡顿捕获,默认为true可设置为false进行关闭

一级

UMEfs.KEY_ENABLE_LAUNCH

用于关闭启动捕获,默认为true可设置为false进行关闭

一级

UMEfs.KEY_ENABLE_MEM

用于关闭内存占用捕获,默认为true可设置为false进行关闭

一级

UMEfs.KEY_ENABLE_NET

用于关闭网络分析捕获,默认为true可设置为false进行关闭

一级

UMEfs.KEY_ENABLE_H5PAGE

用于关闭App与H5打通开关,默认为true可设置为false进行关闭

一级

UMEfs.KEY_ENABLE_PAGE

用于关闭Page开关,默认为true可设置为false进行关闭

一级

UMEfs.KEY_ENABLE_CODE_LOG

用于关闭日志回捞开关,默认为true可设置为false进行关闭

一级

示例:

 QtConfigure.setLogEnabled(true);
 Bundle bundle = new Bundle();
 bundle.putBoolean(UMCrash.KEY_ENABLE_CRASH_JAVA, true);
 bundle.putBoolean(UMCrash.KEY_ENABLE_CRASH_NATIVE, true);
 bundle.putBoolean(UMCrash.KEY_ENABLE_ANR, false);
 bundle.putBoolean(UMEfs.KEY_ENABLE_PA, false);
 bundle.putBoolean(UMEfs.KEY_ENABLE_LAUNCH, false);
 bundle.putBoolean(UMEfs.KEY_ENABLE_MEM, false);
 bundle.putBoolean(UMEfs.KEY_ENABLE_H5PAGE, false);
 bundle.putBoolean(UMEfs.KEY_ENABLE_CODE_LOG, false);
 UMCrash.initConfig(bundle);
 QtConfigure.init(this,"您的appkey","应用商店名称",QtConfigure.DEVICE_TYPE_PHONE, "");

说明

1、由于启动监控早于SDK初始化,所以彻底去掉启动监控还需关闭插件插桩或去掉手动API埋点。

2、卡顿开关关闭情况下不会对卡顿模块进行初始化,并输出如下日志内容:enablePaLog is false 。

3、启动开关关闭情况下不会对卡顿模块进行初始化,并输出如下日志内容:enableLaunchLog is false 。

4、内存开关关闭情况下不会对内存模块进行初始化,并输出如下日志内容: enableMemLog is false 。

5、日志回捞关闭情况下不会对日志回捞模块进行初始化,并输出如下日志内容: enable codeLog is false 。

8.10符号表

什么是符号表

符号表是内存地址与函数名、文件名、行号的映射表。符号表元素如下所示:<起始地址> <结束地址> <函数> [<文件名:行号>]为了能快速并准确地定位用户APP发生Crash的代码位置,我们使用符号表对APP发生Crash的程序堆栈进行解析还原 因此在使用U-APM还原时需要先上传符号表!

为什么要上传符号表

为了能快速并准确地定位用户APP发生Crash的代码位置,使用符号表对APP发生Crash的程序堆栈进行解析还原

举一个例子

image

性能监控提供了手动上传符号表。

Android 打包符号表方式

如何打包符号表

Java 符号

多个mapping文件请自行处理追加到一个文件中,最终命名为mapping.txt,并打包成zip文件,如果需要同时包含so符号,可以把so文件打包在一起。(具体结构可参考下面“符号表文件建议示例”)

Android so库

保证符号表的so文件与发布的so文件同名,so压缩前最大支持400M;如果一个版本里包含同文件名,不同架构的so,可以压缩到不同的目录中,反符号化时需要通过buildid去关联;建议编译时使用-g参数,带上debug信息,崩溃堆栈可以解析到代码行级,实际发布时,再使用strip命令去掉调试信息;如果不带debug信息,则只能定位到函数名级下列情况下,需要so文件带有buildid

  • 不同CPU架构的so文件名一样,放在不同的路径下

  • 同一个应用版本里,可能有多个版本的so库,使用了动态加载的技术如何生成带buildid的so,请检查编译参数,确保没有带”—build-id=none”,如果还是没有buildid,可以添加编译参数”ld_flags += -Wl,--build-id=sha1”可通过file命令检查so文件是否带buildid,调试信息

符号文件建议示例

xxx.zip|— mapping.txt —多个mapping需要自行合并

|— libxx1.so —要求与发布的so同名

|— libxx

|— libxx3.so —同文件名,多个架构放不同的目录

|— x86

|— libxx3.so —同文件名,多个架构放不同的目录

已经上传的符号表可以在符号表管理页面进行查看

image

当前支持上传方式:后台手动上传(最大支持400M)

版本选择

当前支持现有版本列表和手动输入两种方式:

  1. 如果是已经有错误上报到U-APM后台的版本,可以直接在上传符号表时的版本下拉框中选择

  2. 如果是即将发布的新版本,支持手动输入版本号,请输入与新版本完全一致的内容,并点击‘添加版本号‘即可手动添加

image

手动上传方式

  1. 按照文档说明将符号表文件压缩到一起:查看【如何打包符号表】

  2. 登录平台,找到需要上传的符号表应用,点击顶部的设置进入应用设置界面

  3. 点击符号表管理 ,点击上传,将第一步压缩好的符号表文件上传即可

8.11设置HTTP接口API

//isHttpsProtocol默认为true,为false则SDK本地默认发送HTTP请求 UMEfs.setRequestProtocol(boolean isHttpsProtocol);

接口说明:

1、该接口仅影响UAPM 性能部分发送请求,crash部分不受该接口控制;

2、该接口需要在初始化SDK之前设置;

3、用户可通过该接口修改SDK本地是以HTTP头发送还是HTTPS头发送,默认SDK是以HTTPS头发送,并且可以通过云控配置动态下发修改,并且云控下发会覆盖该接口的设置;

4、通过setCustomDomainEfs接口传入的域名中的HTTP或HTTPS头接口内会自动切掉,以SDK默认值(HTTPS头)或setRequestProtocol接口或云控决定SDK使用HTTP或HTTPS。

8.12日志回捞

设置回捞标识

您可以通过如下接口设置回捞标识:

Bundle bundle = new Bundle();
//设置回捞标识为android0911
bundle.putString(UMEfs.KEY_LOG_USER_ID, "android0911");
UMEfs.initConfig(bundle);

注意:

1)该设置必须在初始化SDK之前完成,运行时不可再次设置

2)回捞标识不能为空,且长度不能超过128

3)如果不设置回捞标识,默认以UMID作为标识回捞

日志记录

您可以通过如下接口完成相关日志的记录:

ULog.v("日志TAG", "日志内容"); ULog.d("日志TAG", "日志内容"); ULog.i("日志TAG", "日志内容"); ULog.w("日志TAG", "日志内容"); ULog.e("日志TAG", "日志内容");

注意:

1)共提供五种日志等级,包括:v/d/i/w/e

2)参数1为日志的TAG,不能为空或长度超过64,参数2为日志的内容,不能为空或长度超过1024

3)务必使用「import com.umeng.logsdk.ULog;」类下的ULog.v等方法,且必须要在初始化SDK之后调用。如果使用「com.umeng.commonsdk.statistics.common.ULog;」将不生效

日志策略

1)日志持久化存储上限为5MB,当达到上限时则仅保留最近7天的日志,如果最近7天日志达到上限则不再继续存储日志

2)触发日志持久化存储:

2.1)前后台切换;

2.2)缓存数据达到上限则进行持久化日志存储

3)当回捞任务下发到本地,并成功加载后,则进行回捞任务和本地日志的匹配,匹配到的日志开始上传,当前进程正在产生的日志需要下次启动后匹配任务继续上传

日志排查

1)日志回捞模块开启,输出如下日志:

enable codeLog is true

2)正确读取并加载日志任务,输出如下日志:

09-13 14:56:28.988 15994-15994/com.efs.demo I/ULogConfigManager: [log register] begin. 09-13 14:56:29.704 15994-15994/com.efs.demo I/ULogConfigManager: [log register] call back config. 09-13 14:56:29.709 15994-15994/com.efs.demo I/ULogConfigManager: [log register] save did is 9560fe0f75e7c92fff351d537633a91cia 09-13 14:56:29.709 15994-15994/com.efs.demo I/ULogConfigManager: [log register] save uid is android0911 09-13 14:56:29.710 15994-15994/com.efs.demo I/ULogConfigManager: [log register] save task id is 1660130437264, task is {"task_etime":1663257599000,"target_type":0,"task_id":"1660130437264","task_btime":1662307200000,"task_type":0} 09-13 14:56:29.710 15994-15994/com.efs.demo I/ULogConfigManager: [log register] add mem task id is 1660130437264 09-13 14:56:29.710 15994-15994/com.efs.demo I/ULogConfigManager: [log register] save task id is 1660130437265, task is {"task_etime":1663257599000,"target_type":1,"task_id":"1660130437265","task_btime":1662307200000,"task_type":0} 09-13 14:56:29.710 15994-15994/com.efs.demo I/ULogConfigManager: [log register] add mem task id is 1660130437265 09-13 14:56:29.710 15994-15994/com.efs.demo I/ULogConfigManager: [log register] save task id set is 1660130437264_1660130437265

3)持久化存储日志(如前后台切换),输出如下日志:

09-13 15:06:23.445 15994-16722/com.efs.demo I/efs.base: {"fr":"android","sdk":23,"others_OS":"Android","stime":1663052188738,"dsp_h":1920,"rom":"6.0.1","sdk_ver":"1.3.11.umeng","w_tm":1663052783,"um_access":"wifi","lang":"zh","um_umid_header":"aid03bc207717fd2238c5d8bf93ed4fffb","pkg":"com.efs.demo","type":"codelogperf","dsp_w":1080,"um_network_type":0,"wid":"54d8e67e-0a4e-4e11-9517-08ac993aa670","log_uid":"android0911","pid":15994,"ps":"com.efs.demo","build_model":"MI 4LTE","appid":"ez2cookeijezdgu3nxmci6zt","um_app_carrier":"","ctime":1663052783,"net":"wifi","um_crash_sdk_version":"efs.1.6.0.001.200","um_os":"android","vcode":"1","tzone":"Asia\/Shanghai","um_app_channel":"Umeng","brand":"xiaomi","log_did":"9560fe0f75e7c92fff351d537633a91cia","codelog":{"taskid":"","status":0,"time_start":1663052782368,"time_end":1663052783439,"uid":"android0911","did":"9560fe0f75e7c92fff351d537633a91cia","body":[{"tag":"walle","msg":"button 1 --->>> ","level":0,"time":1663052782367,"process":"com.efs.demo","thread":"main"},{"tag":"walle","msg":"button 1 --->>> ","level":2,"time":1663052782370,"process":"com.efs.demo","thread":"main"}]},"uid":"54d8e67e-0a4e-4e11-9517-08ac993aa670","ver":"1.0","model":"mi-4lte"} 09-13 15:06:23.459 15994-16077/com.efs.demo I/RecordLogCacheProcessor: save file, type is codelogperf 09-13 15:06:23.463 15994-16077/com.efs.demo I/RecordLogCacheProcessor: upload file, name is codelogperf_none_1_1_15994_2442_1663052783458_android0911_9560fe0f75e7c92fff351d537633a91cia_1663052782368_1663052783439

查看data/data/<你的app>/app_UApm/<你的appkey>/upload_codelog中有日志文件,则表示日志保存成功

4)日志匹配并上传成功,输出如下日志:

09-13 15:06:39.255 15994-16077/com.efs.demo I/efs.cache: [-->>] add file is codelogperf_gzip_2_1_15994_3356_1663052783463_android0911_9560fe0f75e7c92fff351d537633a91cia_1663052782368_1663052783439 09-13 15:06:39.262 15994-16141/com.efs.demo I/efs.LogSendAction.Codelog: send data url is http://aplus2-portal-lite.emas-poc.com 09-13 15:06:39.272 15994-16141/com.efs.demo I/efs.px.api: Upload file, url is http://aplus2-portal-lite.emas-poc.com/apm_logs 09-13 15:06:39.478 15994-16141/com.efs.demo I/efs.px.api: upload result : true, resp is HttpResponse {succ=true, code=200, data='{"msg":"成功","code":0,"cip":"XXX.XX.XX.XXX","stm":1663052801}', extra={req_url=http://aplus2-portal-lite.emas-poc.com/apm_logs, flow_limit=true, biz_code=0, size=592, type=codelogperf}} 09-13 15:06:39.480 15994-16077/com.efs.demo I/efs.send_log: send secess.

附录-SDK上报策略

如果您创建了自定义异常,则需要存在自动采集的崩溃/ANR发生时一起上报

测试中请关注SDK上报策略,当日单设备达到限制后无法再上报数据

错误类型

上报策略

Java

崩溃捕获后会尝试立刻发送,如果失败就下次启动发送同时通过流量 + 数量的限制,详细请见下方表格

Native

ANR

自定义异常

发生后跟随Java/Native/ANR 错误上报

卡顿/启动/网络/H5页面分析

实时上报

错误上报的流量+数量限制:

目前默认值

允许保留在崩溃日志目录 mCrashLogsFolderName 下最大的崩溃日志条数。在生成日志前,如果发现崩溃日志文件数达到限制的条数,就会删除最早生成的那条崩溃日志。每删除一条崩溃日志,统计项 CrashStatKey.LOG_ABANDONED_FILE 和 CrashStatKey.LOG_ABANDONED_BUILTIN_FILE 都会加 1

15

允许保留在崩溃日志目录 mCrashLogsFolderName 下最大的自定义日志数。在生成自定义日志前,如果发现自定义日志文件数达到限制,就会删除最早生成的那个自定义日志。每删除一条自定义日志,统计项 CrashStatKey.LOG_ABANDONED_FILE 和 CrashStatKey.LOG_ABANDONED_CUSTOM_FILE 都会加 1。

10

java 崩溃日志中,获取 logcat 的最大行数

1500

native 崩溃日志中,获取 logcat 的最大行数

3000

anr 日志中,获取 logcat 的最大行数

1000

是否同步上传主进程初始化过程中产生的崩溃日志。开启该选项时,如果 SDK 检测到主进程发生崩溃,在生成完该崩溃日志后,SDK 会尝试立即将崩溃日志上传(以防止该场景下的稳定崩溃收集不到)。该开关仅在Java和 native 崩溃中生效,自定义日志无效。SDK 判断主进程的条件为:Package Name 与 /proc/self/cmdline 中的进程名相等。

true

是否生成完日志后立即上传。该开关针对除自定义日志以外的日志有效,自定义日志由日志生成时指定是否立即上传。

true

是否在发现 APP 当前的版本与上次运行时的版本不一致时,清除所有的崩溃统计数据。版本是否一致,是根据版本号 VersionInfo.mVersion、子版本号 VersionInfo.mSubVersion、打包流水号 VersionInfo.mBuildId 判断,任何一个不一样,都会认为是不同版本。

false

是否在生成完崩溃日志后,使用 gz 算法压缩崩溃日志。压缩成功后,原日志被删除;压缩失败,原日志将保留

true

是否在生成完崩溃日志后,使用默认算法加密崩溃日志。加密成功后,原日志被删除;加密失败,原日志将保留

false

生成日志时,每个日志允许写入的最大字节数。 当达到指定的字节数时,会将剩余的全部丢弃。日志的总长度、丢弃字节数等信息,在日志最后会有记录。对 JAVA, NATIVE, ANR 日志都有效;为 <= 0 的值时,表示不限制。

1024*1024

在上传崩溃日志时,上传的单个日志允许的最大字节数。超过此限制时,将放弃上传该日志并直接删除,同时将统计项 CrashStatKey.LOG_LARGE_FILE加 1 。其对所有类型的日志有效。为 <= 0 的值时,表示不限制。

800*1024

每24小时内,允许上传日志总共的最大字节数。超过时,将放弃日志的上传,日志将保留在磁盘;超过 24 小时后,再次调用上传接口时,再上传日志。为 < 0 的值时,表示不限制。每次尝试上传发现达到该限制时,统计项 CrashStatKey.LOG_UPLOAD_LIMIT 和 CrashStatKey.LOG_UPLOAD_BYTES_LIMIT 都会加 1。

1.5*1024*1024

每 24 小时内上传的最大崩溃日志条数。每次尝试上传发现达到该限制时,统计项 CrashStatKey.LOG_UPLOAD_LIMIT 和 CrashStatKey.LOG_UPLOAD_BUILTIN_LIMIT 都会加 1。其自版本 3.0.0 从 mMaxUploadCrashLogCountPerDay 重命名而来。

25

每 24 小时内上传的最大自定义日志条数。每次尝试上传发现达到该限制时,统计项 CrashStatKey.LOG_UPLOAD_LIMIT 和 CrashStatKey.LOG_UPLOAD_CUSTOM_LIMIT 都会加 1。

20

每 24 小时内每种自定义类型的日志允许生成的最大条数。不同类型的自定义日志条数会分别计数。

6

每个进程允许生成的最大 ANR 日志条数。

3

崩溃生成日志后,不自动重启

true

是否在SDK处理完Java异常且生成完 Java 崩溃日志后,将异常信息通知给 SDK 初始化之前,其他人(系统)注册的 UncaughtExceptionHandler。

true

是否在 SDK 处理完 native 崩溃信号且生成完 native 崩溃日志后,将崩溃信号通知给 SDK 初始化之前,其他人(系统)注册的信号处理函数。

false

自动更新当前 CPU 使用率等信息的时间间隔,单位为秒(s)。

50

  • 本页导读 (0)
文档反馈