コンテンツにスキップ

Swift のライブアクティビティ

Swift Braze SDK用にライブアクティビティを実装する方法について説明します。ライブアクティビティは、ロック画面に直接表示される永続的でインタラクティブな通知で、ユーザーはデバイスのロックを解除することなく、ダイナミックなリアルタイム更新を得ることができます。

iPhoneのロック画面に表示された配達トラッカーのライブアクティビティ。車のアイコンが付いたステータスバーがほぼ半分まで進んでいる。テキストには「2 min until pickup」と表示されている

iPhoneロック画面の配達トラッカーライブアクティビティ。車のアイコン付きステータスバーがほぼ半分まで進んでいる。テキストには「2 min until pickup」と表示されている

iPhoneのロック画面に表示された配達トラッカーのライブアクティビティ。車のアイコンが付いたステータスバーがほぼ半分まで進んでいる。テキストには「ピックアップまで2分」と表示されている

iPhoneのロック画面に表示される配達追跡のライブアクティビティ。車のアイコンが付いたステータスバーがほぼ半分まで進んでいる。テキストには「2 min until pickup」と表示されている

仕組み

iPhoneのロック画面に表示された配達トラッカーのライブアクティビティ。車のアイコンが付いたステータスバーがほぼ半分まで進んでいる。「集荷まで2分」と表示されている

ライブアクティビティは、静的な情報と、更新可能なダイナミックな情報を組み合わせて表示します。たとえば、配達状況を追跡するステータストラッカーを表示するライブアクティビティを作成できます。このライブアクティビティには、静的な情報として会社名が含まれ、配達ドライバーが目的地に近づくにつれて更新されるダイナミックな「配達までの時間」も含まれます。

開発者は Braze を使用して、ライブアクティビティのライフサイクルを管理し、Braze REST APIを呼び出してライブアクティビティを更新できます。購読しているすべてのデバイスは、できるだけ早くその更新を受信します。また、ライブアクティビティを Braze で管理しているため、他のメッセージングチャネル (プッシュ通知、アプリ内メッセージ、Content Cards) と組み合わせて使用し、利用を促進できます。

シーケンス図

図を表示
---
config:
  theme: mc
---
sequenceDiagram
  participant Server as Client Server
  participant Device as User Device
  participant App as iOS App / Braze SDK
  participant BrazeAPI as Braze API
  participant APNS as Apple Push Notification Service
  Note over Server, APNS: Launch Option 1<br/>Locally Start Activities
  App ->> App: Register a Live Activity using <br>`launchActivity(pushTokenTag:activity:)`
  App ->> App: Get push token from iOS
  App ->> BrazeAPI: Activity ID & Push token<br>automatically sent to Braze
  Note over Server, APNS: Launch Option 2<br/>Remotely Start Activities
  Device ->> App: Call `registerPushToStart`<br>to collect push tokens early
  App ->> BrazeAPI: Push-to-start tokens sent to Braze
  Server ->> BrazeAPI: POST /messages/live_activity/start
  Note right of BrazeAPI: Payload includes:<br>- push_token<br>- activity_id<br>- external_id<br>- event_name<br>- content_state (optional)
  BrazeAPI ->> APNS: Live activity start request
  APNS ->> Device: APNS sends activity to device
  App ->> App: Get push token from iOS
  App ->> BrazeAPI: Activity ID & Push token<br>automatically sent to Braze
  Note over Server, APNS: Resuming activities upon app launch
  App ->> App: Call `resumeActivities(ofType:)` on each app launch
  Note over Server, APNS: Updating a Live Activity
  loop update a live activity
  Server ->> BrazeAPI: POST /messages/live_activity/update
  Note right of BrazeAPI: Payload includes changes<br>to ContentState (dynamic variables)
  BrazeAPI ->> APNS: Update sent to APNS
  APNS ->> Device: APNS sends update to device
  end
  Note over Server, APNS: Ending a Live Activity
  Server ->> BrazeAPI: POST /messages/live_activity/update
  Note right of BrazeAPI: Activity can be ended via:<br> - User manually dismisses<br>- Times out after 12 hours<br>- Setting `end_activity: true` on `/messages/live_activity/update`
  APNS ->> Device: Live activity is dismissed

