メインコンテンツへスキップ
Live Activitiesを使用すると、iOSアプリがロック画面とDynamic Islandに直接リアルタイム更新を表示できます。配送追跡、スポーツスコア、または時間に敏感なトランザクション更新に最適で、アプリを開かずにユーザーに情報を提供し続けます。
AndroidにはAndroid Live通知と呼ばれる同様の機能があります。

要件


セットアップ

これらの手順では、Live Activitiesを迅速にセットアップする方法を説明します。詳細とデザインのカスタマイズについては、AppleのLive Activities開発者ドキュメントを参照してください。

1. Widget Extensionを追加する

Xcodeで、ファイル > 新規 > ターゲット… > Widget Extensionに移動します。

XcodeでアプリのWidget Extensionターゲットを新規追加します。

選択して次へを押します。 名前を入力してWidget Extensionを設定し(例:OneSignalWidget)、Include Live Activityが選択されていることを確認します。次に完了をクリックします。

Live ActivityのWidget Extensionオプション。

スキームをアクティブ化するように求められた場合は、アクティブ化しないをクリックします。

Live ActivityのWidget Extensionオプション。

2. Info.plistを更新する

メインターゲットのInfo.plistに、キーSupports Live ActivitiesBooleanとして追加し、YESに設定します。

InfoにSupports Live Activitiesキーを追加し、その値をBoolean YESに設定します

プログラムで設定する場合は、次のようになります:
info.plist
<key>NSSupportsLiveActivities</key>
<true/>
Live Activitiesを更新する場合、「優先度」を設定するオプションがあり、Appleはこれを使用して更新の緊急性を判断します。Appleには内部しきい値があり、高優先度フラグを頻繁に使用するリクエストをスロットルします。Live Activitiesのユースケースがより頻繁な高優先度更新に依存している場合、AppleのDeveloper Docsで指示されているように、Info.plistにキーNSSupportsLiveActivitiesFrequentUpdatesをBoolean型でYESとして追加できます。Live Activityがプッシュ予算を超えると、ユーザーにダイアログが表示され、Live Activityを続行することを許可すると、シームレスなユーザーエクスペリエンスのために予算が自動的に増加します。

3. SDKを追加する

  • パッケージマネージャー
  • Cocoapods
Widget Extensionターゲットで、一般 > フレームワーク、ライブラリ、および埋め込みコンテンツの下にOneSignalFrameworkを追加します:

Widget ExtensionターゲットにOneSignalFrameworkを追加します

4. ウィジェット属性とUIを定義する

your-nameLiveActivity.swiftファイル(例:OneSignalWidgetLiveActivity.swift)を開いて、構造体のプロパティを定義し、ウィジェットUIを変更します。
  • your-nameAttributesは、Live Activityの静的コンテンツを説明します。
  • ContentStateは、Live Activityの動的コンテンツを説明します。
例に従っている場合は、以下のコードをあなたの OneSignalWidgetLiveActivity.swiftファイルにコピーペーストします。
your-nameLiveActivity.swift
import ActivityKit
import WidgetKit
import SwiftUI
// OneSignalLiveActivitiesモジュールをインポート
// モジュールが見つからないというエラーが発生した場合は、ステップ3に戻り、OneSignalLiveActivities podが正しく追加されていることを確認してください。
import OneSignalLiveActivities

// OneSignalLiveActivityAttributesから継承するように更新
// これはLive Activityを開始するためのAPIリクエストで使用されます
struct OneSignalWidgetAttributes: OneSignalLiveActivityAttributes  {
    // OneSignalLiveActivityContentStateから継承するように更新
    public struct ContentState: OneSignalLiveActivityContentState {
        // アクティビティに関する動的なステートフルプロパティをここに配置します!
        var emoji: String
        // OneSignalLiveActivityContentStateData?への参照を追加
        var onesignal: OneSignalLiveActivityContentStateData?
    }
    // アクティビティに関する固定の変更されないプロパティをここに配置します!
    var name: String
    // OneSignalLiveActivityAttributeDataへの参照を追加
    var onesignal: OneSignalLiveActivityAttributeData
}

