You need to enable JavaScript to run this app.
最新活动
产品
解决方案
定价
合作与生态
支持与服务
开发者
了解我们
导航

Android SDK接入

更新时间:2023.05.30 17:14:51

本文介绍Android SDK的详细接入步骤。接入SDK后,验证数据上报成功,即可在应用性能监控全链路版平台上使用相关分析功能。

使用限制

Android SDK目前仅限在中国大陆应用使用(不包括港澳台地区)。

注意事项

调用SDK初始化接口不会采集用户信息,调用SDK启动接口会开始采集用户信息,请确保采集用户信息之前已经获得用户授权SDK隐私政策

Demo示例

APMInsight_Android

  • Demo已经接入了所有ApmInsight的性能和稳定性监控的能力。
  • 您可以通过Demo模拟一些异常和性能数据。
  • 您可以配置成自己的Appid,将数据上报到平台,进行SDK功能测试。

步骤一:获取SDK包,引入依赖

应用性能监控全链路版的Android SDK无需下载,请根据下方初始化配置说明接入。

  1. 在project级别的build.gradle添加maven地址。

    buildscript {
        repositories {
            maven {
                url "https://artifact.bytedance.com/repository/Volcengine/"
            }
            maven {
                url "https://artifact.bytedance.com/repository/byteX/"
            }
        }
    }
    allprojects {
        repositories {
            maven {
                url "https://artifact.bytedance.com/repository/Volcengine/"
            }
        }
    }
  2. 接入应用性能监控全链路版。

    1. 在project级别的build.gradle文件的dependencies中添加以下代码。

      classpath "com.volcengine:apm_insight_plugin:1.4.2"
    2. 在app module的build.gradle文件的dependencies中添加以下代码。
      插桩是为了辅助收集启动耗时、页面加载、网络监控的数据,这部分只适用于接入App进行监控的用户,不适用于接入SDK进行监控的用户。

      //在文件头添加
      apply plugin: 'apm-plugin'
      // 在dependencies中添加
      implementation 'com.volcengine:apm_insight:1.5.0.cn'
      implementation 'com.volcengine:apm_insight_crash:1.4.7'

步骤二:初始化SDK

AppID和AppToken获取方法,请参见如何查询AppID和AppToken?

崩溃相关功能

在Application中onCreate中,添加以下代码初始化崩溃相关功能。

MonitorCrash.Config config = MonitorCrash.Config.app({{AppId}})
                .token({{AppToken}})// 设置鉴权token,可从平台应用信息处获取,token错误无法上报数据
//              .versionCode(1)// 可选,默认取PackageInfo中的versionCode
//              .versionName("1.0")// 可选,默认取PackageInfo中的versionName
//              .channel("test")// 可选,设置App发布渠道,在平台可以筛选
//              .url("www.xxx.com")// 默认不需要,私有化部署才配置上报地址
                //可选,可以设置自定义did,不设置会使用内部默认的
//              .dynamicParams(new MonitorCrash.Config.IDynamicParams() {
//                  @Override
//                  public String getDid() {//返回空会使用内部默认的did
//                      return null;
//                  }
//
//                  @Override
//                  public String getUserId() {
//                      return null;
//                  }
//              })
                //可选,添加业务自定义数据,在崩溃详情页->现场数据展示
//              .customData(crashType -> {
//                  HashMap<String, String> map = new HashMap<>();
//                  map.put("app_custom", "app_value");
//                  return map;
//              })
//            .autoStart(false) // 是否在初始化时自动开启监控,默认为true
//            .debugMode(true) //线下使用的日志开关,线上不要调用或设置为false
             // 可选,添加pv事件的自定义tag,可以用来筛选崩溃率计算的分母数据
             //.pageViewTags(<<Map<String, String>>>)
                .build();
        MonitorCrash monitorCrash = MonitorCrash.init(ApplicationContext, config);
        
        // 启动监控,当初始化时autoStart传入false设置为初始化时不自动开启监控,需要在合适的位置调用start方法开启监控;如果初始化时未设置autoStart参数或者设置为true,将自动开启监控,不需要调用start方法。
        if (monitorCrash != null) {
            monitorCrash.start();
        }