ライブアクティビティの実装

前提条件

この機能を使用する前に、Swift Braze SDKの統合を完了する必要があります。 また、次の作業も完了する必要があります。

  • プロジェクトが iOS 16.1 以降をターゲットにしていることを確認します。
  • Xcode プロジェクトの Signing & Capabilities で Push Notification エンタイトルメントを追加します。
  • 通知の送信に .p8 キーを使用していることを確認します。.p12 や .pem などの古いファイルはサポートされていません。
  • Braze Swift SDKのバージョン 8.2.0 以降では、ライブアクティビティをリモートで登録できます。この機能を使用するには、iOS 17.2 以降が必要です。

ステップ 1: アクティビティを作成する

まず、Apple のドキュメントの Displaying live data with Live Activities に従って、iOS アプリケーションにライブアクティビティを設定していることを確認します。この作業の一環として、Info.plist に NSSupportsLiveActivities を含め、YES に設定してください。

ライブアクティビティの具体的な内容はビジネスケースによって異なるため、Activity オブジェクトを設定して初期化します。特に、次の項目を定義することが重要です。

  • ActivityAttributes: このプロトコルは、ライブアクティビティに表示される静的な (変化しない) コンテンツと動的な (変化する) コンテンツを定義します。
  • ActivityAttributes.ContentState: この型は、アクティビティの進行中に更新される動的なデータを定義します。

また、SwiftUI を使用して、対応デバイスのロック画面と Dynamic Island の UI 表示を作成します。

ライブアクティビティに関する Apple の前提条件と制限事項を理解しておいてください。これらの制約は Braze とは関係なく適用されます。

例

Superb Owl ショーの最新情報をユーザーに届けるライブアクティビティを作成したいとします。このショーでは、競い合う 2 つの野生動物保護団体が、保護しているフクロウに応じてポイントを獲得します。この例では SportsActivityAttributes という構造体を作成していますが、独自の ActivityAttributes 実装を使用してもかまいません。

#if canImport(ActivityKit)
  import ActivityKit
#endif

@available(iOS 16.1, *)
struct SportsActivityAttributes: ActivityAttributes {
  public struct ContentState: Codable, Hashable {
    var teamOneScore: Int
    var teamTwoScore: Int
  }

  var gameName: String
  var gameNumber: String
}

ステップ 2: アクティビティを開始する

まず、アクティビティの登録方法を選択します。

  • リモート: ユーザーライフサイクルの早い段階で、push-to-start トークンが必要になる前に registerPushToStart メソッドを使用し、その後 /messages/live_activity/start エンドポイントを使用してアクティビティを開始します。
  • ローカル: ライブアクティビティのインスタンスを作成し、launchActivity メソッドを使用して、Braze が管理するプッシュトークンを作成します。

ステップ 2.1: ウィジェット拡張機能に BrazeKit を追加する

Xcode プロジェクトでアプリ名を選択し、General を選択します。Frameworks and Libraries に BrazeKit が表示されていることを確認します。

サンプル Xcode プロジェクトの Frameworks and Libraries に表示された BrazeKit フレームワーク。

ステップ 2.2: BrazeLiveActivityAttributes プロトコルを追加する

ActivityAttributes の実装に BrazeLiveActivityAttributes プロトコルへの準拠を追加し、属性モデルに brazeActivityId プロパティを追加します。

import BrazeKit

#if canImport(ActivityKit)
  import ActivityKit
#endif

@available(iOS 16.1, *)
// 1. Add the `BrazeLiveActivityAttributes` conformance to your `ActivityAttributes` struct.
struct SportsActivityAttributes: ActivityAttributes, BrazeLiveActivityAttributes {
  public struct ContentState: Codable, Hashable {
    var teamOneScore: Int
    var teamTwoScore: Int
  }

  var gameName: String
  var gameNumber: String

  // 2. Add the `String?` property to represent the activity ID.
  var brazeActivityId: String?
}

ステップ 2.3: push-to-start に登録する

次に、ライブアクティビティの型を登録します。これにより、Braze はこの型に関連付けられたすべての push-to-start トークンとライブアクティビティのインスタンスを追跡できます。

例

