メインコンテンツへスキップ

概要

通知サービスエクステンションを使用すると、ユーザーに表示される前にプッシュ通知をインターセプトして変更できます。これにより次のことが可能になります:
  • バックグラウンドデータ処理
  • カスタムスタイル(色、アイコン、バイブレーション)
  • リッチメディア添付ファイル(画像、動画)
  • 配信確認/分析
  • アクションボタンオプション
OneSignalから送信されたプッシュ通知のデータには、OSNotificationクラスを介してアクセスできます

Android通知サービスエクステンション

ユーザーに表示される前に通知を処理できます。一般的なユースケースには次のものがあります:
  • 通知を表示するかどうかに関わらず、バックグラウンドでデータを受信します。
  • カスタムアクセントカラー、バイブレーションパターン、または利用可能なその他のNotificationCompatオプションなど、クライアント側アプリロジックに応じて特定の通知設定を上書きします。
詳細については、AndroidのNotificationCompatオプションに関するドキュメントを参照してください。

1. サービスエクステンション用のクラスを作成する

INotificationServiceExtensionを拡張し、onNotificationReceivedメソッドを実装するクラスを作成します。 メソッドonNotificationReceivedパラメータは、INotificationReceivedEvent型のeventです。
package your.package.name

import androidx.annotation.Keep;
import com.onesignal.notifications.IActionButton;
import com.onesignal.notifications.IDisplayableMutableNotification;
import com.onesignal.notifications.INotificationReceivedEvent;
import com.onesignal.notifications.INotificationServiceExtension;

@Keep // Keep is required to prevent minification from renaming or removing your class
public class NotificationServiceExtension implements INotificationServiceExtension {

     @Override
     public void onNotificationReceived(INotificationReceivedEvent event) {
        IDisplayableMutableNotification notification = event.getNotification();

        if (notification.getActionButtons() != null) {
           for (IActionButton button : notification.getActionButtons()) {
              // you can modify your action buttons here
           }
        }

     /* Add customizations here. See examples below for additional methods to modify the notification*/
     }
}

2. 使用例

以下は、上記のテンプレート通知サービスエクステンションクラスに実装できる一般的な例です。
  • 通知の表示を防ぐ
  • カスタムフィールドを追加
  • 通知の色とアイコンを変更
event.preventDefault();

//Do some async work, then decide to show or dismiss
new Thread(() -> {
    try {
        Thread.sleep(1000);
    } catch (InterruptedException ignored) {}

    //Manually show the notification
    event.getNotification().display();
}).start();

3. サービスエクステンションをAndroidManifest.xmlに追加する

アプリケーションタグ内のAndroidManifest.xmlファイルにクラス名と値をmeta-dataとして追加します。「未使用」の警告は無視してください。
XML
<application> 
  <!-- Keep android:name as shown, set android:value toyour class fully name spaced-->
  <meta-data 
    android:name="com.onesignal.NotificationServiceExtension"
    android:value="com.onesignal.example.NotificationServiceExtension" />
</application>

iOS通知サービスエクステンション

UNNotificationServiceExtensionを使用すると、ユーザーに表示される前にプッシュ通知のコンテンツを変更でき、次のような他の重要な機能にも必要です: アプリのモバイルSDKセットアップの手順に従った場合は、すでにこれをセットアップしている可能性がありますが、このセクションでは、OneSignal通知ペイロードデータにアクセスする方法と、発生している可能性のある問題をトラブルシューティングする方法について説明します。

iOSプッシュペイロードの取得