struct OneSignalWidgetLiveActivity: Widget {
    var body: some WidgetConfiguration {
      // `for: 属性構造体の名前`を使用するように更新
      // これはLive Activityを開始するためのAPIリクエストで使用されます
        ActivityConfiguration(for: OneSignalWidgetAttributes.self) { context in
            // ロック画面/バナーUIをここに配置
            // ペイロード経由で送信された属性を表示するように更新
            VStack {
                Text("Hello \(context.attributes.name) \(context.state.emoji)")
            }
            .activityBackgroundTint(Color.cyan)
            .activitySystemActionForegroundColor(Color.black)

        } dynamicIsland: { context in
            DynamicIsland {
                // 拡張UIをここに配置。leading/trailing/center/bottomなどの
                // さまざまな領域を通じて拡張UIを構成します
                DynamicIslandExpandedRegion(.leading) {
                    Text("Leading")
                }
                DynamicIslandExpandedRegion(.trailing) {
                    Text("Trailing")
                }
                DynamicIslandExpandedRegion(.bottom) {
                    Text("Bottom \(context.state.emoji)")
                    // 追加のコンテンツ
                }
            } compactLeading: {
                Text("L")
            } compactTrailing: {
                Text("T \(context.state.emoji)")
            } minimal: {
                Text(context.state.emoji)
            }
            .widgetURL(URL(string: "http://www.apple.com"))
            .keylineTint(Color.red)
        }
    }
}

5. メインターゲットメンバーシップを許可する

your-nameLiveActivity.swiftファイルのターゲットメンバーシップリストにメインアプリターゲットを追加します。 Xcodeで、画面の右側にあるInspectorパネルを開きます。ターゲットメンバーシップ内で、**+**ボタンをクリックし、ContentViewとOneSignal初期化コードを含むメインアプリターゲットを選択します。

メインターゲットメンバーシップを許可します

6. AppDelegateにセットアップメソッドを追加する

OneSignal SDK初期化の後、AppDelegateOneSignal.LiveActivities.setupを呼び出します。 OneSignalWidgetAttributesをLive Activity属性構造体の名前に置き換えます。
AppDelegate
// OneSignalLiveActivitiesモジュールをインポート
import OneSignalLiveActivities

// これはOneSignal SDKの初期化後に追加する必要があります
if #available(iOS 16.1, *) {
	OneSignal.LiveActivities.setup(OneSignalWidgetAttributes.self)
  // 複数のLive Activitiesがある場合は、setupメソッドでここに追加できます
  // OneSignal.LiveActivities.setup(LiveActivityWidgetAttributes-2.self)
}
これにより、ActivityKit非同期シーケンスを使用して更新を管理および報告します。
アプリで次のシーケンスを直接使用する場合、OneSignal Live Activityの動作に干渉する可能性があります:
  • activityStateUpdates
  • pushTokenUpdates
  • pushToStartTokenUpdates
  • activityUpdates

Live Activityを開始する

デバイスでLive Activityを開始するには2つのオプションがあります:
  • Push-to-start
  • Trigger-in-app
Push To Start APIリクエストを送信します。すべての名前とIDがウィジェットの構成と正確に一致することを確認してください(パラメーターは大文字小文字を区別します)。何かが欠落しているか、誤って追加された場合、ウィジェットの起動時に問題が発生する可能性があります。上記の例で機能するリクエストの例を次に示します。置き換え:
  • YOUR_APP_IDをOneSignal App IDに置き換えます。
  • YOUR_APP_API_KEYをOneSignal APIキーに置き換えます。
  • OneSignalWidgetAttributesをWidget Attributes構造体の名前に置き換えます。
    curl
    curl --location 'https://api.onesignal.com/apps/YOUR_APP_ID/activities/activity/OneSignalWidgetAttributes' \
    --header 'Authorization: key YOUR_APP_API_KEY' \
    --header 'Content-Type: application/json' \
    --data '{
        "event": "start",
        "activity_id": "push-to-start",
        "included_segments": [
            "Subscribed Users"
        ],
        "event_attributes": {
            "name": "World"
        },
        "event_updates": {
            "emoji":"🤩"
        },
        "name": "Live Activities Test",
        "contents": {
            "en": "A push started this Live Activity"
        },
        "headings": {
          "en": "Live Activity Started"
        }
      }'
    
提供されたサンプルコードに従っている場合、デバイスのロック画面にLive Activityが表示されます。

ロック画面のLive Activity

push-to-startでLive Activityを正常に開始しました!ユーザーは更新を受け取り続けるために「許可」を選択する必要があります。

Live Activityを更新する