次の例では、LiveActivityManager クラスがライブアクティビティのオブジェクトを処理します。その後、registerPushToStart メソッドで SportsActivityAttributes を登録します。

import BrazeKit

#if canImport(ActivityKit)
  import ActivityKit
#endif

class LiveActivityManager {

  @available(iOS 17.2, *)
  func registerActivityType() {
    // This method returns a Swift background task.
    // You may keep a reference to this task if you need to cancel it wherever appropriate, or ignore the return value if you wish.
    let pushToStartObserver: Task = Self.braze?.liveActivities.registerPushToStart(
      forType: Activity<SportsActivityAttributes>.self,
      name: SportsActivityAttributes.name
    )
  }

}

ステップ 2.4: push-to-start 通知を送信する

/messages/live_activity/start エンドポイントを使用して、リモートの push-to-start 通知を送信します。

Apple の ActivityKit フレームワークを使用してプッシュトークンを取得すると、Braze SDKがそのトークンを管理できます。Braze はバックエンドで Apple Push Notification service (APNs) にプッシュトークンを送信するため、Braze API を通じてライブアクティビティを更新できるようになります。

  1. Apple の ActivityKit API を使用して、ライブアクティビティ実装のインスタンスを作成します。
  2. pushType パラメーターを .token に設定します。
  3. 定義したライブアクティビティの ActivitiesAttributes と ContentState を渡します。
  4. launchActivity(pushTokenTag:activity:) に渡して、アクティビティを Braze インスタンスに登録します。pushTokenTag パラメーターは、ユーザーが定義するカスタム文字列です。作成するライブアクティビティごとに一意である必要があります。

ライブアクティビティを登録すると、Braze SDKがプッシュトークンを抽出し、その変更を監視します。

例

この例では、ライブアクティビティのオブジェクトのインターフェイスとして LiveActivityManager というクラスを作成します。次に、pushTokenTag を "sports-game-2024-03-15" に設定します。

import BrazeKit

#if canImport(ActivityKit)
  import ActivityKit
#endif

class LiveActivityManager {

  @available(iOS 16.2, *)
  func createActivity() {
    let activityAttributes = SportsActivityAttributes(gameName: "Superb Owl", gameNumber: "Game 1")
    let contentState = SportsActivityAttributes.ContentState(teamOneScore: "0", teamTwoScore: "0")
    let activityContent = ActivityContent(state: contentState, staleDate: nil)
    if let activity = try? Activity.request(attributes: activityAttributes,
                                            content: activityContent,
      // Setting your pushType as .token allows the Activity to generate push tokens for the server to watch.
                                            pushType: .token) {
      // Register your Live Activity with Braze using the pushTokenTag.
      // This method returns a Swift background task.
      // You may keep a reference to this task if you need to cancel it wherever appropriate, or ignore the return value if you wish.
      let liveActivityObserver: Task = AppDelegate.braze?.liveActivities.launchActivity(pushTokenTag: "sports-game-2024-03-15",
                                                                                        activity: activity)
    }
  }

}

ライブアクティビティウィジェットは、この初期コンテンツをユーザーに表示します。

iPhone のロック画面に表示された、2 チームのスコアを示すライブアクティビティ。Wild Bird Fund チームと Owl Rehab チームのスコアはどちらも 0。

ステップ 3: アクティビティのトラッキングを再開する

アプリの起動時に Braze がライブアクティビティを確実に追跡するには、次の手順を実行します。

  1. AppDelegate ファイルを開きます。
  2. ActivityKit モジュールが利用可能な場合はインポートします。
  3. アプリケーションに登録したすべての ActivityAttributes 型について、application(_:didFinishLaunchingWithOptions:) で resumeActivities(ofType:) を呼び出します。

これにより、Braze はアクティブなすべてのライブアクティビティについて、プッシュトークンの更新を追跡するタスクを再開できます。ユーザーがデバイス上でライブアクティビティを明示的に閉じた場合、そのライブアクティビティは削除されたものとみなされ、Braze はそれ以降追跡しないことに注意してください。

例

import UIKit
import BrazeKit

#if canImport(ActivityKit)
  import ActivityKit