初始化崩溃相关功能的代码有以下说明:

  • Context建议传递ApplicationContext。
  • 参数都不能为null,否则会造成初始化失败。
  • versionInt为数字版本号,versionString为字符版本号,如100、"1.0.0"。
  • 初始化返回的MonitorCrash实例为后续配置的入口。
  • aid可以在平台项目浏览器的url上面获取。
  • 避免重复调用初始化方法,并对init返回对象做空指针判断。

性能相关功能

在Application中onCreate中,添加以下代码初始化性能相关功能。

注意

请在主线程中添加初始化性能相关功能的代码。

//必须放到Application的onCreate里面,会注册监听生命周期,不涉及数据采集和隐私合规问题
ApmInsight.getInstance().init(application);

//在同意隐私合规后调用
ApmInsightInitConfig.Builder builder = ApmInsightInitConfig.builder();
//设置分配的appid
builder.aid({{app_id}});
//设置分配的AppToken
builder.token({{AppToken}});
//是否开启卡顿功能
builder.blockDetect(true);
//是否开启严重卡顿功能
builder.seriousBlockDetect(true);
//是否开启流畅性和丢帧
builder.fpsMonitor(true);
//控制是否打开WebView监控
builder.enableWebViewMonitor(true);
//控制是否打开内存监控
builder.memoryMonitor(true);
//控制是否打开电量监控
builder.batteryMonitor(true);
//控制是否打开CPU监控
builder.cpuMonitor(true);
//控制是否打开磁盘监控
builder.diskMonitor(true);
//控制是否打开流量监控
builder.trafficMonitor(true);
//是否打印日志,注:线上release版本要配置为false
builder.debugMode(true);
//默认不需要,私有化部署才需要配置数据上报的域名 (内部有默认域名,测试支持设置http://www.xxx.com  默认是https协议
//builder.defaultReportDomain("www.xxx.com");
//设置渠道。1.3.16版本增加接口
builder.channel("google play");
//打开自定义日志回捞能力。1.4.1版本新增接口
builder.enableLogRecovery(true);
//设置数据和Rangers Applog数据打通,设备标识did必填。1.3.16版本增加接口
builder.setDynamicParams(new IDynamicParams() {
    @Override
    public String getUserUniqueID() {
        //可选。依赖AppLog可以通过AppLog.getUserUniqueID()获取,否则可以返回null。
        return null;
    }

    @Override
    public String getAbSdkVersion() {
        //可选。如果依赖AppLog可以通过AppLog.getAbSdkVersion()获取,否则可以返回null。getAbSdkVersion是回调类的参数可以初始化后再设置。
        return null;
    }

    @Override
    public String getSsid() {
        //可选。依赖AppLog可以通过AppLog.getSsid()获取,否则可以返回null。getSsid是回调类的参数可以初始化后再设置。
        return null;
    }

    @Override
    public String getDid() {
        //1.4.0版本及以上可选,其他版本必填。设备的唯一标识,如果依赖AppLog可以通过 AppLog.getDid() 获取,也可以自己生成。getDid是回调类的参数可以初始化后再设置。
        return null;
    }
    
    @Override
    public String getUserId() {
         //可选。用户的唯一标识,支持用户自定义user_id把平台数据和自己用户关联起来。getUserId是回调类的参数可以初始化后再设置。
         return "userid";
    }
    
});
ApmInsight.getInstance().start(builder.build());
//初始化自定日志,配置自定义日志最大占用磁盘,内部一般配置20,代表最大20M磁盘占用。1.4.1版本开始存在这个api
VLog.init(this,20);

启动分析和页面体验相关功能依赖插件插桩,需配置ApmPlugin的whiteList为自己的包名,配置后该目录下的代码会被插桩。
在app module的build.gradle文件最外层,添加以下代码完成插桩。