モバイルSDKセットアップに従うと、OneSignalNotificationServiceExtensionにコードを追加するセクションに到達します。 そのコードには、OneSignalExtension.didReceiveNotificationExtensionRequestメソッドがあります。これは、ユーザーに表示される前に通知のbestAttemptContentをアプリに渡す場所です。このメソッドが呼び出される前に、通知ペイロードを取得し、(必要に応じて)ユーザーに表示される前に更新できます。 この例では、次のデータを含む通知を送信します:
JSON
{
  "app_id": "YOUR_APP_ID",
  "target_channel": "push",
  "headings": {"en": "The message title"},
  "contents": {"en": "The message contents"},
  "data":{
    "additional_data_key_1":"value_1",
    "additional_data_key_2":"value_2"
    },
  "include_subscription_ids": ["SUBSCRIPTION_ID_1"]
}
この追加のdataには、aパラメータを使用してcustomオブジェクトを介してOneSignalNotificationServiceExtension内でアクセスできます。
// Check if `bestAttemptContent` exists
if let bestAttemptContent = bestAttemptContent {

    // Try to retrieve the "custom" data from the notification payload
    if let customData = bestAttemptContent.userInfo["custom"] as? [String: Any],
       let additionalData = customData["a"] as? [String: Any] {

        // Convert the `additionalData` dictionary to a JSON string for logging
        if let jsonData = try? JSONSerialization.data(withJSONObject: additionalData, options: .prettyPrinted),
           let jsonString = String(data: jsonData, encoding: .utf8) {
            // Successfully converted to JSON; log the formatted JSON string
            print("The additionalData dictionary in JSON format:\n\(jsonString)")
        } else {
            // Failed to convert the `additionalData` dictionary to JSON
            print("Failed to convert additionalData to JSON format.")
        }
    }

    // Try to retrieve the "aps" data from the notification payload
    if let messageData = bestAttemptContent.userInfo["aps"] as? [String: Any],
       let apsData = messageData["alert"] as? [String: Any],
       let body = apsData["body"] as? String,  // Extract the "body" of the alert
       let title = apsData["title"] as? String {  // Extract the "title" of the alert
        // Successfully retrieved the body and title; log the values
        print("The message contents is: \(body), message headings is: \(title)")
    } else {
        // Failed to retrieve the "aps" data or its contents
        print("Unable to retrieve apsData")
    }

    // Pass the notification to OneSignal for further processing
    OneSignalExtension.didReceiveNotificationExtensionRequest(self.receivedRequest,
                                                              with: bestAttemptContent,
                                                              withContentHandler: self.contentHandler)
}
コンソール出力例:
The additionalData dictionary in JSON format:
{
  "additional_data_key_1" : "value_1",
  "additional_data_key_2" : "value_2"
}
The message contents is: The message contents, message headings is: The message title

iOS通知サービスエクステンションのトラブルシューティング

このガイドは、iOSモバイルアプリで画像、アクションボタン、または配信確認が表示されない問題をデバッグするためのものです。 Xcode設定を確認する General > Targetsで、メインアプリターゲットOneSignalNotificationServiceExtensionターゲットが同じで正しいことを確認してください:
  • サポートされる送信先
  • 最小デプロイメント(iOS 14.5以上)
Cocoapodsを使用している場合は、ビルドエラーを回避するために、これらがPodfileのメインターゲットと一致することを確認してください。

Xcodeのメインアプリターゲットの例

XcodeのOneSignalNotificationServiceExtensionターゲットの例

OneSignalNotificationServiceExtension > Infoタブで続けて、NSExtensionキーを展開します。次のことが表示されることを確認してください:
XML
 <dict>
   <key>NSExtensionPointIdentifier</key>
   <string>com.apple.usernotifications.service</string>
   <key>NSExtensionPrincipalClass</key>
   <string>$(PRODUCT_MODULE_NAME).NotificationService</string>
 </dict>
例:

InfoタブのNSExtensionキーの例

Objective-Cを使用している場合は、$(PRODUCT_MODULE_NAME).NotificationServiceの代わりにNotificationServiceを使用してください。
「インストール時のみコピー」をオフにする メインアプリターゲット > Build Phases > Embed App Extensionsを選択します。「インストール時のみコピー」がチェックされていないことを確認してください。チェックされている場合は、チェックを外してください:

メインアプリターゲットのビルドフェーズ設定

iOS通知サービスエクステンションのデバッグ

通知サービスエクステンションが正しくセットアップされていることを確認するには、次の手順に従ってください。

1. OneSignalNotificationServiceExtensionコードを更新する

