メインコンテンツへスキップ
通知サービスエクステンションを使用すると、ユーザーに表示される前にプッシュ通知をインターセプトして変更できます。
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*/
     }
}

@Keepアノテーションは、ProGuard/R8がミニファイ中にクラスの名前変更や削除を行わないようにするために必要です。

ステップ2: 通知をカスタマイズする

以下は、上記のテンプレート通知サービスエクステンションクラスに実装できる一般的な例です。
event.preventDefault()を呼び出すと通知の自動表示を阻止し、手動で表示するかまったく表示しないかを決定できます。
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();
event.preventDefault()を呼び出した後にdisplay()を呼び出さない場合、通知は警告なしに静かに破棄されます。詳細については重複通知を参照してください。

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

アプリケーションタグ内のAndroidManifest.xmlファイルにクラス名と値をmeta-dataとして追加します。「未使用」の警告は無視してください。
XML
<application>
  <meta-data
    android:name="com.onesignal.NotificationServiceExtension"
    android:value="com.onesignal.example.NotificationServiceExtension" />
</application>
com.onesignal.example.NotificationServiceExtensionをクラスの完全修飾名に置き換えてください。

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

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

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

didReceive(_:withContentHandler:)のオーバーライドは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"]
}
userInfocustomディクショナリ内のaキーを介してOneSignalNotificationServiceExtension内でこの追加のdataにアクセスします:
if let bestAttemptContent = bestAttemptContent {

    if let customData = bestAttemptContent.userInfo["custom"] as? [String: Any],
       let additionalData = customData["a"] as? [String: Any] {

        if let jsonData = try? JSONSerialization.data(withJSONObject: additionalData, options: .prettyPrinted),
           let jsonString = String(data: jsonData, encoding: .utf8) {
            print("The additionalData dictionary in JSON format:\n\(jsonString)")
        } else {
            print("Failed to convert additionalData to JSON format.")
        }
    }

    if let messageData = bestAttemptContent.userInfo["aps"] as? [String: Any],
       let apsData = messageData["alert"] as? [String: Any],
       let body = apsData["body"] as? String,
       let title = apsData["title"] as? String {
        print("The message contents is: \(body), message headings is: \(title)")
    } else {
        print("Unable to retrieve apsData")
    }

    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 General tab showing Supported Destinations and Minimum Deployment for the main app target
Xcode General tab showing Supported Destinations and Minimum Deployment for the notification service extension target
OneSignalNotificationServiceExtension > Infoタブで続けて、NSExtensionキーを展開します。次のことが表示されることを確認してください:
XML
 <dict>
   <key>NSExtensionPointIdentifier</key>
   <string>com.apple.usernotifications.service</string>
   <key>NSExtensionPrincipalClass</key>
   <string>$(PRODUCT_MODULE_NAME).NotificationService</string>
 </dict>
例:
Xcode Info tab showing the NSExtension dictionary with NSExtensionPointIdentifier and NSExtensionPrincipalClass keys
Objective-Cを使用している場合は、$(PRODUCT_MODULE_NAME).NotificationServiceの代わりにNotificationServiceを使用してください。

「インストール時のみコピー」をオフにする

メインアプリターゲット > Build Phases > Embed App Extensionsを選択します。「インストール時のみコピー」がチェックされていないことを確認してください。チェックされている場合は、チェックを外してください:
Xcode Build Phases tab showing Embed App Extensions with Copy only when installing unchecked

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)")
        os_log("%{public}@", log: OSLog(subsystem: "YOUR_BUNDLE_ID", category: "OneSignalNotificationServiceExtension"), type: OSLogType.debug, userInfo.debugDescription)

        if let bestAttemptContent = bestAttemptContent {
            print("Running NotificationServiceExtension")
            bestAttemptContent.body = "[Modified] " + bestAttemptContent.body

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

    override func serviceExtensionTimeWillExpire() {
        if let contentHandler = contentHandler, let bestAttemptContent =  bestAttemptContent {
            OneSignalExtension.serviceExtensionTimeWillExpireRequest(self.receivedRequest, with: self.bestAttemptContent)
            contentHandler(bestAttemptContent)
        }
    }

}

デバッグログタイプはコンソールで Action > Include Debug Messages を使用して有効にする必要があります。

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

アクティブスキームをOneSignalNotificationServiceExtensionに設定します。
Xcode toolbar showing the active scheme dropdown set to OneSignalNotificationServiceExtension

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

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

4. コンソールを開く

Xcodeで、Window > Devices and Simulatorsを選択します。
Xcode menu showing the Window dropdown with Devices and Simulators selected
デバイスが接続されているのが見えるはずです。Open Consoleを選択します。
Xcode Devices window showing the Open Console button for a connected device

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

コンソールで:
  1. Action > Include Debug Messages を選択します
  2. CATEGORYとしてOneSignalNotificationServiceExtensionを検索します
  3. Start を選択します
macOS Console app showing the category filter and Start button for debugging the notification service extension
このデバイスにメッセージを含む通知を送信します(プッシュ通知 APIから送信する場合はcontentsプロパティを使用します)。この例では、ペイロードは次のとおりです:
cURL
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"
]
}'
アプリが実行されている場合と実行されていない場合の両方で、メッセージがログに記録されているのが見えるはずです。
macOS Console app showing debug log output from the OneSignalNotificationServiceExtension
メッセージが表示されない場合は、アプリからOneSignalを削除し、モバイルSDKセットアップを再度実行して、インテグレーションが正しいことを確認してください。

FAQ

iOSで通知サービスエクステンションが実行されないのはなぜですか? エクステンションはmutable-contentが設定されている場合にのみ実行されます。OneSignalは添付ファイルやアクションボタンがある場合に自動的にこれを設定します。Xcode設定がトラブルシューティングセクションの要件と一致していることを確認してください。 Androidで通知の表示を防ぐことはできますか? はい、event.preventDefault()を呼び出すと通知を抑制できます。後でevent.getNotification().display()を呼び出して表示するか、呼び出さずに静かに破棄することもできます。詳細については重複通知を参照してください。 AndroidでAnnotation @Keepは必要ですか? はい、@Keepアノテーションは、ProGuard/R8がミニファイ中にINotificationServiceExtensionを実装するクラスの名前変更や削除を行わないようにするために必要です。

関連ページ

モバイルSDKセットアップ

iOSおよびAndroid向けにOneSignal SDKをインストールして設定します。

画像とリッチメディア

プッシュ通知に画像、GIF、動画を添付します。

配信確認

デバイスへの通知配信確認を追跡します。

重複通知

すべてのプラットフォームでの重複プッシュ通知をトラブルシューティングします。