ApmPlugin {
    // 是否进行插桩
    enable true
    // 是否在Debug包插桩,默认不插桩
    enableInDebug true
    // DEBUG("DEBUG"), INFO("INFO"), WARN("WARN"), ERROR("ERROR");
    // DEBUG 级别Log会汇总所有被插桩处理的类供查看,路径 app/build/ByteX/ApmPlugin/ApmPlugin_log.txt
    logLevel "DEBUG"
    // 启动分析开关:监控App启动耗时,需要同时开启pageLoadSwitch
    startSwitch = true
    // 页面响应开关:监控Activity的生命周期耗时
    pageLoadSwitch = true
    // 网络监控开关:监控okhttp3的网络请求
    okHttp3Switch = true
    //插桩显示HttpUrlConnection的网络请求开关
    httpUrlConnectionSwitch = true
    // 白名单下的包进行插桩,需要填写要插装类所在的包名,支持前缀配置
    whiteList = [
            "com"
    ]
    // 黑名单包下类不进行插桩,可以配置包名和类名,没有可以填空
    blackList = [
            "com.xxx"
    ]
}

WebView页面监控

WebView初始化一般在某个Activity或者某个Fragment内,添加以下代码将待监控的Webview进行封装:

//设置webView的WebChromeClient如下或者继承WebViewMonitorWebChromeClient
webView.setWebChromeClient( new WebViewMonitorWebChromeClient());
//设置webView的WebViewClient如下或者继承WebViewMonitorWebViewClient
webView.setWebViewClient(new WebViewMonitorWebViewClient());
//WebView加载url时候需要调用如下函数
WebViewMonitorHelper.getInstance().onLoadUrl(webView, url);
webView.loadUrl(url);

步骤三:验证数据上报

前提条件

  • 配置设备白名单
    崩溃是100%上报的,不受采样率控制。除了崩溃其他监控数据需要在平台SDK上报配置页面配置采样上报,默认情况下采样命中后才会上报。由于平台默认配置的采样率较低,在SDK接入测试阶段请配置DID白名单,确保当前设备所有性能数据都采样命中,才可以上报到平台查看这些数据。
    图片
    那么,如何获取需要添加到白名单的DID?

    • 如果业务已经自定义,直接根据自定义的DID配置,初始化时getDid()返回的值。
    • 如果业务没有自定义,需要获取内部默认的DID。
      您可以通过以下接口获取DID。
    ApmInsightAgent.getDid()
  • 配置各模块采样率
    例如,验证卡顿数据前,请在SDK上报配置页面打开总开关,并将卡顿采样率配置为100%。验证完成后,再修改为适合的采样率。

Java崩溃/Java启动崩溃

完成前提条件后,添加以下代码发生崩溃。崩溃只有在下次启动才会上报。

throw new RuntimeException("Monitor Exception"); // 执行就崩,如果应用启动后8秒内崩溃, 则判定为启动崩溃进行上报

卡顿

完成前提条件后,在主线程调用以下函数发生卡顿。初始化SDK时,在主线程阻塞,App会自动监控到卡顿,2分钟内会上报到服务器。
例如,主线程调用如下函数:

private void testSeriousBlock() {
    try {
        Thread.sleep(3500);
    } catch (Exception e){
    }
}

严重卡顿把sleep时间修改为6000毫秒。

启动分析/页面响应

完成前提条件后,初始化SDK时,打开启动分析和页面响应的开关,App启动一段时间SDK会自动上报启动分析、页面响应的数据。

流畅性/丢帧

完成前提条件后,初始化SDK时,打开配置功能的开关,用户进入页面后滑动一段时间SDK会自动上报流畅性数据和丢帧数据。

内存

完成前提条件后,初始化SDK时,打开配置功能开关,设置debug测试模式。

builder.debugMode(true);
builder.memoryMonitor(true);

上述代码可以模拟发生以下两种场景:

  • OOM获取模式:默认在OOM(内存使用100%)的时候进行内存文件分析。
    • 调用模拟OOM的方法OOMMaker.createOOM();
    • 重新启动后,会自动上报内存数据,几分钟后去服务器查看内存数据。
  • 内存触顶模式:如果日活过少,没有OOM或者很少OOM,但是用户想分析内存问题,可以在SDK上报设置页面配置启动日志收集的内存占用比例,配置后在内存使用达到阈值时,SDK会上报启动日志收集内存信息,进行内存文件分析。
    • 调用模拟内存增加的方法OOMMaker.createReachTop(80);
      示例中阈值配置为80%,请根据实际业务场景修改阈值。
    • 稍等1分钟等待获取内存文件,然后重新启动后,会自动上报内存数据,几分钟后去服务器查看内存数据。

