> ## 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.

# 跨平台实时活动SDK设置

> 学习如何在OneSignal的包装器SDK中实现实时活动，如React Native、Flutter、Unity、Cordova等，支持推送启动和默认实时活动类型。

实时活动是iOS相对较新的功能，需要原生实现，在使用React Native、Flutter、Unity、Cordova等跨平台框架时可能会遇到挑战。为了简化这个过程，OneSignal的SDK包含了最小化原生代码要求的功能，支持在支持的平台上简化实时活动集成。

## 要求

* 我们SDK的最新版本。
* iOS 16.1+ 和 iPadOS 17+
* 使用[.p8 APNs密钥](./ios-p8-token-based-connection-to-apns)。苹果不支持实时活动的p12证书。
* Xcode 14或更高版本

## 设置

### 1. 设置我们的SDK

确保您已在应用上设置了最新版本的移动SDK。实时活动不适用于网站或我们的Web SDK。

<Columns cols={2}>
  <Card href="./unity-sdk-setup">
    <div style={{ display: 'flex', alignItems: 'flex-start', gap: '1rem' }}>
      <div style={{ flexShrink: 0, width: '40px', height: '40px', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
        <img src="https://mintcdn.com/onesignal/4HyuQPBpu-4xjmQC/images/docs/cms/Docs/docs-unity.png?fit=max&auto=format&n=4HyuQPBpu-4xjmQC&q=85&s=4f65e7750194bcbdc08b8f1549d27eb5" style={{ maxWidth: '100%', maxHeight: '100%', objectFit: 'contain' }} width="96" height="96" data-path="images/docs/cms/Docs/docs-unity.png" />
      </div>

      <div>
        <div style={{ fontWeight: '600', fontSize: '1.1rem', marginBottom: '0.25rem' }}>
          Unity
        </div>

        <div>
          基于Unity的移动应用跨平台SDK指南。
        </div>
      </div>
    </div>
  </Card>

  <Card href="./react-native-sdk-setup">
    <div style={{ display: 'flex', alignItems: 'flex-start', gap: '1rem' }}>
      <div style={{ flexShrink: 0, width: '40px', height: '40px', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
        <img src="https://mintcdn.com/onesignal/4HyuQPBpu-4xjmQC/images/docs/cms/Docs/docs-react.png?fit=max&auto=format&n=4HyuQPBpu-4xjmQC&q=85&s=dddbb392fdea1f20e0d9e20e6d90098a" style={{ maxWidth: '100%', maxHeight: '100%', objectFit: 'contain' }} width="96" height="96" data-path="images/docs/cms/Docs/docs-react.png" />
      </div>

      <div>
        <div style={{ fontWeight: '600', fontSize: '1.1rem', marginBottom: '0.25rem' }}>
          React Native 和 Expo
        </div>

        <div>
          React Native和Expo环境的设置说明。
        </div>
      </div>
    </div>
  </Card>

  <Card href="./flutter-sdk-setup">
    <div style={{ display: 'flex', alignItems: 'flex-start', gap: '1rem' }}>
      <div style={{ flexShrink: 0, width: '40px', height: '40px', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
        <img src="https://mintcdn.com/onesignal/4HyuQPBpu-4xjmQC/images/docs/cms/Docs/docs-flutter.png?fit=max&auto=format&n=4HyuQPBpu-4xjmQC&q=85&s=09904d15d1b7bd1c5f902a6101c13a22" style={{ maxWidth: '100%', maxHeight: '100%', objectFit: 'contain' }} width="96" height="96" data-path="images/docs/cms/Docs/docs-flutter.png" />
      </div>

      <div>
        <div style={{ fontWeight: '600', fontSize: '1.1rem', marginBottom: '0.25rem' }}>
          Flutter
        </div>

        <div>
          使用Dart的Flutter应用SDK指南。
        </div>
      </div>
    </div>
  </Card>

  <Card href="./cordova-sdk-setup">
    <div style={{ display: 'flex', alignItems: 'flex-start', gap: '1rem' }}>
      <div style={{ flexShrink: 0, width: '40px', height: '40px', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
        <img src="https://mintcdn.com/onesignal/4HyuQPBpu-4xjmQC/images/docs/cms/Docs/docs-ionic.png?fit=max&auto=format&n=4HyuQPBpu-4xjmQC&q=85&s=b9e33554d01ff7413f11f9bbf1f4a1b2" style={{ maxWidth: '100%', maxHeight: '100%', objectFit: 'contain' }} width="96" height="96" data-path="images/docs/cms/Docs/docs-ionic.png" />
      </div>

      <div>
        <div style={{ fontWeight: '600', fontSize: '1.1rem', marginBottom: '0.25rem' }}>
          Ionic 和 Ionic Capacitor
        </div>

        <div>
          Ionic和Capacitor混合移动应用的设置。
        </div>
      </div>
    </div>
  </Card>

  <Card href="./net-sdk-setup">
    <div style={{ display: 'flex', alignItems: 'flex-start', gap: '1rem' }}>
      <div style={{ flexShrink: 0, width: '40px', height: '40px', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
        <img src="https://mintcdn.com/onesignal/F6GiolM7XhfdYah_/images/docs/cms/Docs/docs-logo-dotnet.svg?fit=max&auto=format&n=F6GiolM7XhfdYah_&q=85&s=89024e079243d091d9bd6fda0493242d" style={{ maxWidth: '100%', maxHeight: '100%', objectFit: 'contain' }} width="48" height="48" data-path="images/docs/cms/Docs/docs-logo-dotnet.svg" />
      </div>

      <div>
        <div style={{ fontWeight: '600', fontSize: '1.1rem', marginBottom: '0.25rem' }}>
          .NET MAUI
        </div>

        <div>
          与.NET MAUI应用集成的指南。
        </div>
      </div>
    </div>
  </Card>

  <Card href="./huawei-sdk-setup">
    <div style={{ display: 'flex', alignItems: 'flex-start', gap: '1rem' }}>
      <div style={{ flexShrink: 0, width: '40px', height: '40px', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
        <img src="https://mintcdn.com/onesignal/4HyuQPBpu-4xjmQC/images/docs/cms/Docs/docs-huawei.png?fit=max&auto=format&n=4HyuQPBpu-4xjmQC&q=85&s=d15371678eda8514d135b2d4cc51a56a" style={{ maxWidth: '100%', maxHeight: '100%', objectFit: 'contain' }} width="96" height="96" data-path="images/docs/cms/Docs/docs-huawei.png" />
      </div>

      <div>
        <div style={{ fontWeight: '600', fontSize: '1.1rem', marginBottom: '0.25rem' }}>
          华为Android原生
        </div>

        <div>
          使用HMS推送服务的华为设备SDK设置。
        </div>
      </div>
    </div>
  </Card>
</Columns>

### 2. 添加新的`setupDefault`方法

为了告诉OneSignal SDK管理`DefaultLiveActivityAttributes`类型的实时活动生命周期，您可以调用`setupDefault`方法。此方法允许您使用[启动实时活动](/reference/start-live-activity)和[更新实时活动](/reference/update-live-activity-api) API来启动/更新/结束默认实时活动。

<CodeGroup>
  ```javascript React Native/Expo theme={null}
  import { OneSignal } from 'react-native-onesignal'

  //推送启动
  OneSignal.LiveActivities.setupDefault()

  //从应用内启动实时活动（推送启动不需要）
  const activityId = "my_activity_id"
  const attributes = { title: "示例标题" } ;
  const content = { message: { en: "消息" } };
  OneSignal.LiveActivities.startDefault(activityId, attributes, content);

  ```

  ```csharp Unity theme={null}
  using OneSignalSDK;

  //推送启动
  OneSignal.LiveActivities.SetupDefault();

  //从应用内启动实时活动（推送启动不需要）
  string activityId = "my_activity_id";

  OneSignal.LiveActivities.StartDefault(
    activityId,
    new Dictionary<string, object>() {
        { "title", "欢迎！" }
    },
    new Dictionary<string, object>() {
        { "message", new Dictionary<string, object>() {
            { "en", "你好世界！"}
        }},
    });
  ```

  ```javascript Cordova/Ionic theme={null}
  /*Cordova*/

  //推送启动
  window.plugins.OneSignal.LiveActivities.setupDefault();

  //从应用内启动实时活动（推送启动不需要）
  const activityId = "my_activity_id";
  const attributes = { title: "示例标题" };
  const content = { message: { en: "消息" } };
  window.plugins.OneSignal.LiveActivities.startDefault(
    activityId,
    attributes,
    content
  );

  /*Ionic/Capacitor*/
  import OneSignal from "onesignal-cordova-plugin";

  //推送启动
  OneSignal.LiveActivities.setupDefault();

  //从应用内启动实时活动（推送启动不需要）
  const activityId = "my_activity_id";
  const attributes = { title: "示例标题" };
  const content = { message: { en: "消息" } };
  OneSignal.LiveActivities.startDefault(activityId, attributes, content);
  ```

  ```csharp .NET theme={null}
  using OneSignalSDK;

  //推送启动
  OneSignal.LiveActivities.SetupDefault();

  //从应用内启动实时活动（推送启动不需要）
  string activityId = "my_activity_id";

  OneSignal.LiveActivities.StartDefault(
    activityId,
    new Dictionary<string, object>() {
        { "title", "欢迎！" }
    },
    new Dictionary<string, object>() {
        { "message", new Dictionary<string, object>() {
            { "en", "你好世界！"}
        }},
    });
  ```

  ```javascript Flutter theme={null}
  import 'package:onesignal_flutter/onesignal_flutter.dart';

  OneSignal.LiveActivities.setupDefault()

  //从应用内启动实时活动（推送启动不需要）
  const String activityId = "my_activity_id";
  OneSignal.LiveActivities.startDefault(activityId!, {
    "title": "欢迎！"
    }, {
    "message": {"en": "你好世界！"},
  });
  ```
</CodeGroup>

### 3. 创建活动小组件

<Steps>
  <Step title="更新您的Info.plist">
    在Xcode中，打开主目标的`Info.plist`，添加键`Supports Live Activities`作为**Boolean**，并将其设置为`YES`。

    <Frame caption="在Info中添加支持实时活动键并将其值设置为Boolean YES">
      <img src="https://mintcdn.com/onesignal/yt4lRKoquAlWvRvF/images/live-activities/info-la-setting.png?fit=max&auto=format&n=yt4lRKoquAlWvRvF&q=85&s=e839231401651b71d0ae8d48614ec130" width="2166" height="1488" data-path="images/live-activities/info-la-setting.png" />
    </Frame>

    <Note>
      更新实时活动时，您可以设置"优先级"，苹果使用该优先级来确定更新的紧急程度。苹果有内部阈值，会限制过于频繁使用高优先级标志的请求。

      如果您的实时活动用例需要更频繁的高优先级更新，您可以根据[苹果开发者文档](https://developer.apple.com/documentation/activitykit/starting-and-updating-live-activities-with-activitykit-push-notifications#Determine-the-update-frequency)的指导，将键`NSSupportsLiveActivitiesFrequentUpdates`作为Boolean类型设置为YES添加到Info.plist中。当实时活动超出其推送预算时，用户将看到对话框，如果他们允许实时活动继续，预算将自动增加以提供无缝的用户体验。
    </Note>
  </Step>

  <Step title="创建Widget扩展">
    在Xcode中，转到**File > New > Target... > Widget Extension**。

    <Frame caption="在Xcode中为应用添加新的Widget扩展目标。">
      <img src="https://mintcdn.com/onesignal/FXJz6yFfOqztaEND/images/live-activities/live-activity-widget-extension.png?fit=max&auto=format&n=FXJz6yFfOqztaEND&q=85&s=60a52d6484203c4d6af21bc3a7da5e62" width="2166" height="1488" data-path="images/live-activities/live-activity-widget-extension.png" />
    </Frame>

    选择并按**Next**。

    通过提供名称（示例：`OneSignalWidget`）配置Widget扩展，并确保选择**Include Live Activity**。然后点击**Finish**。

    <Frame caption="实时活动的Widget扩展选项。">
      <img src="https://mintcdn.com/onesignal/yt4lRKoquAlWvRvF/images/live-activities/OneSignalWidget.png?fit=max&auto=format&n=yt4lRKoquAlWvRvF&q=85&s=47412314963f6fbd58fd2c7d3a529322" width="2166" height="1488" data-path="images/live-activities/OneSignalWidget.png" />
    </Frame>

    如果提示激活方案，点击**Don't Activate**。

    <Frame caption="实时活动的Widget扩展选项。">
      <img src="https://mintcdn.com/onesignal/yt4lRKoquAlWvRvF/images/live-activities/la-scheme-activation.png?fit=max&auto=format&n=yt4lRKoquAlWvRvF&q=85&s=d3a2207ff2b5988c63c2abd631a72541" width="2166" height="1488" data-path="images/live-activities/la-scheme-activation.png" />
    </Frame>
  </Step>

  <Step title="将OneSignalXCFramework添加到Podfile">
    在项目的Targets列表中找到您的widget扩展目标名称。示例名称为`OneSignalWidgetExtension`。

    <Frame caption="找到您的widget扩展目标名称">
      <img src="https://mintcdn.com/onesignal/yt4lRKoquAlWvRvF/images/live-activities/cocoapods-la-extension-name.png?fit=max&auto=format&n=yt4lRKoquAlWvRvF&q=85&s=850a91387539587802306a66771435eb" width="2166" height="1488" data-path="images/live-activities/cocoapods-la-extension-name.png" />
    </Frame>

    打开您的`Podfile`并添加以下代码。将`OneSignalWidgetExtension`替换为您的widget扩展目标名称。

    ```ruby Podfile theme={null}
    target 'OneSignalWidgetExtension' do
      #use_frameworks!
      pod 'OneSignalXCFramework', '>= 5.0.0', '< 6.0'
    end
    ```

    关闭Xcode并运行`pod repo update && pod install`以安装`OneSignalLiveActivities` pod。
  </Step>
</Steps>

### 4. 设置LiveActivity.swift文件

在Xcode中，打开\_WidgetExtensionLiveActivity.swift\_文件。

在屏幕右侧打开检查器面板。在**目标成员**中，点击\*\*+\*\*按钮并选择您的Runner目标。

<Frame caption="允许主目标成员">
  <img src="https://mintcdn.com/onesignal/FXJz6yFfOqztaEND/images/live-activities/target-membership.png?fit=max&auto=format&n=FXJz6yFfOqztaEND&q=85&s=3315253623dfec6c13a56ff30a156772" width="2392" height="1488" data-path="images/live-activities/target-membership.png" />
</Frame>

使用以下默认实时活动布局更新\_WidgetExtensionLiveActivity.swift\_的内容。此Widget中的值可以更改为您希望在widget上显示的任何内容，setupDefault方法将处理为这些属性定义结构。

```swift Swift theme={null}
import ActivityKit
import WidgetKit
import SwiftUI
import OneSignalLiveActivities

// 您的结构名称在这里可能不同
@available(iOS 16.2, *)
struct OneSignalWidgetLiveActivity: Widget {
    var body: some WidgetConfiguration {
        ActivityConfiguration(for: DefaultLiveActivityAttributes.self) { context in
            // 锁屏/横幅UI
            VStack {
                Spacer()

                Text("标题: " + (context.attributes.data["title"]?.asString() ?? ""))
                    .font(.headline)

                Spacer()

                HStack {
                    Spacer()
                    Text(context.state.data["message"]?.asDict()?["en"]?.asString() ?? "默认消息")
                    Spacer()
                }

                Text("INT: " + String(context.state.data["intValue"]?.asInt() ?? 0))
                Text("DBL: " + String(context.state.data["doubleValue"]?.asDouble() ?? 0.0))
                Text("BOL: " + String(context.state.data["boolValue"]?.asBool() ?? false))

                Spacer()
            }
            .activitySystemActionForegroundColor(.black)
            .activityBackgroundTint(.white)

        } dynamicIsland: { _ in
            DynamicIsland {
                // 扩展UI
                DynamicIslandExpandedRegion(.leading) {
                    Text("前导")
                }
                DynamicIslandExpandedRegion(.trailing) {
                    Text("尾随")
                }
                DynamicIslandExpandedRegion(.bottom) {
                    Text("底部")
                    // 更多内容
                }
            } compactLeading: {
                Text("L")
            } compactTrailing: {
                Text("T")
            } minimal: {
                Text("最小")
            }
            .widgetURL(URL(string: "http://www.apple.com"))
            .keylineTint(Color.red)
        }
    }
}

```

***

## 测试实时活动

1. 启动应用

2. 查看我们[启动实时活动API参考](/reference/start-live-activity)中的所有可能字段。这些字段的结构可能因您设置UI的方式而有所不同。例如：

* `"event_updates"`：这是实时活动启动后可以更新的动态数据（代码示例中`context.state`之后的任何内容）。由于我们有context.state.data，我们会向此字段添加数据对象以及我们在代码示例中添加的消息字典等任何其他字段。使用方法请参见下面的示例请求。
* `"event_attributes"`：这是在推送启动请求中设置的静态数据，在实时活动被移除或覆盖之前保持相同的值。

3. 使用推送启动时，您在请求中设置`"activity_id"`，而不是在代码中。使用不同的活动ID将启动新的实时活动。使用相同的活动ID将覆盖当前使用该ID的widget。

4. 确保您已更改URL路径中的[OneSignal应用ID](./keys-and-ids)和Authorization头中的[Rest API密钥](./keys-and-ids#rest-api-key)。如果您使用默认设置，则无法更改`DefaultActivityAttributes`类型。另请注意，添加到路径的活动类型区分大小写，应与您定义的内容或下面示例中使用的默认活动匹配。

```curl curl theme={null}
curl --request POST \
     --url https://api.onesignal.com/apps/YOUR_APP_ID/activities/activity/DefaultLiveActivityAttributes \
     --header 'Authorization: key YOUR_REST_API_KEY' \
     --header 'Content-Type: application/json' \
     --header 'accept: application/json' \
     --data '
{
  "event": "start",
  "event_updates": {
    "data": {
      "message": {
        "en": "消息嵌套在context.state.data[\"message\"]中作为字典"
      },
      "intValue": 10,
      "doubleValue": 3.14,
      "boolValue": true
    }
  },
  "event_attributes": {
    "data": {
      "title": "这在LA启动时设置，之后不会更新"
    }
  },
  "activity_id": "my-activity-id",
  "name": "OneSignal通知名称",
  "contents": {
    "en": "英文消息"
  },
  "headings": {
    "en": "英文消息"
  },
  "sound": "beep.wav",
  "priority": 10
}'
```

***

## 低级方法

如果您想生成自己的推送启动令牌，这些是可选方法，这也已在SDK的最新版本中添加。使用这些方法需要您与Xcode进行更多交互，并使用Swift为推送启动生成自己的令牌。您可以在[这里](https://github.com/OneSignal/OneSignal-iOS-SDK/pull/1377#:~:text=Alternative%20\(low%20level\)%20method%20to%20setup%20Live%20Activities%20with%20OneSignal)找到相关指南。

<CodeGroup>
  ```javascript React Native/Expo theme={null}
  //设置推送启动令牌
  OneSignal.LiveActivities.setPushToStartToken(activityType: string, token: string)

  //移除推送启动令牌
  OneSignal.LiveActivities.removePushToStartToken(activityType: string)

  ```

  ```csharp Unity theme={null}
  //设置推送启动令牌
  OneSignal.LiveActivities.SetPushToStartToken(string activityType, string token)

  //移除推送启动令牌
  OneSignal.LiveActivities.RemovePushToStartToken(string activityType)
  ```

  ```javascript Cordova/Ionic theme={null}
  /* Cordova */
  //设置推送启动令牌
  window.plugins.OneSignal.LiveActivities.setPushToStartToken(activityType: string, token: string)

  //移除推送启动令牌
  window.plugins.OneSignal.LiveActivities.removePushToStartToken(activityType: string)

  /* Ionic */
  //设置推送启动令牌
  OneSignal.LiveActivities.setPushToStartToken(activityType: string, token: string)

  //移除推送启动令牌
  OneSignal.LiveActivities.removePushToStartToken(activityType: string)
  ```

  ```csharp .NET theme={null}
  //设置推送启动令牌
  OneSignal.LiveActivities.SetPushToStartToken(string activityType, string token)

  //移除推送启动令牌
  OneSignal.LiveActivities.RemovePushToStartToken(string activityType)
  ```

  ```javascript Flutter theme={null}
  //设置推送启动令牌
  OneSignal.LiveActivities.setPushToStartToken(String activityType, String token)

  //移除推送启动令牌
  OneSignal.LiveActivities.removePushToStartToken(String activityType)
  ```
</CodeGroup>

***
