> ## Documentation Index
> Fetch the complete documentation index at: https://docs.flashcat.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# Android SDK 数据收集

> 全面了解 Flashduty Android RUM SDK 自动收集的性能指标、事件属性和设备信息

<Info>
  Flashduty Android RUM SDK 默认自动收集所有 RUM 事件的多个指标和属性。您还可以通过 API 添加自定义属性以扩展默认数据集。
</Info>

## 应用启动指标

Flashduty 自动收集以下应用启动性能指标：

| 指标                            | 描述              | 测量范围                          |
| ----------------------------- | --------------- | ----------------------------- |
| **cold\_start\_duration**     | 冷启动持续时间         | 从应用进程创建到首个 Activity 渲染完成      |
| **warm\_start\_duration**     | 温启动持续时间         | 应用进程已存在，从 Activity 开始到渲染完成    |
| **hot\_start\_duration**      | 热启动持续时间         | 应用和 Activity 都在内存中，从恢复到渲染完成   |
| **activity\_start\_duration** | Activity 启动持续时间 | 从 `onCreate` 到首帧绘制完成          |
| **is\_pre\_warmed**           | 预热启动标识          | 布尔值，指示应用是否通过预热启动（Android 11+） |

<Tip>
  **启动类型说明：**

  * **冷启动** - 应用首次启动或进程被终止后启动，需要加载所有资源并初始化应用状态
  * **温启动** - 应用进程在内存中，但 Activity 需要重新创建
  * **热启动** - 应用和 Activity 都在内存中，只需将 Activity 带回前台
</Tip>

## Views 监控

View 代表用户在应用中看到的唯一屏幕。每个 View 开始时会创建一个新的 RUM 事件，并在 View 的整个生命周期内更新该事件。

<Note>
  View 会收集其生命周期内发生的所有资源、操作、错误和长任务的相关信息。
</Note>

### 自动追踪策略

在 Android 中，Activities 和 Fragments 被视为 View。SDK 提供以下自动追踪策略：

| 策略                                 | 描述                        | 适用场景              |
| ---------------------------------- | ------------------------- | ----------------- |
| **ActivityViewTrackingStrategy**   | 基于 Activity 生命周期追踪        | 传统 Activity 架构    |
| **FragmentViewTrackingStrategy**   | 基于 Fragment 生命周期追踪        | Fragment 为主的应用    |
| **MixedViewTrackingStrategy**      | 同时追踪 Activity 和 Fragment  | 混合架构应用            |
| **NavigationViewTrackingStrategy** | 适用于 Jetpack Navigation 组件 | 使用 Navigation 的应用 |

<Tip>
  您也可以通过手动调用 `RumMonitor.startView()` 和 `RumMonitor.stopView()` 来自定义 View 追踪。
</Tip>

## 默认属性

RUM SDK 为所有事件自动附加默认属性，帮助您了解用户设备、网络状态和应用上下文。