#endif

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

  static var braze: Braze? = nil

  func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {

    if #available(iOS 16.1, *) {
      Self.braze?.liveActivities.resumeActivities(
        ofType: Activity<SportsActivityAttributes>.self
      )
    }

    return true
  }
}

ステップ 4: アクティビティを更新する

iPhone のロック画面に表示された、2 チームのスコアを示すライブアクティビティ。Wild Bird Fund は 2 ポイント、Owl Rehab は 4 ポイント。

/messages/live_activity/update エンドポイントを使用すると、Braze REST API 経由で渡されるプッシュ通知を通じてライブアクティビティを更新できます。このエンドポイントを使用して、ライブアクティビティの ContentState を更新します。

ContentState を更新すると、ライブアクティビティウィジェットに新しい情報が表示されます。前半終了時の Superb Owl ショーは次のように表示されます。

詳細については、/messages/live_activity/update エンドポイントの記事を参照してください。

ステップ 5: アクティビティを終了する

ライブアクティビティがアクティブな間は、ユーザーのロック画面と Dynamic Island の両方に表示されます。Braze を通じて終了するには、end_activity を true に設定して /messages/live_activity/update エンドポイントを使用します。

ライブアクティビティを終了する際の信頼性を高めるには、次のオプションの手順を実行します。

  1. 必要に応じて、同じ update リクエストに dismissal_date を含め、iOS がライブアクティビティの UI を削除するタイミングを指定します。
  2. メッセージアクティビティログで配信結果を確認します。

自動的な非表示を設定する

自動的な非表示を設定するには、ライブアクティビティの開始後に、更新エンドポイントへのフォローアップリクエストをスケジュールします。

  1. 追跡可能な activity_id を指定して /messages/live_activity/start リクエストを送信します。
  2. その activity_id と目標終了時刻をバックエンドのスケジューラーに保存します。
  3. 目標終了時刻に、end_activity を true に設定して /messages/live_activity/update リクエストを送信します。
  4. 同じ更新リクエストで非表示日時を設定します。詳細については、/messages/live_activity/update エンドポイントを参照してください。

非表示のタイミングは iOS によって制御されることに注意してください。有効な終了リクエストを送信した後でも、OS レベルの状況によっては、ロック画面や Dynamic Island からの削除が遅れたり、異なる動作をしたりする場合があります。

ライブアクティビティは、Braze 以外の要因で終了することもあります。

  • ユーザーによる非表示: ユーザーはライブアクティビティを手動で閉じることができます。
  • タイムアウト: デフォルトでは 8 時間経過すると、iOS はユーザーの Dynamic Island からライブアクティビティを削除します。デフォルトでは 12 時間経過すると、iOS はユーザーのロック画面からライブアクティビティを削除します。

詳細については、/messages/live_activity/update エンドポイントの記事を参照してください。

ライブアクティビティのトラッキング

ライブアクティビティのイベントは、Currents、Snowflake Data Sharing、クエリビルダーで利用できます。以下のイベントを使用すると、ライブアクティビティのライフサイクルを把握・監視し、トークンの利用可能性を追跡できます。また、問題を独自に診断したり、配信ステータスを確認したりすることもできます。

  • Live Activity Push To Start Token Change:Braze で push-to-start (PTS) トークンが追加または更新されたタイミングを記録します。これにより、ユーザーごとのトークン登録と利用可能性を追跡できます。
  • Live Activity Update Token Change:Live Activity Update (LAU) トークンの追加、更新、削除を追跡します。
  • Live Activity Send:Braze によってライブアクティビティが開始、更新、または終了されるたびに記録します。
  • Live Activity Outcome:Braze から送信されたすべてのライブアクティビティについて、Apple Push Notification service (APNs) への最終的な配信ステータスを示します。

Live Activity の送信を確認する

ワークスペースが iOS Live Activities を送信しているかどうかを確認する必要がある場合は、次の方法を使用できます。

メッセージアクティビティログ

設定 > メッセージアクティビティログに移動し、Live Activity のエラーでフィルタリングすると、想定される期間内の Live Activity 関連の配信結果を確認できます。詳細については、メッセージアクティビティログを参照してください。

クエリビルダー、Currents、または Snowflake データ共有