网络监控

完成前提条件后,初始化SDK时,配置插桩ApmPlugin的okHttp3Switch,打开网络监控开关。
当App使用okhttp3进行访问时会自动监控到并上报到服务器。插桩支持的okhttp版本最低是3.10.0。当前okhttp3对外暴露了上报网络监控数据的接口。
其他网络库监控需要自己采集网络监控数据,然后再通过网络监控数据接口上报网络数据,才能在平台查看监控数据。具体上报接口和上报数据结构请联系平台对接的人员获取。

电量监控

完成前提条件后,初始化SDK时,打开电量开关。
App启动后,端上采样命中会自动采集上报电量数据。

事件上报

完成前提条件后,在事件管理页面新增事件并配置采样,事件采样命中才会上报。
添加以下代码,配置事件上报的规则:

HashMap<String, String> dimension = new HashMap<>();
//维度值
dimension.put("key1", "value1");
dimension.put("key2", "value2");
HashMap<String, Double> metric = new HashMap<>();
//指标值
metric.put("metric1", (double) 10);
metric.put("metric2", 8.8);
ApmInsightAgent.monitorEvent("event1", dimension, metric);

添加以下代码,通过事件上报接口配置事件采样:

/**
 * 事件上报
 *
 * @param serviceName 事件名
 * @param dimension   可枚举Key-Value,代表维度。key代表维度名称,value代表维度值,平台会自动计算key值下的value的百分占比和上报量
 * @param metric      不可枚举的Key-Value,代表指标。key代表指标名称,value代表指标值,平台会自动计算value的平均值和上报量
 */
public static void monitorEvent(final String serviceName, final Map<String, String> dimension, final Map<String, Double> metric) {
}
/**
 * 事件上报
 *
 * @param serviceName 事件名
 * @param dimension   可枚举Key-Value标识维度
 * @param metric      不可枚举的Key-Value标识指标
 * @param extraJson   辅助分析事件的数据,只可以在单点原始日志查看
 *
 */
public static void monitorEvent(final String serviceName, final Map<String, String> dimension, final Map<String, Double> metric, final JSONObject extraJson) {
}

通过以上接口配置事件采样后,可以在平台查看事件信息。
平台查看的事件示例如下所示:

//代表event1 采样没有命中
2021-04-11 21:19:01.019 13535-13587/com.example.apm.insight.demo D/ApmInsight: Receive:EventData event1 simple:false
//代表event2 采样命中
2021-04-11 21:19:01.916 13535-13587/com.example.apm.insight.demo D/ApmInsight: Receive:EventData event102 simple:true

CPU监控

完成前提条件后,初始化SDK时,打开CPU监控,CPU指标会自动采集后上报。
CPU异常可以在端上模拟异常场景,然后等待端上检测异常上报后,在平台查看异常数据。
添加以下代码,模拟CPU异常:

for (int i = 0; i < 6; i++) {
    new Thread(new Runnable() {
        @Override
        public void run() {
            while (true) {
                Math.acos(Math.cos(java.lang.Double.valueOf(9999999)));
            }
        }
    },"cpu-"+i).start();
}

打开debug开关后,在Logcat日志中过滤ApmInsight,可以查看以下日志:

//CPU异常数据
2021-12-30 15:29:29.512 26285-26887/com.example.apm.insight.demo D/ApmInsight: Receive:ExceptionCpuData
//CPU指标
2021-12-30 15:29:29.512 26285-26887/com.example.apm.insight.demo D/ApmInsight: Receive: ProcessCpuDat

磁盘监控

