通知サービスエクステンションを使用すると、ユーザーに表示される前にプッシュ通知をインターセプトして変更できます。これにより次のことが可能になります:
- バックグラウンドデータ処理
- カスタムスタイル(色、アイコン、バイブレーション)
- リッチメディア添付ファイル(画像、動画)
- 配信確認/分析
- アクションボタンオプション
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として追加します。「未使用」の警告は無視してください。
<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をアプリに渡す場所です。このメソッドが呼び出される前に、通知ペイロードを取得し、(必要に応じて)ユーザーに表示される前に更新できます。
この例では、次のデータを含む通知を送信します:
{
"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のOneSignalNotificationServiceExtensionターゲットの例
OneSignalNotificationServiceExtension > Infoタブで続けて、NSExtensionキーを展開します。次のことが表示されることを確認してください:
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.usernotifications.service</string>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).NotificationService</string>
</dict>
例:
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に設定します。
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プロパティを使用します)。この例では、ペイロードは次のとおりです:
//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が正しくセットアップされていることを確認してください。