次の Live Activity イベントを確認して、Live Activity のライフサイクルと配信を検証します。

  • Live Activity Send: Braze によって Live Activity が開始、更新、または終了されるたびに記録されます
  • Live Activity Outcome: 送信された各 Live Activity の APNs への最終配信ステータスです

必要に応じて、トークンの利用可否を示すシグナルも確認できます。

  • Live Activity Push To Start Token Change
  • Live Activity Update Token Change

API 使用状況ダッシュボード

設定 > API と識別子 > ダッシュボードに移動し、フィルターを選択して、エンドポイントでフィルタリングすると、API レスポンスを確認できます。たとえば、/messages/live_activity/update (または /messages/live_activity/start) を選択し、過去 30 日間のリクエスト量を表示します。API レスポンスがあれば、API が呼び出されており、このワークスペースで iOS Live Activity 通知が使用されていることを示します。詳細については、API 使用状況ダッシュボードを参照してください。

ライブアクティビティイベントの監視(オプション)

Braze SDKは、braze.liveActivitiesに2つのサブスクリプションメソッドを提供し、ライブアクティビティの完全なライフサイクルを監視できます。詳細なステップバイステップのウォークスルーについては、ライブアクティビティチュートリアルを参照してください。

  • subscribeToStateUpdates(_:): push-to-startトークン登録と実行中のアクティビティインスタンスの両方のライフサイクルイベントを配信します。
  • subscribeToErrors(_:): ライブアクティビティのトラッキング中に発生したSDKおよびサーバー側のエラーを配信します。

サブスクリプションの設定

application(_:didFinishLaunchingWithOptions:)でサブスクリプションを一度設定し、アプリのライフタイム全体にわたって保持します。

class AppDelegate: UIResponder, UIApplicationDelegate {
  static var braze: Braze?

  var stateSubscription: Braze.Cancellable?
  var errorSubscription: Braze.Cancellable?

  func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    let braze = Braze(configuration: config)
    Self.braze = braze

    if #available(iOS 16.1, *) {
      stateSubscription = Self.braze?.liveActivities.subscribeToStateUpdates { event in
        self.handleStateUpdate(event)
      }
      errorSubscription = Self.braze?.liveActivities.subscribeToErrors { error in
        self.handleLiveActivityError(error)
      }
    }

    return true
  }
}

subscribeToStateUpdates

subscribeToStateUpdates(_:)は、ライブアクティビティの完全なライフサイクルをカバーするUpdateEvent値を配信します。イベントは2つのスコープに分かれています。

  • .activityType(ActivityType): push-to-startトークン登録のためのタイプレベルイベント(iOS 17.2以降)。アクティビティインスタンスはまだ存在しません。
  • .activityInstance(ActivityInstance): 特定の実行中のアクティビティのインスタンスレベルイベント。

複数のサブスクライバーがサポートされており、各アクティブなサブスクリプションはすべてのイベントを独立して受信します。

タイプスコープのイベント

イベント 発火タイミング
.pushToStartTokenRead(activityType:) push-to-startトークンがOSから読み取られました。Brazeはこのタイプの新しいアクティビティをリモートで開始できるようになりました。
.pushToStartTokenFlushed(activityType:) トークンがBrazeサーバーに送信されました。Brazeはこのタイプのpush-to-start通知を送信できます。
.pushToStartOptedOut(activityType:) ユーザーがoptOutPushToStart(type:)を通じてこのアクティビティタイプのpush-to-startをオプトアウトしました。
.pushToStartOptOutFlushed(activityType:) オプトアウトがBrazeサーバーに送信されました。

インスタンススコープのイベント