Update Live Activity APIを使用してアクティブなウィジェットを更新します。 アクティビティを開始するときに使用したactivity_idと一致させます。 このサンプルリクエストは、定義したactivity_idpush-to-startというタイトルであるため、push-to-startウィジェットを更新します。 click-to-startウィジェットを更新するには、リクエストパスをpush-to-startの代わりにclick-to-startを使用するように更新します。
curl
curl --location 'https://api.onesignal.com/apps/YOUR_APP_ID/live_activities/push-to-start/notifications' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: key YOUR_API_KEY' \
--data '{
    "event": "update",
    "event_updates": {
        "emoji": "😎"
    },
    "contents": {
        "en": "A push updated this Live Activity"
    },
    "name": "Live Activity Updated"
}'

Live Activity更新

Live Activityを正常に更新しました!Live Activityの更新の詳細については、Update Live Activity APIをご覧ください。

Live Activityを終了する

同じUpdate Live Activity APIを使用して、"event": "end"を設定することでLive Activityを終了できます。
curl
curl --location 'https://api.onesignal.com/apps/YOUR_APP_ID/live_activities/my_activity_id/notifications' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: key YOUR_API_KEY' \
--data '{
    "event": "end",
    "event_updates": {
        "emoji": "👋"
    },
    "contents": {
        "en": "A push ended this Live Activity"
    },
    "name": "Live Activity Ended"
}'
Live Activityが終了する他の方法:
  • SDK のexit()メソッドを使用する。
  • ユーザーが手動でLive Activityをスワイプして削除する。
  • ユーザーがiOS設定でLive Activitiesの権限を取り消す。

Live Activity終了

Live Activityを正常に終了し、例を完了しました!

ベストプラクティスと推奨事項

デザインに関する考慮事項

  • AppleのLive Activities Human Interface Guidelinesに従ってください。
    • 重要な情報を優先して、一目で理解しやすくします。
    • Dynamic Islandに注意を引く要素をアプリに追加しないでください。
    • マージンを使用し、要素間のスペースを維持します。
    • 背景に太字の色を使用します。ライトモードとダークモードの両方をデザインします。

機能性

