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

# Android 实时通知

> 使用 OneSignal 实时通知在 Android 设备上创建和更新动态实时通知。在单个通知内提供持续更新的内容，为 Android 模拟 iOS 实时活动。

OneSignal 的 Android 实时通知让您能够向单个通知发送实时更新，减少杂乱并提高参与度。这些通知保持持久性并动态更新其内容——非常适合体育比分、下载进度或事件跟踪。

要接收实时通知，Android 用户必须启用推送通知。

## 要求

* 您的应用必须使用最新版本的 [OneSignal SDK](./mobile-sdk-setup)。
* Android 用户必须启用推送通知权限。

***

## 实时通知 vs. 标准推送

与每次发送新通知的常规推送通知不同，实时通知使用单个随时间更新的通知。更新通过使用相同 `collapse_id` 的 [创建消息 API](/reference/create-message) 发送。

***

## 配置

### 1. 实现通知服务扩展

创建一个实现 `INotificationServiceExtension` 的 `NotificationServiceExtension` 类。此类拦截传入的通知并可以修改或覆盖它们。

<Info>
  有关更多详细信息，请参阅 [Android 通知服务扩展](./service-extensions#android-notification-service-extension)。
</Info>

```kotlin NotificationServiceExtention.kt theme={null}
package com.onesignal.sample.android

import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.os.Build
import com.onesignal.notifications.INotificationReceivedEvent
import com.onesignal.notifications.INotificationServiceExtension
import org.json.JSONObject
import java.util.logging.Logger

class NotificationServiceExtension : INotificationServiceExtension {
  override fun onNotificationReceived(event: INotificationReceivedEvent) {
        val context = event.context
        val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as? NotificationManager
            ?: run {
                logger.warning("NotificationManager not available.")
                return
            }

        notificationManager.let {
            if (!notificationChannelsCreated) {
                createNotificationChannels(notificationManager)
            }
        }

        // Use `additional_data`to submit the Live Notification payload.
    		val additionalData = event.notification.additionalData
        val liveNotificationPayload = additionalData?.optJSONObject("live_notification")
        if (liveNotificationPayload == null) {
            logger.info("No live notification payload found. Showing original notification.")
            return
        }

        event.preventDefault()
        handleLiveNotification(event, liveNotificationPayload, notificationManager, context)
    }
}

```

### 2. 将扩展添加到 Android 清单

<CodeGroup>
  ```xml AndroidManifest.xml theme={null}
    <meta-data android:name="com.onesignal.NotificationServiceExtension"
                android:value="com.onesignal.sample.android.NotificationServiceExtension" />
  ```

  ```xml Example AndroidManifest.xml theme={null}
  <?xml version="1.0" encoding="utf-8"?>
  <manifest xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools">

      <application
          android:allowBackup="true"
          android:dataExtractionRules="@xml/data_extraction_rules"
          android:fullBackupContent="@xml/backup_rules"
          android:icon="@mipmap/ic_launcher"
          android:name=".MainApplication"
          android:label="@string/app_name"
          android:roundIcon="@mipmap/ic_launcher_round"
          android:supportsRtl="true"
          android:theme="@style/Theme.OneSignalAndroidSample"
          tools:targetApi="31">
          <meta-data android:name="com.onesignal.NotificationServiceExtension"
              android:value="com.onesignal.sample.android.NotificationServiceExtension" />
          <activity
              android:name=".MainActivity"
              android:exported="true">
              <intent-filter>
                  <action android:name="android.intent.action.MAIN" />

                  <category android:name="android.intent.category.LAUNCHER" />
              </intent-filter>
          </activity>
      </application>

  </manifest>
  ```
</CodeGroup>

### 3. 创建实时通知类型

实时通知类型指示要启动哪个实时通知。

#### 定义键

实时通知通过 `key` 引用，它决定如何路由更新。

```kotlin NotificationServiceExtention.kt theme={null}
private const val PROGRESS_LIVE_NOTIFICATION = "progress"
```

#### 创建通知渠道

渠道定义通知的行为方式（声音、振动、外观）。您必须为实时通知类型创建渠道。我们建议：

* 进度通知使用低重要性
* 禁用徽章
* 将声音和振动保持在最低限度

有关更多信息，请参阅 [Android 通知渠道类别](./android-notification-categories)。

#### 设计实时通知

设计实时通知时，您可以灵活地为每种更新类型创建通知设计。您创建的每个设计都必须分配特定类型，允许实时通知的不同呈现。

```kotlin NotificationServiceExtention.kt theme={null}
private fun updateProgressNotification(
        liveNotificationUpdates: JSONObject,
        context: Context,
        notificationManager: NotificationManager
    ) {
        val currentProgress = liveNotificationUpdates.optInt("current_progress", 0)

        val builder = NotificationCompat.Builder(context, PROGRESS_CHANNEL_ID)
            .setContentTitle("Progress Live Notifications")
            .setContentText("It's working...")
            .setSmallIcon(android.R.drawable.ic_media_play)
            .setLargeIcon(BitmapFactory.decodeResource(context.resources, android.R.drawable.ic_dialog_info))
            .setOngoing(true)
            .setOnlyAlertOnce(true)
            .setProgress(100, currentProgress, false)
            .setAutoCancel(false) // Prevent auto-dismissal of notification until you set the end event

        notificationManager.notify(keyMap[PROGRESS_LIVE_NOTIFICATION]!!, builder.build())
        logger.info("Updated progress notification with progress: $currentProgress")
    }
```

**设计考虑事项：**

* 小图标和主题色
* 大图标
* 大图片
* 操作按钮

<Info>
  有关高级设计选项，请参阅 [Android 自定义通知布局](https://developer.android.com/develop/ui/views/notifications/custom-notification)。
</Info>

### 4. 提取实时通知载荷

实时通知使用 `additional_data` 字段传递结构化内容。

```kotlin NotificationServiceExtention.kt theme={null}
val additionalData = event.notification.additionalData
val liveNotificationPayload = additionalData?.optJSONObject("live_notification")
```

#### 实时通知架构

| 属性                 | 必需 | 描述                                        |
| ------------------ | -- | ----------------------------------------- |
| `key`              | 是  | 用于加载正确的通知 UI。                             |
| `event`            | 是  | 在实时通知上执行的操作。                              |
| `event_attributes` | 否  | 静态数据用于初始化实时通知；定义通知所需数据的自定义架构。             |
| `event_updates`    | 否  | 实时通知的动态内容。必须符合应用实时通知中定义的 ContentState 接口。 |

```json Example Live Notification Payload theme={null}
  {
      "key": "celtics-vs-lakers",
      "event": "start",
      "event_attributes": {
          "homeTeam": "Celtics",
          "awayTeam": "Lakers",
          "game": "Finals Game 1"
      },
      "event_updates": {
          "quarter": 1,
          "homeScore": 0,
          "awayScore": 0,
      }
  }
```

### 5. 处理实时通知事件

每个实时通知都必须响应以下事件：

| 事件       | 描述               | 必需字段                                |
| -------- | ---------------- | ----------------------------------- |
| `start`  | 使用静态和动态数据开始实时通知。 | `event_attributes`, `event_updates` |
| `update` | 使用新动态数据更新实时通知。   | `event_updates`                     |
| `end`    | 结束并移除实时通知。       | 无                                   |

```kotlin NotificationServiceExtention.kt theme={null}
val liveNotificationEvent = liveNotificationPayload.optString("event", "")
```

***

## 启动实时通知

当您准备启动实时通知时：

* 设置 `event_attributes` 来初始化实时通知的静态数据。此数据在实时通知的生命周期内不会更改。
* 设置 `event_updates` 数据来初始化实时通知的动态数据。这是在实时通知生命周期内可以且将会更改的数据。
* 使用 [`collapse_id`](./push#collapse-id) 确保每次更新都覆盖前一次。此 ID 应该对实时通知唯一，以确保后续更新反映在同一个通知中。

```curl curl theme={null}
  curl -X "POST" "https://api.onesignal.com/notifications" \
       -H 'Authorization: key YOUR_REST_API_KEY' \
       -H 'Content-Type: application/json; charset=utf-8' \
       -d $'{
    "app_id": "YOUR_APP_ID",
    "isAndroid": true,
    "collapse_id": "THE_UNIQUE_ID_FOR_THIS_LIVE_NOTIFICATION",
    "data": {
      "live_notification": {
        "key": "progress",
        "event": "start",
        "event_attributes": {},
        "event_updates": {
          "current_progress": 0
        }
      }
    },
    "headings": {
      "en": "Start"
    },
    "contents": {
      "en": "Starting Live Notification"
    },
    "include_aliases": {
      "external_id": ["EID1", "EID2"]
    },
    "target_channel": "push"
  }'
```

***

## 更新实时通知

您可以随意多次更新实时通知，只要首先启动它。

* 设置 `event_updates` 数据来初始化实时通知的动态数据。这是在实时通知生命周期内可以且将会更改的数据，并告知要用什么更新实时通知的内容。

**示例 cURL 请求**

```curl curl theme={null}
  curl -X "POST" "https://api.onesignal.com/notifications" \
       -H 'Authorization: key YOUR_REST_API_KEY' \
       -H 'Content-Type: application/json; charset=utf-8' \
       -d $'{
    "app_id": "YOUR_APP_ID",
    "isAndroid": true,
    "collapse_id": "THE_UNIQUE_ID_FOR_THIS_LIVE_NOTIFICATION",
    "data": {
      "live_notification": {
        "key": "progress",
        "event": "update",
  			"event_attributes": {},
        "event_updates": {
          "current_progress": 80
        }
      }
    },
    "headings": {
      "en": "Update"
    },
    "contents": {
      "en": "Updating Live Notification"
    },
    "include_aliases": {
      "external_id": ["EID1", "EID2"]
    },
    "target_channel": "push"
  }'
```

## 结束实时通知

**示例 cURL 请求**

```curl curl theme={null}
  curl -X "POST" "https://api.onesignal.com/notifications" \
       -H 'Authorization: key YOUR_REST_API_KEY' \
       -H 'Content-Type: application/json; charset=utf-8' \
       -d $'{
    "app_id": "YOUR_APP_ID",
    "isAndroid": true,
    "collapse_id": "THE_UNIQUE_ID_FOR_THIS_LIVE_NOTIFICATION",
    "data": {
      "live_notification": {
        "key": "progress",
        "event": "dismiss"
      }
    },
    "headings": {
      "en": "Dismissing"
    },
    "contents": {
      "en": "Dismissing Live Notification"
    },
    "include_aliases": {
      "external_id": ["EID1", "EID2"]
    },
    "target_channel": "push"
  }'
```

***

<Check>
  您已成功创建了实时通知！

  相关文档：

  * [Android 通知服务扩展](./service-extensions#android-notification-service-extension)
  * [Android SDK 设置](./mobile-sdk-setup)
  * [创建消息 API](/reference/create-message)
</Check>

***
