1.2.1.3 Android SDK使用说明
Android SDK 使用文档
需要许可如下权限(添加到 AndroidManifest.xml
文件中)
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
若App中开启了定位权限(Android 6.0及以上需动态授权),sdk将自动获取定位数据
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
2.1. Gradle
我们已将SDK同步至Jcenter仓库,开发人员可通过Gradle命令集成。
app
的build.grade
中添加下列语句。其中请将 x.x
替换为版本号。当前最新版为2.2.7。
compile 'com.netease.da:hubbledata-sdk-android:x.x.x'
2.2. AAR导入
将下载好的aar文件放到libs
目录下, 在app的build.gradle
增加如下repo
flatDir {
dirs 'libs'
}
然后使用下面的方式引入
compile 'com.netease.da:hubbledata-sdk-android:x.x.x'
2.3. JAR导入(新版本已废弃, 请任选上面的一种方式)
~~ 将下载包里面的 mobidroid.jar 放入 App 项目 libs 目录中 ~~
然后在app
的build.grade
中添加下列语句
// 数据埋点
compile files("libs/mobidroid.jar")
在 app
的 build.gradle
中添加下列语句
android {
defaultConfig {
resValue("string", "hubble_app_key", "您的 app key")
}
}
4.1. Android 4.0 及以上版本(新接口)
自定义
Application
,并在onCreate()
方法中添加如下代码,开启统计功能DATracker.enable(this);
如果需要配置参数,可参考下面常用接口
DATracker.enableWithConfiguration(this, new DAConfiguration() .setAppChannel("demo") // 默认 null .setAppVersion("1.0") // 默认取 versionName .enableLog(true) // 默认 false .enableLocationAccess(true) // 默认 false );
全部参数接口概览
接口名称 | 参数类型 | 参数默认值 | 参数含义 |
---|---|---|---|
setAppChannel | String | Null | 应用渠道名称 |
setAppVersion | String | PackageInfo 的versionName | 应用版本号 |
enableLog | Boolean | false | 是否输出控制台日志 |
enableAutoUpload | Boolean | true | 是否自动上传数据 |
enableSendOnWifi | Boolean | false | 是否仅在wifi下上传数据 |
enablePageTrack | Boolean | true | 是否开启自动页面统计 |
enableLocationAccess | Boolean | false | 是否读取位置信息 |
enableABTest | Boolean | false | 是否使用 A/B Test |
enableABVisualization | Boolean | false | 是否使用 A/B Test 可视化调试 |
enableCodelessTrack | Boolean | false | 是否开启自动埋点 |
enableCodelessCircle | Boolean | false | 是否使用自动埋点可视化圈选 |
enableMultiProcess | Boolean | false | 是否支持多进程 |
setFlushBulkSize | Integer | 100 | 本地数据库缓存的最大记录数 |
setFlushInterval | Long | 15000(ms) | 两次数据发送的最小时间间隔 |
setClient | DAClient | Http Client,默认使用HttpURLConnection 进行数据上报。自定义的方法请参考文档后面的详细说明 |
4.2. Android 4.0 及以上版本(老接口,已废弃,但不影响使用)
自定义Application
,并在onCreate()
方法中添加如下代码,开启统计功能。注意:SDK 目前不支持多进程,初始化前要判断进程,避免重复初始化
DATracker.enableTracker(getApplicationContext(), "demo", "1.0", "Google Play", true, false);
参数依次为,当前 Context 实例、程序的 app key、版本和来源渠道、是否允许 SDK 在会话开始和进入后台时自动上传数据、是否只在 wifi 环境下发送数据
设置为只在 WIFI 下发送数据,会导致服务器接收数据延迟,对统计系统结果的及时性会产生影响,不建议使用
App Key 可从移动分析系统网站获取,不得使用为空值或者 null, 多次调用参数请确保一致
例如,定义MyApplication
继承Application
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
DATracker.enableTracker(getApplicationContext(), "demo", "1.0", "Google Play", true, false);
}
}
并在AndroidManifest.xml
注册
<application
android:name=".MyApplication"
...>
...
</application>
4.3. Android 4.0 以下版本
在 App 中所有的 Activity onCreate
方法中调用如下代码,开启统计功能
参数依次为,当前 Activity 实例、程序的 app key、版本和来源渠道
DATracker.enableTracker(this, "demo", "1.0", "Google Play");
如需要禁用 SDK 自动上传数据功能,调用
DATracker.enableTracker(this, "demo", "1.0", "Google Play", false);
如需要设置只在 wifi 环境下发送数据,调用
DATracker.enableTracker(this, "demo", "1.0", "Google Play", true, true);
Android 4.0以下版本必须在 App 中所有的 Activity onResume
方法中调用如下方法,标识用户会话开始。Android 4.0及以上版本无需调用。
DATracker.getInstance().resume();
Android 4.0以下版本必须在 App 中所有 Activity onPause
方法添加调用,标识用户会话结束。Android 4.0及以上版本无需调用。
DATracker.getInstance().close();
如果应用中包含 Activitiy 类继承于自定义 Activity 衍生类,则只需在该类加入上述代码即可,即 onResume
中添加 resume
,onPause
中添加 close
方法,如果 Main Activity 也继承于该类,则还需在 onCreate
中添加 enableTracker
,其子类不需要添加。但其他非集成于此类的 Activitiy 类必须按上述规则添加代码。
5.1. 开启A/B测试
- 接口定义
/**
* 打开ab test
*
* @param abEnabled
*/
public DATracker enableABTest(boolean abEnabled)
- 示例调用
DATracker.getInstance()
.enableLog(true)
.enableABTest(true);
5.2. 获取“实验变量”
“实验变量”的值控制展示的内容或程序的逻辑。一般情况下,不同实验版本应有不同的变量值。实验变量值应由相关人员在后台提前录入,如下图所示:
SDK提供两个接口获取“实验变量”:同步获取和异步获取。
(1) 同步获取:从缓存获取,若命中,则返回缓存的变量值;否则,返回默认值。
- 接口定义
public <V> V getVariable(String variableName, V defaultValue)
- 示例调用
// 获取Boolean类型的试验变量isNewHome的值,第二个参数为设定默认值
if (DATracker.getInstance().getVariable("isNewHome", false)) {
// 跳转至新首页
} else {
// 跳转至旧首页
}
(2) 异步获取:从网络获取,若网络请求成功,则返回最新的变量值并更新缓存;否则,返回默认值。
- 接口定义
/**
* @param variableName 实验变量名
* @param defaultValue 默认值
* @param listener 异步回调
* @param <V>
*/
public <V> void asyncGetVariable(final String variableName, final V defaultValue, final OnVariableReceived<V> listener)
- 示例调用
DATracker.getInstance().asyncGetVariable("isNewHome", false, new OnVariableReceived<Boolean>() {
@Override
public void onReceived(Boolean value) {
if (value) {
// 跳转至新首页
} else {
// 跳转至旧首页
}
}
});
配置说明
名称 | 含义 | 可选值 | 是否支持 |
---|---|---|---|
autoLog | 是否开启全埋点 | true,false | 不支持 |
pageLog | 是否开启pageView事件 | true,false | 支持 |
enableABTest | 是否开启AB Test | true,false | 支持 |
abTestInterval | 实验数据更新频率 | time(h) | 支持 |
updateInterval | 云端配置更新频率 | time(h) | 支持 |
使用Debug可以实时远程查看上传的debug数据,便于测试;web端开关可控制debug数据是否写入线上数据库。
SDK默认使用HttpURLConnection
进行数据上报,开发人员如果希望自定义数据上报操作(比如实现免流量功能),可在初始化SDK时,多传入一个DAClient实例,示例代码如下:
DATracker.enableTracker(getApplicationContext(), "MA-809E-F83D9C323504", "1.0", "Google Play", true, false, new MyClient());
DAClient定义如下:
public interface DAClient {
android.util.Pair<Integer, String> execute(String endpointUrl, Map<String, String> headers, byte[] dataEncrypted);
}
其中,endpointUrl为数据上报服务器;headers为http/https请求头部参数,包括数据编码、加密的必要参数,开发人员构造http/https请求时,必须添加这些头部参数;dataEncrypted为加密后的数据。
DAClient实例示例代码如下:
public class MyClient implements DAClient {
private String TAG = "MyClient";
private SSLSocketFactory mFoundSSLFactory;
public MyClient() {
// By default, we use a clean, FACTORY default SSLSocket. In general this is the right
// thing to do.
try {
final SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, null, null);
mFoundSSLFactory = sslContext.getSocketFactory();
} catch (final GeneralSecurityException e) {
Log.i("TAG", "System has no SSL support. Built-in events editor will not be available", e);
mFoundSSLFactory = null;
}
}
@Override
public Pair<Integer, String> execute(String endpointUrl, Map<String, String> headers, byte[] dataEncrypted) {
byte[] response = performRequest(endpointUrl, headers, dataEncrypted);
if (response == null) {
Log.d(TAG, "the response is null, abort");
return null;
}
try {
JSONObject json = new JSONObject(new String(response));
int code = json.optInt("code");
if (code == 200) {
Log.d(TAG, "Finish uploading: " + code);
return new Pair<Integer, String>(code, "Finish uploading");
} else {
Log.d(TAG, "Failed to upload, resonse code: " + code);
return new Pair<Integer, String>(code, "Failed to upload");
}
} catch (JSONException e) {
Log.d(TAG, "Failed to transfer response from the internet to JsonObject: " + e.getLocalizedMessage());
return new Pair<Integer, String>(4004, "Failed to transfer response from the internet to JsonObject");
}
}
public byte[] performRequest(String endpointUrl, Map<String, String> headers, byte[] dataEncrypted) {
Log.v(TAG, "Attempting request to " + endpointUrl);
byte[] response = null;
// the while(retries) loop is a workaround for a bug in some Android HttpURLConnection
// libraries- The underlying library will attempt to reuse stale connections,
// meaning the second (or every other) attempt to connect fails with an EOFException.
// Apparently this nasty retry logic is the current state of the workaround art.
int retries = 0;
boolean succeeded = false;
while (retries < 3 && !succeeded) {
InputStream in = null;
OutputStream out = null;
BufferedOutputStream bout = null;
HttpURLConnection connection = null;
try {
final URL url = new URL(endpointUrl);
connection = (HttpURLConnection) url.openConnection();
if (null != mFoundSSLFactory && connection instanceof HttpsURLConnection) {
((HttpsURLConnection) connection).setSSLSocketFactory(mFoundSSLFactory)
;
}
connection.setConnectTimeout(2000);
connection.setReadTimeout(10000);
if (headers != null) {
for (String key : headers.keySet()) {
connection.setRequestProperty(key, headers.get(key));
}
}
connection.setFixedLengthStreamingMode(dataEncrypted.length);
connection.setDoOutput(true);
connection.setRequestMethod("POST");
out = connection.getOutputStream();
bout = new BufferedOutputStream(out);
bout.write(dataEncrypted);
bout.flush();
bout.close();
bout = null;
out.close();
out = null;
in = connection.getInputStream();
response = slurp(in);
in.close();
in = null;
succeeded = true;
} catch (final Exception e) {
Log.d(TAG, "Error occured during data sending, abort reason: " + e.getMessage());
retries = retries + 1;
} finally {
if (null != bout)
try {
bout.close();
} catch (final IOException e) {
;
}
if (null != out)
try {
out.close();
} catch (final IOException e) {
;
}
if (null != in)
try {
in.close();
} catch (final IOException e) {
;
}
if (null != connection)
connection.disconnect();
}
}
if (retries >= 3) {
Log.v(TAG, "Could not connect to DATracker service after three retries.");
}
return response;
}
private static byte[] slurp(final InputStream inputStream)
throws IOException {
final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[8192];
while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
return buffer.toByteArray();
}
}
如果App开发人员需要查看SDK内部日志,可通过该接口打开日志。默认关闭。
开启控制台日志。建议在自定义Application
的 onCreate 中调用。
DATracker.getInstance().enableLog(true);
关闭控制台日志。建议在自定义Application
的 onCreate 中调用。
DATracker.getInstance().enableLog(false);
当app具备定位权限且该接口设置为true时,读取定位数据。否则,不读取。默认为false。
DATracker.getInstance().enableLocationAccess(true);
手动发送数据
DATracker.getInstance().upload();
这里的自动上传仅仅指的是允许 SDK 在会话开始和进入后台时自动上传数据
DATracker.getInstance().setAutoUploadOn(false);
当用户调用该接口设置两次数据发送的最小时间间隔interval(ms)时,开启固定间隔自动上传数据,默认关闭。当interval < 15000ms 时,仍按照默认值 15000ms 计算,即用户设置的间隔时间不得低于默认值 15000ms。
public void setFlushInterval(long flushInterval);
当用户调用该接口设置本地数据库缓存的最大记录数时,开启超出阈值立即上传数据,默认关闭。当用户设置的 flushBulkSize < 100 时,仍按照默认值 100 计算,即用户设置的最大记录数不得低于默认值 100。
public void setFlushBulkSize(int flushBulkSize);
DATracker.getInstance().setSendOnWifiOn(true);
设置为只在 WIFI 下发送数据,会导致服务器接收数据延迟,对统计系统结果的及时性会产生影响,不建议使用
启用推广追踪,请在 Main Activity 里紧跟 启用 API
后调用
DATracker.getInstance().enableCampaign();
此方法只需要在 自定义Application 或 Main Activity 内调用,旧版接口,不推荐使用
DATracker.getInstance().getDeviceId();
该 Device ID 并非 Apple UDID, 仅用户系统本身设备去重用途, 并且可能根据 Apple 政策做相应调整, 不保证长期唯一性
在用户登录后,请调用如下接口,参数为用户帐号
public void loginUser(String userId);
当用户登出后,请调用
public void logoutUser();
如登录发生在需要捕捉事件后,则该事件无用户信息
在拿到用户经纬度时, 调用如下接口记录用户位置
public void setLocation(double latitude, double longitude);
或者如果App开启了定位权限,可以调用如下接口设置sdk的定位读取权限。若设置为true,sdk会在应用进入前台时,自动读取定位数据,部分机型可能会弹出定位询问对话框。若设置为false,sdk不会读取定位数据。默认为false。
public void enableLocationAccess(boolean bool);
调用如下方法进行事件捕捉
public void trackEvent(String eventId);
public void trackEvent(final String eventId, final Map<String, String> attributes);
eventId 为事件标识,如 "login", "buy"
DATracker.getInstance().trackEvent("login");
attributes 为自定义字段名称,格式如 "{"money":"100", "timestamp":"1357872572"}"
可对事件发生时的其他信息进行记录
Map<String, String> attr = new HashMap<String, String>();
attr.put("money", "100");
DATracker.getInstance().trackEvent("login", attr);
如果需要记录事件发生持续时间,可调用如下接口
public void trackEvent(String eventId, int costTime);
public void trackEvent(final String eventId, final int costTime, final Map<String, String> attributes);
如果需要记录事件发生时的位置信息, 可调用如下接口
public void trackEvent(final String eventId, double latitude, double longitude);
public void trackEvent(final String eventId, double latitude, double longitude,
final Map<String, String> attributes)
如果需要记录发生持续时间以及记录事件发生时的位置信息, 可调用如下接口
public void trackEvent(final String eventId, final int costTime, double latitude, double longitude,
final Map<String, String> attributes)
虽然在任何地方都可以进行事件捕捉,但最好不要在较多循环内或者非主线程中调用,以及最好不要使用很长 eventID 或者 key value 值,否则会增加 SDK 发送的数据量
特别地,如果某个事件的属性,在所有事件中都会出现,可以将该属性设置为事件通用属性,通用属性会保存在 App 本地,可调用如下接口:
public void registerSuperProperties(Map<String, String> superProperties);
成功设置事件通用属性后,再通过 trackEvent 追踪事件时,事件通用属性会被添加进每个事件中。重复调用 registerSuperProperties 会覆盖之前已设置的通用属性。
如果不覆盖之前已经设定的通用属性,可调用:
public void registerSuperPropertiesOnce(Map<String, String> superProperties);
查看当前已设置的通用属性,调用:
public Map<String,String> currentSuperProperties();
删除一个通用属性,调用:
public void unregisterSuperProperty(String superPropertyName);
删除所有已设置的事件通用属性,调用:
public void clearSuperProperties();
当事件通用属性和事件属性的 Key 冲突时,事件属性优先级最高,它会覆盖事件公共属性。
可以通过计时器统计事件的持续时间,默认的时间单位是毫秒。首先,在事件开始时调用 trackTimer 记录事件开始时间,该方法并不会真正发送事件,接口为
public void trackTimer(final String eventId);
public void trackTimer(final String eventId, final TimeUnit timeUnit);
调用trackEvent 时,若已记录该事件的开始时间,SDK会在追踪相关事件时自动将事件持续时间记录在事件属性中,并删除该事件定时器。
清除所有的事件定时器,调用:
public void clearTimedEvents();
多次调用 trackTimer 时,相同 eventId 的事件的开始时间以最后一次调用时为准。
在 try catch block 里面调用,参数为 Exception (含子类)实例
try {
int b = 1/0;
} catch (ArithmeticException e) {
DATracker.getInstance().trackException(e);
}
如还需要记录 Callstack,可调用
DATracker.getInstance().trackExceptionWithCallstack(e);
如需要 crash 捕捉, 需要在启用 SDK 后在每个需要捕捉 crash 信息的线程中调用如下方法来开启该功能
Thread.setDefaultUncaughtExceptionHandler(new DATracker.UncaughtExceptionHandler());
如需要在 Activity 中捕捉 crash,则需要在 onCreate 里面调用如下方法
Thread.setDefaultUncaughtExceptionHandler(new DATracker.UncaughtExceptionHandler());
如需捕捉应用运行过程中的所有 crash,则需在自定义Application
的 onCreate 中调用如下方法。推荐使用。
Thread.setDefaultUncaughtExceptionHandler(new DATracker.UncaughtExceptionHandler());
public void trackScreen(String screenName);
screenName 为当前 View 名称
keyword 为搜索关键词,searchType 为搜索类型,比如新闻搜索,视频搜索等
public void trackSearch(String keyword, String searchType);
content 为分享内容,from 为分享发生地,to 为分享目的地,比如新浪微博,网易微博等
public void trackShare(String content, String from, String to);
对用户的任务进行记录,参数为任务 id 和任务失败原因,可用于用户行为完成,用户行为耗时等统计。
DATracker.getInstance().trackOnMissionBegan("mission-1")
DATracker.getInstance().trackOnMissionAccomplished("mission-1");
DATracker.getInstance().trackOnMissionFailed("mission-2", "no power");
public void trackOrder(@NonNull double amount, @NonNull String unit, Map<String, String> attr)
amount 为订单金额,不可为空;unit 为货币单位,采用国际通用标准,例如人民币 “CNY”,不可为空;attr 为其他自定义属性,可以为空
为了更准确地提供针对人群的分析服务,可以使用 SDK 的 DATracker$People 设置用户属性。用户可以在留存分析、分布分析等功能中,使用用户属性作为过滤条件,精确分析特定人群的指标。
获取当前用户信息设置实例
DATracker.getInstance().getPeople();
设置当前用户信息属性(全局或单个)
public void set(Map<String, String> properties);
public void set(String property, String value);
设置当前用户信息属性(如果该属性已经设置过,则忽略)。与 set() 方法不同的是,如果被设置的用户属性已存在,则这条记录会被忽略而不会覆盖已有数据,如果属性不存在则会自动创建。因此,setOnce() 比较适用于为用户设置首次激活时间、首次注册时间等属性。
public void setOnce(Map<String, String> properties);
public void setOnce(String property, String value);
清除当前用户信息属性
public void unset(String property);
删除当前用户记录
public void deleteUser();
记录用户消费接口(用于用户价值评估功能)。正数金额代表客户的消费金额,负金额代表客户的退款。
public void trackCharge(double amount);
public void trackCharge(double amount, Map<String, String> properties);
清除用户消费记录
public void clearCharges();
设置用户账户
public People setAccount(String account);
设置用户真实姓名
public People setRealName(String realName);
设置用户性别(0-女,1-男,2-未知)
public People setGender(int gender);
设置用户出生日期(SDK会自动转换格式:yyyy-MM-dd )
public People setBirthday(Date birthday);
连续设置用户基本信息
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
try {
Date date = dateFormat.parse("1989-08-03");
DATracker.getInstance().getPeople().setAccount("nailperry").setRealName("张三").setGender(1).setBirthday(date);
} catch (ParseException e) {
e.printStackTrace();
}
一次性设置用户基本信息
public void setPopulationAttributes(String account, String realName, Date birthday, int gender);
设置用户地址信息
public void setLocation(String country, String region, String city);
31.1. 版本要求
Android 4.0+
31.2. 默认采集页面数据
EventID
为 固定统一的 da_screen
dateType
为 pv
properties
的参数设计如下:
(1) $screenName
为当前页面的名称;
- 当页面统计的当前页面为
Activity
时,$screenName
为ActivityName
; - 当页面统计的当前页面为
Activity
下的Fragment
时,$screenName
为ActivityName/FragmentName
。
(2) $screenTitle
为当前页面的title
,可为空;
31.3. 页面统计开关(默认为true)
开启
DATracker.getInstance().enablePageTrack(true);
关闭
DATracker.getInstance().enablePageTrack(false);
31.4. 自定义页面信息
- Fragment
对于 App 中的核心页面Fragment
,我们提供了一个接口 FragmentAutoTracker
:
public interface FragmentAutoTracker {
/**
* 返回当前页面的Url
* 用作下个页面的referrer
* @return String
*/
String getScreenUrl();
/**
* 返回当前页面的Title
* @return String
*/
String getScreenTitle();
/**
* 返回自定义属性集合
* 我们内置了两个属性:$screenName,代表当前页面名称;$screenTitle 为当前页面的title,可为空;
* 默认情况下,
* $screenName会采集当前Activity的CanonicalName,即:
* activity.getClass().getCanonicalName(), 如果想自定义页面名称, 可以在Map里put该key进行覆盖。注意:screenName的前面必须要要加"$"符号。
* $screenTitle 会通过activity.getTitle().toString()采集页面主题,如果想自定义页面主题,可重写getScreenTitle()函数。
*
* @return Map<String, String>
*/
Map<String, String> getTrackProperties();
}
当用户实现该接口时,SDK 会将 getTrackProperties 返回的属性(Map类型)加入页面统计事件的属性中,作为用户访问该页面时的事件属性;SDK 会将 getScreenUrl 返回的字符串作为页面的 Url Schema,记录在页面统计事件的 $url 属性中,并且当用户切换页面时,将前一个页面中的 Url Schema 作为当前页面事件的 $referrer 属性。
例如:
public class OrderDetailFragment extends Fragment implements FragmentAutoTracker {
@Override
public String getScreenUrl() {
return "da://page/order/detail?orderId=888888";
}
@Override
public String getScreenTitle() {
return "订单详情";
}
@Override
public Map<String, String> getTrackProperties() {
Map<String, String> properties = new HashMap<>();
properties.put("orderId", "888888");
properties.put("manufacturer", "da");
return properties;
}
}
- Activity
对于 App 中的核心页面Activity
,我们提供了一个接口 ActivityAutoTracker
:
public interface ActivityAutoTracker extends FragmentAutoTracker{
boolean trackFragmentAsScreen();
}
该接口相比于Fragment多了一个trackFragmentAsScreen()
函数,当该函数返回 true 时,则将Activity中的Fragment作为页面进行统计,而不统计Activity页面。当该函数返回false时,则只统计Activity页面,不统计Activity中的Fragment。此功能需结合Fragment数据采集使用。
当对Activity中的Fragment进行数据采集时,请确保
trackFragmentAsScreen()
返回true。
31.5. 过滤部分页面
开启PageTrack后,如果需要指定部分页面不被PageTrack,可以按照下面示例指定哪些页面不被PageTrack:
HashSet<String> list = new HashSet<>();
list.add(MainActivity.class.getCanonicalName());
DATracker.getInstance().filterAutoTrackActivities(list);
31.6. 采集Fragment数据
情形一:
一个Activity
同一时刻在屏幕中只将一个Fragment
作为页面进行统计的情形,例如,主页(Activity
)通过底部Tab
切换Fragment
,每切换到一个Tab
,便将当前Tab
对应的Fragment
作为页面进行统计。
对于需要进行页面统计的Fragment
,除了在Fragment
的onResume()
、onPause()
生命周期中分别加入onFragmentResume
和onFragmentPause
代码外,APP开发人员还需要根据Fragment
的管理方式重写setUserVisibleHint
或onHiddenChanged
方法。如果不清楚是否应该重写setUserVisibleHint
或onHiddenChanged
方法,建议这两个方法都重写。
建议上述代码可以在一个基类TrackedFragment
中做,让所有需要进行页面统计的Fragment
类都继承这个基类TrackedFragment
,就完成了所有子类页面埋点。
代码示例如下:
public class TrackedFragment extends Fragment{
@Override
public void onResume() {
super.onResume();
DATracker.getInstance().onFragmentResume(this);
}
@Override
public void onPause() {
super.onPause();
DATracker.getInstance().onFragmentPause(this);
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
DATracker.getInstance().setFragmentUserVisibleHint(this, isVisibleToUser);
}
@Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
DATracker.getInstance().onFragmentHiddenChanged(this, hidden);
}
}
当Activity
实现ActivityAutoTracker
接口且trackFragmentAsScreen()
返回true时,SDK 会自动识别Activity
中当前显示的Fragment
并进行数据采集。反之,当Activity
没有实现ActivityAutoTracker
接口或者trackFragmentAsScreen()
返回false时,不采集该Activity
下的任何Fragment数据。
情形二:(局限性)
当一个Activity
下同时在屏幕中显示多个调用了SDK的onFragmentResume
、onFragmentPause
接口的Fragment
时,我们无法判断将哪个作为页面统计。
31.7. 页面时长统计
31.7.1. 启用
开关
DATracker.getInstance().enablePageTrack(true);
Activity
打开开关后,即可自动统计,无需添加额外代码。
Fragment 和 V4Fragment
需要分别继承 HubbleBaseFragment 和 HubbleBaseV4Fragment 两个基类。
31.7.2. 设置业务属性
接口
实现下面接口 (Activity、Fragment、V4Fragment)
public interface IHubblePageInfo { /** * 获取页面自定义属性 * * @return 页面自定义属性的封装对象 */ HubblePageInfo getPageInfo(); }
示例
public class DemoActivity extends Activity implements IHubblePageInfo { private HubblePageInfo mHubblePageInfo; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_demo); } @Override public HubblePageInfo getPageInfo() { // 创建对象,也可以放在其他位置 if (mHubblePageInfo == null) { mHubblePageInfo = new HubblePageInfo(); } // 设置属性,也可以放在其他位置,原则上赋值时间越早越好 // 自定义 eventId(可选)。如果不设置,SDK 默认设为 “da_duration_当前类名” mHubblePageInfo.eventId = "id"; // 自定义属性(可选) mHubblePageInfo.attributes.put("key1", "value1"); mHubblePageInfo.attributes.put("key2", "value2"); // 返回页面属性对象(必填) return mHubblePageInfo; } }
原则
- HubblePageInfo 对象必须声明为成员变量,否则会影响统计数据。
- HubblePageInfo 对象的创建和属性赋值可以仿照上面示例的用法,也可以放在别处,原则上时间越早越好。 比如,一拿到属性数据就可以设置了。
32.1. 最低版本要求
Android **5.0**(我们使用了[MediaProjection][1]来共享屏幕)32.2. 需要的权限
<!-- Ab编程试验需要的权限 -->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
32.3. 接入代码样例
DATracker.getInstance().enableABVisualization(true);
32.4. 说明:
32.5. 1. 关于授权
我们需要两个权限, 一个是android.permission.SYSTEM_ALERT_WINDOW
, 我们已经在SDK里面做了权限的申请, 第一次授权成功后, 请重新扫描二维码打开应用. 如果在左下角看到了悬浮按钮, 就说授权成功了.
应用每次扫描二维码打开时, 会向用户申请录制屏幕的权限, 目前只有授权成功后才会开始分享屏幕.如果用不到该功能, 可以不写这个权限生命.
32.6. 关于proguard
SDK已经进行了proguard, 请不要二次proguard!!