测试阶段建议配置:平台磁盘相关采样率配置为100%,磁盘相关阈值都配置为1,最大上报文件使用默认值20,端上设置 builder.debugMode(true) 。
App一次启动只会上报一次磁盘数据。为了降低对性能的影响,SDK默认为App在后台时才会采集上报一次磁盘数据,按照测试阶段建议配置后,您可以设置debug模式在前台也可以采集上报磁盘数据。 冷启动后过滤ApmInsight会看到Receive:DiskData的日志,代表磁盘监控数据上报成功,可以在平台磁盘异常页面查看数据。

流量监控

完成前提条件后,初始化SDK时,打开流量开关。App启动后,端上采样命中会自动采集上报流量数据。流量指标10分钟采集一次。流量异常需要端上10分钟流量消耗超过平台配置的阈值。
添加以下代码,模拟流量异常:

//十分钟流量
2023-01-12 21:10:49.615 5472-5576/com.example.apm.insight.demo D/ApmInsight: TrafficData10
//流量异常
2023-01-12 21:10:49.615 5472-5576/com.example.apm.insight.demo D/ApmInsight: TrafficDataException

步骤四:其他功能

自定义日志

自定义日志的的三个使用场景:崩溃日志上报、日志回捞以及主动上报。

主动上报

  1. 初始化SDK时,打开自定义日志。

    //打开自定义日志回捞能力
    builder.enableLogRecovery(true);
    ApmInsight.getInstance().init(this, builder.build());
    //初始化自定日志,配置自定义日志最大占用磁盘,内部一般配置20,代表最大20M磁盘占用。1.4.1版本开始存在这个能力
    VLog.init(this,20);
  2. 主动上报Vlog日志文件。

    //示例:上传当前时间前10分钟的vlog日志。
    ApmInsightAgent.uploadVlog(System.currentTimeMillis() - 1000 * 60 * 10, System.currentTimeMillis());
    
    /**
     * Vlog日志 主动上报
     *
     * @param start 起始时间 毫秒
     * @param end  结束时间 毫秒
     */
    public static void uploadVlog(long start, long end) {
    }

    日志文件比较大,一次上报大约会消耗200事件量。

  3. 在平台的自定义文件页面,根据DID或User ID查询日志文件。

崩溃时主动上报

  1. 初始化SDK时,打开自定义日志。

    //打开自定义日志回捞能力
    builder.enableLogRecovery(true);
    ApmInsight.getInstance().init(this, builder.build());
    //初始化自定日志,配置自定义日志最大占用磁盘,内部一般配置20,代表最大20M磁盘占用。1.4.1版本开始存在这个能力
    VLog.init(this,20);
  2. 在平台SDK上报配置页面崩溃分析里配置是否上传自定义日志。

  3. 在平台崩溃详情页面的自定义日志下查看通过VLog类打印的日志。

日志回捞

用户出现问题需要日志排查时,通过平台回捞端上通过自定义日志VLog打印的日志来排查问题。具体步骤如下所示:

  1. 初始化SDK时,打开自定义日志。

    //打开自定义日志回捞能力
    builder.enableLogRecovery(true);
    ApmInsight.getInstance().init(this, builder.build());
    //初始化自定日志,配置自定义日志最大占用磁盘,内部一般配置20,代表最大20M磁盘占用。1.4.1版本开始存在这个能力
    VLog.init(this,20);
  2. 通过API打点自定义日志。

    // com.apm.insight.VLog;
    VLog.v(String tag, String msg);
    VLog.d(String tag, String msg);
    VLog.i(String tag, String msg);
    VLog.w(String tag, String msg);
    VLog.e(String tag, String msg);
    // 也可以通过接口来设置生效的日志级别
    VLog.changeLevel(com.apm.insight.LogLevel.WARN);
  3. 通过平台日志回捞页面新建任务,输入DID或UID回捞指定用户的自定义日志排查问题。

    • UID初始化时配置:

      @Override
          public String getUserId() {
               //可选。用户的唯一标识,支持用户自定义user_id把平台数据和自己用户关联起来。getUserId是回调类的参数可以初始化后再设置。
               return "userid";
          }
    • DID初始化时配置:

      @Override
          public String getDid() {
              //1.4.0版本及以上,可选,其他版本必填,设备的唯一标识。如果依赖AppLog可以通过 AppLog.getDid() 获取。也可以自己生成。
              return null;
          }

      如果DID返回的是null,可以通过UID的配置进行日志回捞。

