# Android集成指南

### BeaconReport

灯塔SDK用于上报的主类，该对象为单例对象。

#### 初始化SDK

```java
public void start(@NonNull Context context, @NonNull TunnelInfo info, @Nullable final BeaconConfig config)
// 参数2
 TunnelInfo(@NonNull String appKey, String version, String channelID)
```

例如：

```java
BeaconConfig config = BeaconConfig.builder()
             .strictMode(false)// 是否开启严苛模式，会检查事件参数规范，并抛出异常
             .logAble(true)//是否打开日志
             // 设置用于上报的OKHttpClient（可以与业务共用一个Client），该项也可以不设置
             .setHttpAdapter(OkHttpAdapter.create(new OkHttpClient()))
             .build();
BeaconReport beaconReport = BeaconReport.getInstance();
beaconReport.startWithTunnelInfo(this, new TunnelInfo(APP_KEY), config);
```

注意： 1. Context、TunnelInfo不可为空 2. 灯塔SDK内部默认使用Socket做网络通信，若传入OKHttpClient会优先使用https上报，**建议使用OKHttp**。 3. **打开日志后，qimei将以Toast的形式弹出，并复制到剪贴板。（上线前务必关闭！）**

#### 上报事件

```java
public EventResult report(BeaconEvent beaconEvent);
```

例如：

```java
Map<String, String> params = new HashMap<>();
params.put("k1", "v1");
BeaconEvent event = BeaconEvent.builder()
                .withCode("onClick")// 必须
                .withParams(params) //非必须
                .build();
EventResult result = BeaconReport.getInstance().report(event);
Log.i("TAG", "EventResult{ eventID:" + result.eventID + ", errorCode: " + result.errorCode + ", errorMsg: " + result.errMsg + "}");
```

若该事件符合上报规范，则**错误码为0**，并且返回该事件在SDK中的唯一ID(以实时和普通分别计算)，若不符合上报规范则返回错误码以及信息，错误码对应表见附录。

注意： 1. 若BeaconEvent中AppKey参数传空则默认为宿主AppKey 2. EventCode不可为空！ 3. params中单个value最大长度为10K，kv整体最大为45K

#### 获取Qimei

1. 同步获取Qimei

```java
    @Nullable
    public Qimei getQimei();
```

1. 异步获取Qimei

```java
public void getQimei(IAsyncQimeiListener listener);
```

例如：

```java
beaconReport.getQimei(new IAsyncQimeiListener() {
          @Override
          public void onQimeiDispatch(Qimei qimei) {
              Log.i(TAG, "OldQimei: " + qimei.getQimeiOld() + ", newQimei: " + qimei.getQimeiNew());
          }
      });
```

其中OldQime为原来可能为androidID、imei、mac的qimei，A3字段。newQimei为标准的36位qimei，需要后台配置打开双列Qimei才会有值，对应A153字段。

#### 注册多通道

```java
public void registerTunnel(TunnelInfo tunnelInfo);
```

注册多通道上报，即多份AppKey使用同一份灯塔SDK

例如：

```java
BeaconReport.getInstance().registerTunnel(new TunnelInfo("0M300V63NP0NGUB3", "1.1", "channel"));
```

注意：上报BeaconEvent时，必须填充和TunnelInfo中一致的AppKey。

#### 获取灯塔采集参数

```java
public BeaconPubParams getCommonParams(Context context);
```

返回灯塔SDK采集到用户信息。

#### 停止事件上报

```java
public void stopReport(boolean immediately);
```

当App处于后台或弱网需要减少灯塔SDK使用的资源时，可以停止灯塔SDK内部轮询以及网络请求。

#### 恢复事件上报

```java
public void resumeReport();
```

当调用了停止事件上报后需要恢复灯塔SDK轮询时调用。

#### 获取当前SDK版本

```java
public String getSDKVersion();
```

### BeaconEvent

```java
public final class BeaconEvent {
    private String appKey; //该事件AppKey
    private String code; // 该事件名
    private EventType type; //事件类型
    private boolean isSucceed;// 是否成功
    private Map<String, String> params;// 事件参数
//...
```

例如：

```java
Map<String, String> params = new HashMap<>();
params.put("k1", "v1");
BeaconEvent event = BeaconEvent.builder()
                .withCode("onClick") //必填
                .withType(EventType.REALTIME) //非必须，默认为普通事件
                .withParams(params) //非必须
                .withAppKey(appKey)// 非必须，默认为宿主AppKey
                .withIsSucceed(true)// 非必须，默认为true
                .build();
```

### BeaconConfig