NotificationService.mまたはNotificationService.swiftを開き、ファイルの内容全体を以下のコードに置き換えます。(コードは元のセットアップコードと同じですが、追加のログを追加しています。 YOUR_BUNDLE_IDを実際のBundle IDに置き換えてください。
import UserNotifications
import OneSignalExtension
import os.log

class NotificationService: UNNotificationServiceExtension {

    var contentHandler: ((UNNotificationContent) -> Void)?
    var receivedRequest: UNNotificationRequest!
    var bestAttemptContent: UNMutableNotificationContent?

    override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
        self.receivedRequest = request
        self.contentHandler = contentHandler
        self.bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)

        let userInfo = request.content.userInfo
        let custom = userInfo["custom"]
        print("Running NotificationServiceExtension: userInfo = \(userInfo.description)")
        print("Running NotificationServiceExtension: custom = \(custom.debugDescription)")
        //debug log types need to be enabled in Console > Action > Include Debug Messages
        //Replace YOUR_BUNDLE_ID with your actual Bundle ID
        os_log("%{public}@", log: OSLog(subsystem: "YOUR_BUNDLE_ID", category: "OneSignalNotificationServiceExtension"), type: OSLogType.debug, userInfo.debugDescription)

        if let bestAttemptContent = bestAttemptContent {
            /* DEBUGGING: Uncomment the 2 lines below to check this extension is executing
                          Note, this extension only runs when mutable-content is set
                          Setting an attachment or action buttons automatically adds this */
            print("Running NotificationServiceExtension")
            bestAttemptContent.body = "[Modified] " + bestAttemptContent.body

            OneSignalExtension.didReceiveNotificationExtensionRequest(self.receivedRequest, with: bestAttemptContent, withContentHandler: self.contentHandler)
        }
    }

    override func serviceExtensionTimeWillExpire() {
        // Called just before the extension will be terminated by the system.
        // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
        if let contentHandler = contentHandler, let bestAttemptContent =  bestAttemptContent {
            OneSignalExtension.serviceExtensionTimeWillExpireRequest(self.receivedRequest, with: self.bestAttemptContent)
            contentHandler(bestAttemptContent)
        }
    }

}

2. アクティブスキームを変更する

アクティブスキームをOneSignalNotificationServiceExtensionに設定します。

Xcodeアクティブスキームの選択

3. プロジェクトをビルドして実行する

実際のデバイスでXcodeでプロジェクトをビルドして実行します。

4. コンソールを開く

Xcodeで、Window > Devices and Simulatorsを選択します。

Xcode Devices and Simulatorsウィンドウ

デバイスが接続されているのが見えるはずです。Open Consoleを選択します。

デバイスコンソールアクセスボタン

5. コンソールを確認する

コンソールで:
  • Action > Include Debug Messagesを選択します
  • CATEGORYとしてOneSignalNotificationServiceExtensionを検索します
  • Startを選択します

コンソールデバッグ設定

このデバイスにメッセージを含む通知を送信します(Create message APIから送信する場合はcontentsプロパティを使用します)。この例では、ペイロードは次のとおりです:
cURL
  //Replace with your own app data:
  //YOUR_API_KEY, YOUR_APP_ID, SUBSCRIPTION_ID_1

curl --request POST \
 --url 'https://api.onesignal.com/notifications' \
 --header 'Authorization: Key YOUR_API_KEY' \
 --header 'accept: application/json' \
 --header 'content-type: application/json' \
 --data '
{
"app_id": "YOUR_APP_ID",
"target_channel": "push",
"headings": {"en": "The message title"},
"contents": {"en": "The message contents"},
"data":{"additional_data_key_1":"value_1","additional_data_key_2":"value_2"},
"include_subscription_ids": [
"SUBSCRIPTION_ID_1"
]
}'
アプリが実行されている場合と実行されていない場合の両方で、メッセージがログに記録されているのが見えるはずです。

コンソールデバッグ出力の例

メッセージが表示されない場合は、アプリからOneSignalを削除し、モバイルSDKセットアップを再度実行して、OneSignalが正しくセットアップされていることを確認してください。