フォールバックメッセージの設定

  • Live Activityが開始された後、ユーザーが更新を受信できない特定のケースでは、アプリを開くことで更新を継続する必要があります
    • これに対応するために、stale dateを将来の日付と時刻に設定します。これは、ユーザーに最初の更新を送信した後のタイミングで、更新を受信していないユーザーにフォールバックメッセージが表示されます。
    • ウィジェットUIでこの「stale」状態をリッスンして、フォールバックメッセージを表示できます:
    swift
      struct ptsLiveActivity: Widget {
      var body: some WidgetConfiguration {
          ActivityConfiguration(for: ptsAttributes.self) { context in
              //stale dateの後にtrueになります
              let isStale = context.isStale
              if !isStale{
                  VStack {
                      Text("\(context.attributes.name) \(context.state.emoji)")
                          .activityBackgroundTint(Color.cyan)
                          .activitySystemActionForegroundColor(Color.black)
                  }
              }  else {
              //メッセージがstaleの場合、ユーザーにウィジェットをクリックしてアプリを開くように要求します
                  VStack {
                      Text("Something went wrong, please click to refresh")
                  }
              }
      //... ウィジェットUIの残り
      }
    
}



---

## FAQ

### 高優先度更新の予算は何ですか?

Appleは高優先度(`priority: 10`)更新に固定制限を提供していませんが、動的なシステムレベルの予算を適用しています。短期間に高優先度更新を送信しすぎると、更新が遅延またはドロップされるスロットリングが発生する可能性があります。

スロットリングのリスクを軽減するには:
- 優先度レベルを混在させる:Appleは、バランスを取るために`priority: 5`(標準)と`priority: 10`(高)の両方を使用することを推奨しています。
- `priority: 10`は、時間に敏感または重要な更新のみに予約します(例:注文ステータスの変更、ゲームスコア)。

ユースケースで頻繁な更新が必要な場合:
- アプリの`Info.plist`ファイルに`NSSupportsLiveActivitiesFrequentUpdates`キーをBoolean `YES`として追加します。
- この予算を超えると、iOSはユーザーに追加の更新を許可するように促す場合があります。ユーザーが同意すると、Appleはシームレスなエクスペリエンスを維持するために、許可された更新制限を自動的に拡張します。

詳細については、[AppleのDeveloper Docs](https://developer.apple.com/documentation/activitykit/starting-and-updating-live-activities-with-activitykit-push-notifications#Determine-the-update-frequency)を参照してください。

### メインアプリからLive Activity更新を読み取ることはできますか?

はい。デバッグまたはUI同期のために更新を監視できます:

```swift
Task {
    for await content in activity.contentUpdates {
        print("LA activity id: \(activity.id), content update: \(content.state)")
    }
}
// 出力例:
// LA activity id: EFE6D54D-F7E1-45EF-9514-4C2598F8DED2, content update: ContentState(message: "My message from payload")
ライフサイクルの変更を追跡:
Task {
    for await state in activity.activityStateUpdates {
        print("LA state update: \(state)")
        //状態に基づいて何かをしたい場合は、これを使用します:
      	if state != ActivityState.active {
            //ここで何かを行う
        }
    }
}

// 出力例 1 - LAは終了したが、まだ表示されている
// LA state update: active

/* StateはActivityState列挙型の4つの可能な値のいずれかになります
active、dismissed、ended、stale
*/

APIが400を返し、サブスクライバー制限を超えているというエラーメッセージが表示されました。どうすればよいですか?

プッシュサブスクライバー数がプランのプッシュサブスクライバー数を超えている場合は、アカウントを次のプランにアップグレードするか、support@onesignal.comにお問い合わせください。最新のプラン詳細については、こちらをご覧ください

プッシュとLive Activitiesの両方を送信しないようにするにはどうすればよいですか?

アプリケーションは既に一連のプッシュ通知を送信している可能性があり、設計したLive Activityがこれらのプッシュ通知の必要性を置き換えます。たとえば、プッシュ経由でスコア更新を送信している場合、これをLive Activityで置き換えることができます。 ユーザーがメッセージを受け取りすぎないようにするために、ユーザーがLive Activityにオプトインするときにデータタグを追加することをお勧めします。このデータタグを追加することで、同じまたは類似のコンテンツを含む可能性のあるプッシュメッセージからこのデータタグを持つユーザーを除外できます。詳細については、データタグセグメントをご覧ください。

トラブルシューティング

受信者なし

Live Activityを開始または更新しようとするときにユーザーが見つかるようにするには、アクティビティタイプ、ウィジェット、およびcURLリクエストのすべてに一致する値があることを確認する必要があります。
  1. リクエストのパスパラメーターをチェックして、正しくフォーマットされたリクエストをサーバーに送信していることを確認します。App IDはOneSignal.Initializeメソッドで使用したApp IDと一致する必要があり、アクティビティタイプはLive Activityファイルで定義したタイプと一致する必要があります。
  2. Push To Start APIリクエストの本文には、次のパラメーターが必要です:
  • event: "start"
  • event_updates: アクティビティタイプの下の構造体で定義した動的データで、ウィジェットで使用されます。リクエスト、タイプ、ウィジェット間で大文字小文字と変数がすべて一致することを確認してください。
  • event_attributes: 静的データはEvent Updatesと同じロジックに従い、使用中のすべての変数を含める必要があり、Live Activityのすべての部分とリクエスト全体で一致する必要があります
  • activity_id: これによりウィジェットにIDが割り当てられ、ユーザーのデバイスで起動された後にアクティビティを更新するために使用されます。
  • name: Live Activity名。
  • contents: プッシュ送信に必要なメッセージコンテンツ。
  • headings: プッシュ送信に必要なメッセージ見出し。
  • included_segmentsのようなターゲティングパラメーター。利用可能なオプション

アクティビティが送信されたが、受信されない

  1. リクエストが正しくフォーマットされていることを確認します。ウィジェットで使用されているフィールドが省略されている場合、アクティビティが起動または更新されない可能性があります。
  2. APIリクエストで、設定しているpriorityレベルを確認します。これを10(最高優先度)に設定している場合は、5に下げて再度テストしてください。Appleは独自の内部レート制限に従って、頻繁に送信されるリクエストをスロットルします。
ユースケースでより頻繁な更新が必要な場合は、AppleのDeveloper Docsで指示されているように、Info.plistにBoolean型でYESに設定されたNSSupportsLiveActivitiesFrequentUpdatesキーを追加します。Live Activityがプッシュ予算を超えると、ユーザーにダイアログが表示され、ユーザーがLive Activityの継続を許可すると、シームレスなユーザーエクスペリエンスのために予算が自動的に増加します。
サポートが必要ですか?サポートチームとチャットするか、support@onesignal.comにメールしてください以下を含めてください:
  • 発生している問題の詳細と再現手順(利用可能な場合)
  • OneSignal App ID
  • 該当する場合は、External IDまたはSubscription ID
  • 該当する場合は、OneSignalダッシュボードでテストしたメッセージのURL
  • 関連するログまたはエラーメッセージ
お気軽にお問い合わせください!