<AccordionGroup>
  <Accordion title="通用核心属性">
    | 属性名                   | 类型     | 描述                                                     |
    | --------------------- | ------ | ------------------------------------------------------ |
    | `application.id`      | string | Flashduty 应用 ID。                                       |
    | `application.name`    | string | 应用包名(例如 `com.example.app`)。                            |
    | `application.version` | string | 应用版本名称。                                                |
    | `application.build`   | string | 应用构建版本号。                                               |
    | `session.id`          | string | 唯一会话 ID,用于将用户旅程中的事件分组。                                 |
    | `session.type`        | string | 会话类型:`user`。                                           |
    | `view.id`             | string | 为每个 View 生成的唯一 ID。                                     |
    | `view.url`            | string | View 的规范化 URL(Activity 或 Fragment 的类名)。                |
    | `view.name`           | string | 可自定义的 View 名称。                                         |
    | `env`                 | string | 应用的环境名称(例如 `prod`、`dev`)。                              |
    | `service`             | string | 服务名称,用于区分应用的不同模块或微服务。                                  |
    | `version`             | string | 应用版本。                                                  |
    | `sdk_version`         | string | Flashduty SDK 版本。                                      |
    | `date`                | number | 事件发生的时间戳（epoch 毫秒）                                     |
    | `type`                | string | 事件类型（如 `view`、`resource`、`action`、`error`、`long_task`） |
  </Accordion>

  <Accordion title="设备属性">
    以下属性与设备相关，在所有 RUM 事件中自动收集：

    | 属性名                     | 类型     | 描述                               |
    | ----------------------- | ------ | -------------------------------- |
    | `device.type`           | string | 设备类型,如 `mobile`、`tablet`、`tv` 等。 |
    | `device.name`           | string | 设备商业名称(例如 `Samsung Galaxy S21`)。 |
    | `device.model`          | string | 设备型号(例如 `SM-G991B`)。             |
    | `device.brand`          | string | 设备品牌(例如 `Samsung`)。              |
    | `device.architecture`   | string | 设备架构（例如 `arm64-v8a`）             |
    | `device.marketing_name` | string | 设备的市场营销名称                        |
  </Accordion>

  <Accordion title="连接性属性">
    以下网络相关属性在所有 RUM 事件中自动收集：

    | 属性名                                  | 类型     | 描述                                              |
    | ------------------------------------ | ------ | ----------------------------------------------- |
    | `connectivity.status`                | string | 设备网络可达性状态(`connected`、`not_connected`、`maybe`)。 |
    | `connectivity.interfaces`            | array  | 可用网络接口列表(例如 `wifi`、`cellular`、`ethernet`)。      |
    | `connectivity.cellular.technology`   | string | 蜂窝网络技术类型（例如 `LTE`、`5G`）                         |
    | `connectivity.cellular.carrier_name` | string | 运营商名称（例如 `中国移动`）                                |
  </Accordion>

  <Accordion title="操作系统属性">
    以下操作系统相关属性在所有 RUM 事件中自动收集：

    | 属性名                | 类型     | 描述                          |
    | ------------------ | ------ | --------------------------- |
    | `os.name`          | string | 操作系统名称(例如 `Android`)。       |
    | `os.version`       | string | 操作系统版本(例如 `13`)。            |
    | `os.version_major` | string | 操作系统主版本号（例如 `13`）           |
    | `os.build`         | string | 系统构建号（例如 `TQ2A.230505.002`） |
  </Accordion>

  <Accordion title="地理位置属性">
    RUM 可以从用户的 IP 地址推断出地理位置信息：

    | 属性名               | 类型     | 描述         |
    | ----------------- | ------ | ---------- |
    | `geo.country`     | string | 国家名称       |
    | `geo.country_iso` | string | 国家的 ISO 代码 |
    | `geo.city`        | string | 城市名称       |

    <Note>
      地理位置信息由 Flashduty 后端根据客户端 IP 地址推断，不会在客户端收集精确的 GPS 位置。
    </Note>
  </Accordion>

  <Accordion title="全局用户属性">
    您可以通过 `setUser()` API 设置用户信息，这些信息会被附加到所有 RUM 事件中：

    | 属性名         | 类型     | 描述        |
    | ----------- | ------ | --------- |
    | `usr.id`    | string | 用户的唯一标识符  |
    | `usr.name`  | string | 用户的友好名称   |
    | `usr.email` | string | 用户的电子邮件地址 |

    <Tip>
      您还可以添加自定义用户属性，例如 `usr.plan`、`usr.role` 等。
    </Tip>
  </Accordion>
</AccordionGroup>

## 事件特定属性

除了默认属性外，不同类型的 RUM 事件还会收集特定的指标和属性。