在初始化时传入配置，非必须传入

```java
public class BeaconConfig {
    private final int maxDBCount;//DB存储的最大事件条数(实时和普通分开计算)，默认为1万条
    private final boolean strictMode;// 严苛模式，默认false
    private final boolean logAble;// 日志开关，默认false
    private final boolean abroad;// 是否开启海外版，对qimei有影响，默认false
    private final boolean eventReportEnable; // 是否打开事件上报功能,默认true
    private final boolean auditEnable; // 是否开启稽核功能，默认true
    private final boolean bidEnable;// 是否开启BeaconID信息采集,默认true
    private final boolean collectMACEnable;//是否采集MAC地址信息，默认true
    private final boolean collectIMEIEnable;// 采集IMEI、IMSI信息，默认true
    private final long realtimePollingTime;//实时事件上报轮询间隔(ms)
    private final long normalPollingTIme;// 普通事件上报轮询间隔(ms)
    private final NetAdapter httpAdapter;// 设置OKHttpClient
```

例如：

```java
  BeaconConfig config = BeaconConfig.builder()
                .strictMode(true)
                .logAble(true)
                .maxDBCount(20_000)
                .collectIMEIEnable(false)
                .collectMACEnable(false)
                .setNormalPollingTime(3000)
                .setRealtimePollingTime(1000)
                .setHttpAdapter(OkHttpAdapter.create(new OkHttpClient()))
                .build();
```

### EventResult

```java
public final class EventResult{
 public int errorCode;
 public long eventID;
 public String errMsg;
}
```

### EventType

```java
public enum EventType {
    // 普通事件
    NORMAL,
    // 实时事件
    REALTIME,
    // 大同普通事件
    DT_NORMAL,
    // 大同实时事件
    DT_REALTIME,
}
```

### Qimei

```java
public final class Qimei {
    // A3
    private String qimeiOld;
    // A153 Qimei
    private String qimeiNew;
    // 全部Qimei
    private Map<String, String> qimeiMap;
// ...
    public boolean isEmpty() {
        return qimeiMap == null || qimeiMap.isEmpty();
    }
```

### BeaconPubParams

灯塔采集信息对象

```java
public class BeaconPubParams {
    private String boundleId;                       // B: App包名
    private String appVersion;                      // G: 产品版本
    private String sdkId;                           // G: SDK Id
    private String sdkVersion;                      // G: SDK 版本
    private String productId;                       // G: AppKey
    private String beaconId;                        // EV: Beacon Id
    private String appFirstInstallTime;           // EV：宿主App首次安装时间
    private String appLastUpdatedTime;            // EV: 宿主App最近一更新时间
    private String platform;                         // G: 平台
    private String dtMf;                            // EV: manufacturer，新增采集
    private String osVersion;                       // G: 固件版本
    private String hardwareOs;                      // 设备信息
    private String brand;                            // EV: 品牌
    private String model;                            // G: 机型
    private String language;                         // EV: 语言
    private String resolution;                       // EV: 分辨率
    private String dpi;                              // EV: Density per inch
    private String gpu;                              // GPU info
    private String isRooted;                        // EV: 是否rooted
    private String fingerprint;                      // EV: 指纹信息
    private String qimei;                            // EV: QIMEI
    private String imei;                             // EV: IEMI
    private String dtImei2;                         // EV: IMEI2:新增采集
    private String dtMeid;                          // EV: MEID: 新增采集
    private String imsi;                             // EV: IMSI
    private String androidId;                       // EV: ANDROID_ID
    private String modelApn;                        // G: 设备设置APN
    private String mac;                              // EV: MAC
    private String wifiMac;                         // EV: WiFi Mac
    private String wifiSsid;                        // EV: WiFi ssid
    private String allSsid;                         // a109：扫描当前设备连接的路由器下的所有设备IP和mac地址，第一组为本机的IP和mac地址
    private String networkType;                     // 网络类型
    private String cid;                              // EV：SD卡id

        // getter,setter
```

### 附录

1. 事件错误码对应表

| 错误码 |       含义       |
| :-: | :------------: |
|  0  |       成功       |
| 101 |    事件被后台配置抽样   |
| 102 |    事件模块功能被关闭   |
| 103 |   事件被提交到DB失败   |
| 104 |   当前事件没有对应的通道  |
| 105 | 事件整体kv字符串大于45K |
| 106 |      事件名为空     |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://beacon-help.gitbook.io/beacon-help/sdk-wen-dang/sdkji-cheng-zhi-nan/androidji-cheng-zhi-nan.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