イベント 発火タイミング
.started(activityId:activityType:pushTokenTag:launchSource:) SDKがlaunchActivity(pushTokenTag:activity:)を通じてこのアクティビティのトラッキングを開始しました。launchSourceの値は、アプリが開始したアクティビティの場合は.local、リモートで開始されたアクティビティの場合は.pushToStartです。
.resumed(activityId:activityType:pushTokenTag:) SDKがresumeActivities(ofType:)を通じてこのアクティビティのトラッキングを再開しました。
.pushTokenFlushed(activityId:activityType:pushTokenTag:) アクティビティのプッシュトークンがBrazeサーバーに受け入れられました。
.active(activityId:activityType:) アクティビティは現在アクティブで、ユーザーに表示されています。
.stale(activityId:activityType:staleDate:) アクティビティのコンテンツが古くなりました。iOS 16.2以降でのみ発行されます。
.dismissed(activityId:activityType:) ユーザーがアクティビティを手動で削除しました。
.ended(activityId:activityType:) アクティビティが終了しました。
.contentUpdated(activityId:activityType:) アクティビティのコンテンツ状態が更新されました(iOS 16.2以降)。カスタムロジックを使用して、Activity.activitiesからIDでActivity<T>を検索し、activity.content.stateを通じて型付き状態にアクセスします。
.pushTokenUpdated(activityId:activityType:) ActivityKitがアクティビティのプッシュトークンをローテーションしました。
例
func handleStateUpdate(_ event: Braze.LiveActivities.UpdateEvent) {
  switch event {

  // Type-scoped: push-to-start token lifecycle (iOS 17.2+)
  case .activityType(.pushToStartTokenRead(let activityType)):
    print("[\(activityType)] Push-to-start token read by SDK")

  // ...

  // Instance-scoped: SDK tracking
  case .activityInstance(.started(let id, let type, let tag, let source)):
    print("[\(type)] Activity \(id) started via \(source), tag: \(tag)")

  // ...

  // Instance-scoped: ActivityKit lifecycle
  case .activityInstance(.active(let id, let type)):
    print("[\(type)] Activity \(id) is active")

  // ...

  case .activityInstance(.ended(let id, let type)):
    print("[\(type)] Activity \(id) ended")

  // Instance-scoped: content updates (iOS 16.2+)
  case .activityInstance(.contentUpdated(let id, let type)):
    // For more advanced use cases of `contentUpdated`, see the section below
    print("[\(type)] Content updated for activity \(id)")

  case .activityInstance(.pushTokenUpdated(let id, let type)):
    print("[\(type)] Activity \(id) push token rotated")
  }
}

subscribeToErrors

subscribeToErrors(_:)は、UpdateEventと同じ2つのスコープを使用してErrorEvent値を配信します。

  • .activityType(ActivityType): push-to-start登録失敗のタイプレベルエラー。
  • .activityInstance(ActivityInstance): 実行中のアクティビティのインスタンスレベルエラー。

リトライが適切かどうかを判断するには、isTransientフラグを使用します。SDKは一時的な失敗を自動的にリトライします。

タイプスコープのエラー

エラー 発火タイミング
.pushToStartRegistrationFailed(activityType:isTransient:reason:) push-to-startトークンがBrazeサーバーに到達できませんでした。

インスタンススコープのエラー

エラー 発火タイミング
.registrationFailed(activityId:activityType:pushTokenTag:isTransient:reason:) アクティビティのプッシュトークンがBrazeへの登録に失敗しました。
.activityNotFound(activityId:activityType:) resumeActivities(ofType:)が、もう実行されていないアクティビティの保存済みマッピングを検出しました。アプリが強制終了されている間にアクティビティが終了した可能性があります。
.invalidPushTokenTag(activityId:activityType:tag:) launchActivity(pushTokenTag:activity:)が無効なタグで呼び出されました。タグは空でなく、256バイト未満である必要があります。
例
func handleLiveActivityError(_ error: Braze.LiveActivities.ErrorEvent) {
  switch error {

  // Type-scoped errors
  case .activityType(.pushToStartRegistrationFailed(let type, let isTransient, let reason)):
    if isTransient {
      print("[\(type)] Push-to-start registration failed (transient, will retry): \(reason)")
    } else {
      print("[\(type)] Push-to-start registration failed (permanent): \(reason)")
    }

  // Instance-scoped errors
  case .activityInstance(.registrationFailed(let id, let type, _, let isTransient, let reason)):
    if isTransient {
      print("[\(type)] Activity \(id) registration failed (transient, retrying): \(reason)")
    } else {
      print("[\(type)] Activity \(id) registration failed (permanent): \(reason)")
    }

  case .activityInstance(.activityNotFound(let id, let type)):
    print("[\(type)] Stored activity \(id) not found on resume")

  case .activityInstance(.invalidPushTokenTag(let id, let type, let tag)):
    print("[\(type)] Activity \(id) has invalid push token tag '\(tag)'")
  }
}