<AccordionGroup>
  <Accordion title="Session 属性">
    | 属性名                  | 类型     | 描述           |
    | -------------------- | ------ | ------------ |
    | `session.id`         | string | 唯一会话 ID。     |
    | `session.type`       | string | 会话类型:`user`。 |
    | `session.has_replay` | bool   | 会话是否包含会话重放录制 |
    | `session.is_active`  | bool   | 会话是否处于活动状态   |
  </Accordion>

  <Accordion title="View 属性">
    View 事件包含以下特定属性和性能指标：

    | 属性名                           | 类型         | 描述                                                              |
    | ----------------------------- | ---------- | --------------------------------------------------------------- |
    | `view.id`                     | string     | 每个 View 的唯一 ID。                                                 |
    | `view.name`                   | string     | View 的自定义名称。                                                    |
    | `view.url`                    | string     | View 的 URL(Activity 或 Fragment 类名)。                             |
    | `view.time_spent`             | number(ns) | 用户在此 View 上花费的时间。                                               |
    | `view.loading_time`           | number(ns) | View 加载完成所需的时间。                                                 |
    | `view.loading_type`           | string     | View 加载类型:`initial_load`、`activity_display`、`fragment_display`。 |
    | `view.first_contentful_paint` | number(ns) | 首次内容绘制时间(仅适用于 API 29+)。                                         |
    | `view.action.count`           | number     | View 中收集的所有操作的数量。                                               |
    | `view.resource.count`         | number     | View 中收集的所有资源的数量。                                               |
    | `view.error.count`            | number     | View 中收集的所有错误的数量。                                               |
    | `view.long_task.count`        | number     | View 中收集的所有长任务的数量。                                              |
    | `view.crash.count`            | number     | View 中收集的所有崩溃的数量                                                |
    | `view.is_active`              | bool       | View 是否仍处于活动状态                                                  |
  </Accordion>

  <Accordion title="Resource 属性">
    Resource 事件表示应用中的网络请求。收集的属性包括：

    | 属性名                            | 类型         | 描述                                                                |
    | ------------------------------ | ---------- | ----------------------------------------------------------------- |
    | `resource.id`                  | string     | 资源的唯一标识符。                                                         |
    | `resource.type`                | string     | 资源类型(例如 `xhr`、`fetch`、`image`、`css`、`js`、`font`、`media`、`other`)。 |
    | `resource.url`                 | string     | 资源的 URL。                                                          |
    | `resource.method`              | string     | HTTP 方法(例如 `GET`、`POST`)。                                         |
    | `resource.status_code`         | number     | HTTP 响应状态码。                                                       |
    | `resource.duration`            | number(ns) | 加载资源所花费的总时间。                                                      |
    | `resource.size`                | number     | 资源大小(字节)。                                                         |
    | `resource.dns.duration`        | number(ns) | DNS 解析时间(`domainLookupEnd - domainLookupStart`)。                  |
    | `resource.connect.duration`    | number(ns) | 建立连接的时间(`connectEnd - connectStart`)。                             |
    | `resource.ssl.duration`        | number(ns) | TLS 握手时间(`connectEnd - secureConnectionStart`),仅适用于 HTTPS。        |
    | `resource.first_byte.duration` | number(ns) | 等待首字节响应的时间(`responseStart - requestStart`)。                       |
    | `resource.download.duration`   | number(ns) | 下载响应的时间(`responseEnd - responseStart`)。                           |
    | `resource.redirect.duration`   | number(ns) | 后续 HTTP 重定向所花费的时间(`redirectEnd - redirectStart`)。                 |
    | `resource.provider.name`       | string     | 资源提供商名称,默认为 `unknown`。                                            |
    | `resource.provider.domain`     | string     | 资源提供商域名                                                           |
    | `resource.provider.type`       | string     | 资源提供商类型（如 `first-party`、`cdn`、`ad`、`analytics`）                   |
  </Accordion>

  <Accordion title="Error 属性">
    错误事件收集异常和崩溃信息，错误消息和堆栈跟踪会被自动包含：

    | 属性名              | 类型     | 描述                                                        |
    | ---------------- | ------ | --------------------------------------------------------- |
    | `error.source`   | string | 错误来源(例如 `webview`、`logger`、`network`、`source`、`console`)。 |
    | `error.type`     | string | 错误类型或错误代码。                                                |
    | `error.message`  | string | 简洁、人类可读的单行错误消息。                                           |
    | `error.stack`    | string | 堆栈跟踪或错误的补充信息。                                             |
    | `error.issue_id` | string | 错误问题的唯一标识符。                                               |
    | `error.category` | string | 错误的高级分类,可能的值:`ANR`(应用无响应)、`Exception`(异常)。                |
    | `error.file`     | string | 发生错误的文件名(用于错误追踪问题)。                                       |
    | `error.line`     | number | 发生错误的行号                                                   |
    | `error.is_crash` | bool   | 指示该错误是否导致应用崩溃                                             |

    **网络错误：**

    网络错误包含有关失败的 HTTP 请求的信息，并收集以下属性：

    | 属性名                              | 类型     | 描述                                              |
    | -------------------------------- | ------ | ----------------------------------------------- |
    | `error.resource.status_code`     | number | HTTP 响应状态码。                                     |
    | `error.resource.method`          | string | HTTP 方法(例如 `POST`、`GET`)。                       |
    | `error.resource.url`             | string | 资源 URL。                                         |
    | `error.resource.provider.name`   | string | 资源提供商名称,默认为 `unknown`。                          |
    | `error.resource.provider.domain` | string | 资源提供商域名                                         |
    | `error.resource.provider.type`   | string | 资源提供商类型（如 `first-party`、`cdn`、`ad`、`analytics`） |
  </Accordion>

  <Accordion title="Action 属性">
    Action 代表用户与应用的交互（例如点击、滑动、滚动）。

    **计时属性：**

    | 属性名                      | 类型         | 描述             |
    | ------------------------ | ---------- | -------------- |
    | `action.loading_time`    | number(ns) | 操作的加载时间。       |
    | `action.long_task.count` | number     | 此操作收集的所有长任务数量。 |
    | `action.resource.count`  | number     | 此操作收集的所有资源数量   |
    | `action.error.count`     | number     | 此操作收集的所有错误数量   |

    **基本属性：**

    | 属性名                  | 类型     | 描述                                                   |
    | -------------------- | ------ | ---------------------------------------------------- |
    | `action.id`          | string | 用户操作的 UUID                                           |
    | `action.type`        | string | 用户操作类型（如 `tap`、`scroll`、`swipe`、`application_start`） |
    | `action.name`        | string | 用户操作的名称                                              |
    | `action.target.name` | string | 用户交互的元素，仅适用于自动收集的操作                                  |
  </Accordion>
