通知サービスエクステンションを使用すると、ユーザーに表示される前にプッシュ通知をインターセプトして変更できます。
Android通知サービスエクステンション
ユーザーに表示される前に通知を処理できます。一般的なユースケースには次のものがあります:
通知を表示するかどうかに関わらず、バックグラウンドでデータを受信します。
カスタムアクセントカラー、バイブレーションパターン、または利用可能なその他のNotificationCompatオプションなど、クライアント側アプリロジックに応じて特定の通知設定を上書きします。
詳細については、AndroidのNotificationCompatオプションに関するドキュメント を参照してください。
ステップ1: サービスエクステンション用のクラスを作成する
INotificationServiceExtensionを拡張し、onNotificationReceivedメソッドを実装するクラスを作成します。
メソッドonNotificationReceivedパラメータは、INotificationReceivedEvent 型のeventです。
package your. package .name
import androidx.annotation. K eep;
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()を呼び出さない場合、通知は警告なしに静かに破棄されます。詳細については重複通知 を参照してください。String promoCode = notification . getAdditionalData () != null
? notification . getAdditionalData (). optString ( "promo_code" , null )
: null ;
if (promoCode != null ) {
String updatedBody = notification . getBody () + " Use code: " + promoCode;
notification . setExtender (builder -> {
builder . setContentText (updatedBody);
});
}
int iconResId = R . drawable . icon_default ;
String type = notitifcation . getAdditionalData () != null
? notification . getAdditionalData (). optString ( "type" , "" )
: "" ;
switch (type) {
case "sale" :
iconResId = R . drawable . icon_sale ;
break ;
case "reminder" :
iconResId = R . drawable . icon_reminder ;
break ;
}
int finalIconResId = iconResId;
notification . setExtender (builder -> {
builder . setColor ( 0xFF0000FF ). setSmallIcon (finalIconResId);
});
ここで参照するアイコンはアプリのres/drawableディレクトリに存在する必要があります。
ステップ3: サービスエクステンションをAndroidManifest.xmlに追加する
アプリケーションタグ内のAndroidManifest.xmlファイルにクラス名と値をmeta-dataとして追加します。「未使用」の警告は無視してください。
< 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を読み取ったり変更したりできます。
この例では、次のデータを含む通知を送信します:
{
"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" ]
}
userInfoのcustomディクショナリ内の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のメインターゲットと一致することを確認してください。
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 ) " )
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に設定します。
3. プロジェクトをビルドして実行する
実際のデバイスでXcodeでプロジェクトをビルドして実行します。
4. コンソールを開く
Xcodeで、Window > Devices and Simulators を選択します。
デバイスが接続されているのが見えるはずです。Open Console を選択します。
5. コンソールを確認する
コンソールで:
Action > Include Debug Messages を選択します
CATEGORYとしてOneSignalNotificationServiceExtensionを検索します
Start を選択します
このデバイスにメッセージを含む通知を送信します(プッシュ通知 APIから送信する場合はcontentsプロパティを使用します)。この例では、ペイロードは次のとおりです:
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セットアップ を再度実行して、インテグレーションが正しいことを確認してください。
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、動画を添付します。
重複通知 すべてのプラットフォームでの重複プッシュ通知をトラブルシューティングします。