自定义回捞

回捞支持自定义回捞,用户在平台输入自定义回捞参数,这里可以根据参数返回想要回捞的结果

//可选,自定义回捞设置
ApmInsightAgent.setRecoveryTemplate(new ITemplateConsumer() {
    @Override
    public CustomResult handleTemplateMessage(JSONObject template) {
        //template 是平台配置的 【自定义回捞参数】
        if (template != null) {
            String type = template.optString("type");
            if (!TextUtils.isEmpty(type)) {
                if (type.equals("type_one")) {
                    //返回type_one 回捞的结果
                    HashMap<String, String> result = new HashMap<>();
                    result.put("result", "获取文件成功");
                    //result平台会直接展示,file平台支持下载
                    CustomResult customResult = new CustomResult(result, application.getFilesDir());
                    //返回的回捞结果
                    return customResult;
                } else if (type.equals("type_two")) {
                   //返回type_two 回捞的结果
                    return null;
                }
            }
        }
        return null;
    }
});

上传符号表

应用性能监控全链路版支持手动上传符号表和自动上传符号表。

手动上传符号表

手动上传在平台上操作。

自动上传符号表

在应用工程的build.gradle中添加以下代码,配置自动上传符号表:

apply from: 'https://sf3-ttcdn-tos.pstatp.com/obj/apminsight-symbolicate/apminsight.gradle'
apminsightConfig {
        api_token = "" // 从平台的 全部功能->符号表管理->系统选择 Android->下面可以看到api key和api token。或者联系开发同学获取到的对应appId的一个token,私有化部署不用设置
        api_key = 0 // 从平台的 全部功能->符号表管理->系统选择 Android->下面可以看到api key和api token。或者联系开发同学获取到的对应appId的一个key,私有化部署不用设置
        aid = 187277 // 应用性能监控全链路版上的appid
 //       updateVersionCode = -1 // 默认不用写这一行, 除非您在初始化的时候手动指定了非标准版本号(或SDK版本号); 此处一定要与初始化的版本号一致
//       mappingUrl = "https://www.xxx.com" // 默认不用写这一行,如果是私有化,这里配置私有化平台域名
}

SDK接入时,updateVersionCode字段的值必须与初始化ApmInsight传入的值一致。App接入时,不需要配置,请删除这行代码。

上报自定义数据说明

崩溃的时候会上报很多数据,如果用户想上报一些自定义的数据,在崩溃的时候一起上报,可以添加以下代码。

崩溃配置其他字段

崩溃配置其他字段:包括渠道、版本号等所有自定义字段。

public Config config()

使用自定义维度

崩溃组件的自定义维度:

public MonitorCrash addTags(String key, String value)

性能组件的自定义维度:上报的tag在日志查询里或者原始日志文件里可以查询到。

//示例
ApmInsightAgent.addPerfTag("tag_test","tag_1");
/**
 * 性能数据增加tag
 * @param key
 * @param value
 */
public static void addPerfTag(@NonNull String key, @NonNull String value) {
}
/**
 * 性能数据移除tag
 * @param key
 * @param value
 */
public static void removePerfTag(@NonNull String key, @Nullable String value) {
}

上报自定义错误

其中参数message、type可以为任意字符串(不可过长),可用于筛选。

public void reportCustomErr(String message, String type, Throwable throwable)

例如:

MonitorCrash crash = 初始化返回的MonitorCrash实例
crash.reportCustomErr("test err", "type1", new RuntimeException());

启动自定义打点

启动监控支持自定义打点,方法需要配对出现。
在Application的onCreate和首个Activity的onResume之间,添加以下代码配置自定义打点。

LaunchTrace.startSpan("initData");
LaunchTrace.endSpan("initData");

添加上述代码后,可以在平台启动分析的启动节点耗时中查看自定义打点的耗时:
图片