</AccordionGroup>

## 数据存储与安全

### 本地存储机制

在数据上传到 Flashduty 之前，会以明文形式存储在应用的缓存目录中。

**存储位置：**

```
/data/data/<package_name>/cache/com.flashcat.rum/
```

<Check>
  **安全保护：**

  * 缓存文件夹受 Android 应用沙箱保护
  * 在大多数设备上，其他应用无法读取这些数据
</Check>

<Warning>
  **安全注意事项：**

  * 如果移动设备已 root 或有人篡改 Linux 内核，存储的数据可能会变得可读
  * 敏感数据不应包含在 RUM 事件中，或者应在发送前通过 `EventMapper` 进行混淆或过滤
</Warning>

## 数据上传机制

Android RUM SDK 采用批处理方式上传事件，在保证数据传输的同时最小化对用户体验的影响。

### 批处理流程

<Steps>
  <Step title="事件收集">
    SDK 将未压缩的事件追加到批次文件中，使用 TLV 编码格式（Tag-Length-Value）。
  </Step>

  <Step title="批次优化">
    当批次关闭时：

    * 读取批次文件并提取事件
    * 对 RUM 事件进行去重优化（删除冗余的 View 事件）
    * 构建特定于每个追踪的有效载荷
  </Step>

  <Step title="压缩上传">
    使用 gzip 压缩数据，减少网络流量和上传时间。
  </Step>
</Steps>

### 上传触发条件

批次在以下任一情况下会被上传：

| 触发条件     | 说明                 |
| -------- | ------------------ |
| **文件大小** | 批次文件大小达到阈值（例如 4MB） |
| **事件数量** | 批次中的事件数量达到阈值       |
| **应用状态** | 应用切换到后台            |
| **定时上传** | 定期上传（例如每 5 秒）      |

### 上传策略

<Check>
  **智能上传机制：**

  * **网络优化** - 优先通过 WiFi 上传，移动网络也支持
  * **电量管理** - 确保不会过度消耗设备电量
  * **失败重试** - 上传失败时批次会保留在本地，直到成功发送
  * **数据压缩** - 使用 gzip 压缩，减少网络流量
</Check>

## Direct Boot 模式支持

如果您的应用支持 Direct Boot 模式（在设备解锁前启动），请注意：

<Warning>
  在设备解锁前捕获的数据将**不会被记录**，因为此时凭据加密存储尚不可用。
</Warning>

<Note>
  Flashduty SDK 会在设备解锁后开始收集数据。如果您需要在 Direct Boot 模式下收集数据，请确保使用设备加密存储而非凭据加密存储。
</Note>

## 相关文档

<CardGroup cols={3}>
  <Card title="SDK 接入" icon="plug" href="/zh/rum/sdk/android/sdk-integration">
    了解如何集成 Android SDK
  </Card>

  <Card title="高级配置" icon="sliders" href="/zh/rum/sdk/android/advanced-config">
    配置自定义属性、采样和事件过滤
  </Card>

  <Card title="兼容性" icon="check" href="/zh/rum/sdk/android/compatible">
    了解 SDK 兼容性要求
  </Card>
</CardGroup>