コンテンツ状態の更新を処理する(オプション)

実際のライブアクティビティインスタンスのコンテンツ状態を使用する場合は、このセクションに従ってください。

.contentUpdatedイベントが発火したら、カスタムロジックを使用してActivity.activitiesからIDで実行中のActivity<T>を検索し、activity.content.stateを通じて型付きContentStateにアクセスします。

単一の属性タイプ

case .activityInstance(.contentUpdated(let id, let type)):
  #if canImport(ActivityKit)
    // Add custom logic look up the Activity<T> by ID and access your app's typed ContentState.
    // In this example, `SportsActivityAttributes` is the app's custom type.
    if #available(iOS 16.2, *),
      let activity = findActivityInstance(id: id, as: SportsActivityAttributes.self)
    {
      // `activityContent` is now strongly typed as a `SportsActivityAttributes`
      let activityContent = activity.content.state
      print("[\(type)] Game \(id) — score: \(activityContent.teamOneScore)–\(activityContent.teamTwoScore)")
      return
    }
  #endif
  print("[\(type)] Content updated for activity \(id)")

// ...

// - MARK: Helper methods

@available(iOS 16.2, *)
func findActivityInstance<Attributes: ActivityAttributes>(
  id: String,
  as type: Attributes.Type
) -> Activity<Attributes>? {
  // Use Apple's API to find the matching Live Activity instance:
  // - https://developer.apple.com/documentation/activitykit/activity/activities
  Activity<Attributes>.activities.first(where: { $0.id == id })
}

複数の属性タイプ

アプリが複数のActivityAttributesタイプを使用している場合は、type文字列を確認して適切なActivity<T>を検索します。

case .activityInstance(.contentUpdated(let id, let type)):
  #if canImport(ActivityKit)
    if #available(iOS 16.2, *) {
      if type == SportsActivityAttributes.name,
        let activity = findActivityInstance(id: id, as: SportsActivityAttributes.self)
      {
        let activityContent = activity.content.state
        print("[\(type)] Game \(id) — score: \(activityContent.teamOneScore)–\(activityContent.teamTwoScore)")
        return

      } else if type == OrderActivityAttributes.name,
        let activity = findActivityInstance(id: id, as: OrderActivityAttributes.self)
      {
        let activityContent = activity.content.state
        print("[\(type)] Order \(id) — status: \(activityContent.status), ETA: \(activityContent.eta)")
        return
      }
    }
  #endif
  print("[\(type)] Content updated for activity \(id)")

// ...

// - MARK: Helper methods

@available(iOS 16.2, *)
func findActivityInstance<Attributes: ActivityAttributes>(
  id: String,
  as type: Attributes.Type
) -> Activity<Attributes>? {
  // Use Apple's API to find the matching Live Activity instance:
  // - https://developer.apple.com/documentation/activitykit/activity/activities
  Activity<Attributes>.activities.first(where: { $0.id == id })
}

よくある質問(FAQ)

機能とサポート

ライブアクティビティをサポートしているプラットフォームは?

現在、ライブアクティビティはiOSとiPadOSに固有の機能です。デフォルトでは、iPhoneやiPadで起動したアクティビティは、ペアリングされたwatchOS 11以降またはmacOS 26以降のデバイスにも表示されます。

Brazeは現在、Androidでのネイティブなライブアクティビティサポートを提供していません。Androidでは、Brazeプッシュ通知とカスタム通知レンダリングを使用してライブ更新エクスペリエンスを構築できます。

macOSのメニューバーにライブアクティビティがアラートとして表示されているスクリーンショット

ライブアクティビティの記事では、Braze Swift SDKを使用してライブアクティビティを管理するための前提条件について説明しています。

React Nativeアプリはライブアクティビティをサポートしていますか?

はい、React Native SDK 3.0.0以降は、Braze Swift SDKを介してライブアクティビティをサポートしています。つまり、Braze Swift SDKの上に直接React Native iOSのコードを記述する必要があります。

Appleが提供するライブアクティビティ機能は、JavaScriptでは変換できない言語機能(Swift Concurrency、generics、SwiftUIなど)を使用しているため、ライブアクティビティ用のReact Native固有のJavaScriptコンビニエンスAPIは存在しません。

Brazeはキャンペーンやキャンバスステップとしてのライブアクティビティをサポートしていますか?

いいえ、現在サポートされていません。

プッシュ通知とライブアクティビティ

ライブアクティビティがアクティブな状態でプッシュ通知が送信された場合はどうなりますか?

ブルズ対ベアーズのスポーツ中継のライブアクティビティが画面中央に、プッシュ通知のlorem ipsumテキストが画面下部に表示された携帯電話の画面

ライブアクティビティとプッシュ通知は異なる画面領域を占有するため、ユーザーの画面上で競合することはありません。

ライブアクティビティがプッシュメッセージ機能を活用する場合、ライブアクティビティを受信するためにプッシュ通知を有効にする必要がありますか?

ライブアクティビティは更新にプッシュ通知を利用しますが、異なるユーザー設定によって制御されています。ユーザーはライブアクティビティにオプトインしつつプッシュ通知はオプトアウトでき、その逆も可能です。

ライブアクティビティ更新トークンは8時間後に期限切れになります。

ライブアクティビティにはプッシュプライマーが必要ですか?

プッシュプライマーは、ユーザーにアプリからのプッシュ通知をオプトインするよう促すベストプラクティスです。しかし、ライブアクティビティにオプトインするためのシステムプロンプトはありません。デフォルトでは、ユーザーがiOS 16.1以降でアプリをインストールすると、そのアプリのライブアクティビティにオプトインされます。この権限は、アプリごとにデバイス設定で無効化または再有効化できます。

技術的なトピックとトラブルシューティング

ライブアクティビティにエラーがあるかどうかを確認するには?

ライブアクティビティのエラーは、Brazeダッシュボードのメッセージアクティビティログに記録されます。ここで「LiveActivity Errors」でフィルタリングできます。

push-to-start通知を送信した後、ライブアクティビティを受信できないのはなぜですか?

まず、messages/live_activity/startエンドポイントで説明されているすべての必須フィールドがペイロードに含まれていることを確認します。activity_attributesおよびcontent_stateフィールドは、プロジェクトのコードで定義されているプロパティと一致する必要があります。ペイロードが正しいことが確かな場合は、APNsによってレート制限されている可能性があります。この制限はBrazeではなくAppleによって課されています。

push-to-start通知がデバイスに正常に届いたがレート制限のために表示されなかったことを確認するには、Macのコンソールアプリを使用してプロジェクトをデバッグします。目的のデバイスの記録プロセスをアタッチし、検索バーでprocess:liveactivitiesdを使用してログをフィルタリングします。

push-to-startでライブアクティビティを開始した後、新しい更新を受信しないのはなぜですか?

ステップ2.2: BrazeLiveActivityAttributesプロトコルの追加で説明されている手順が正しく実装されていることを確認してください。ActivityAttributesには、BrazeLiveActivityAttributesプロトコルへの準拠とbrazeActivityIdプロパティの両方が含まれている必要があります。

ライブアクティビティのpush-to-start通知を受信したら、Braze URLの/push_token_tagエンドポイントへの送信ネットワークリクエストが表示され、"tag"フィールドの下に正しいアクティビティIDが含まれていることを再確認してください。

最後に、更新ペイロード内のライブアクティビティ属性タイプが、SDKメソッド呼び出しのregisterPushToStartで使用した文字列とクラスに完全に一致していることを確認してください。定数を使用してタイプミスを防いでください。

live_activity/updateエンドポイントを使用しようとすると、アクセス拒否の応答が返されます。なぜですか?

使用するAPIキーには、さまざまなBraze APIエンドポイントにアクセスするための適切な権限を付与する必要があります。以前に作成したAPIキーを使用している場合、権限の更新を忘れている可能性があります。APIキーセキュリティの概要を確認してください。

messages/sendエンドポイントはmessages/live_activity/updateエンドポイントとレート制限を共有していますか?

デフォルトでは、messages/live_activity/updateエンドポイントのレート制限は、ワークスペースごとに、複数のエンドポイントにわたって、1時間あたり250,000リクエストです。詳細については、APIレート制限を参照してください。

New Stuff!