Reputation: 1173
Im implementing new iOS10 extension to use rich notifications. Im trying to test it on push notifications but is not working, I just receive a simple notification and is not going through the extension.
I did all that it's specified in the official sites and some other places:
As I said, I get the notification but never goes through the extension. I see how the OS tries to load the extension but then throws an error with no relevant description to identify the problem:
Dec 31 21:00:00 iPhone SpringBoard(libextension.dylib)[51] <Notice>: calling plugIn beginUsing:
Dec 31 21:00:57 iPhone pkd[86] <Notice>: assigning plug-in com.test.app.NotificationWithAttachmentExtension(1.0) to plugin sandbox
Dec 31 21:03:57 iPhone pkd[86] <Notice>: enabling pid=51 for plug-in com.test.app.NotificationWithAttachmentExtension(1.0) 38BB5FF1-2597-42E0-B950-169DBFA80573 /private/var/containers/Bundle/Application/A8C47706-C0EC-4FB1-ABA7-0118372F6900/testapp.app/PlugIns/NotificationWithAttachmentExtension.appex
Dec 31 21:00:53 iPhone SpringBoard(PlugInKit)[51] <Notice>: plugin com.test.app.NotificationWithAttachmentExtension interrupted
Dec 31 21:03:56 iPhone SpringBoard(PlugInKit)[51] <Notice>: Hub connection error Error Domain=NSCocoaErrorDomain Code=4097 "connection to service named com.test.app.NotificationWithAttachmentExtension" UserInfo={NSDebugDescription=connection to service named com.test.app.NotificationWithAttachmentExtension}
Jun 29 13:33:36 iPhone SpringBoard(libextension.dylib)[51] <Notice>: PlugInKit error in beginUsing:
Jun 17 23:33:04 iPhone SpringBoard(libextension.dylib)[51] <Notice>: killing invalid plugIn
Dec 31 21:00:00 iPhone SpringBoard(UserNotificationsServer)[51] <Error>: Extension error whilst trying to modify push notification F502-9B36: Error Domain=NSCocoaErrorDomain Code=4097 "connection to service named com.test.app.NotificationWithAttachmentExtension" UserInfo={NSDebugDescription=connection to service named com.test.app.NotificationWithAttachmentExtension}
Dec 31 21:00:00 iPhone SpringBoard(UserNotificationsServer)[51] <Notice>: [com.test.app] Saving notification F502-9B36
Dec 31 21:00:00 iPhone SpringBoard(libextension.dylib)[51] <Notice>: completed calling plugIn beginUsing: for pid: 0
Relevant extension .plist:
<dict>
<key>NSExtensionAttributes</key>
<dict>
<key>UNNotificationExtensionCategory</key>
<string>attachmentCategory</string>
<key>UNNotificationExtensionInitialContentSizeRatio</key>
<real>1</real>
</dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.usernotifications.service</string>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).NotificationService</string>
</dict>
What's wrong or missing?
Upvotes: 31
Views: 36419
Reputation: 6023
Swift 5+ Easy way
(in 2019 i have tried on ios10 and in 2024 i am working on ios 17+)
FOR ATTACHMENT OF PID FOLLOW THE STEP IN PICTURE VIA SELECTING YOU XCODE
TODO: - First way to attach the Notification service if you now the pid or process name
After running the app that contains the extension
Set your breakpoint in the extension
Select Debug / Attach to Process by PID or name
Enter the name of the extension target
Trigger the push notification
if Not worked upper mentioned Trick
2nd Way to use debugger in notification extension
1) Run service extension as the Target instead of the app. Then it will ask for which app you have run service extension, then select your app and it will send the notification.
2) Make sure the deployment target of the service extension is less than your physical device's OS version.
3) Ensure payload contains 'mutable-content: 1'
4) Use FireBase Console for sending Push Notification (Which is authentic) No Need for 3rd Party Notification Service
//TODO: - in my case i was using 3rd party and waste my 2 days
//TODO: - 3rd Way
. this is very easy way just do it like this Firebase Side should be like:
{
"apns":{
"payload":{
"aps":{
"subtitle":"Session 707",
"mutable-content": 1, //Important Line
"sound":"true"
}
},
"fcm_options":{
"image":"https://i.sstatic.net/YxaLI.png"
}
}
}
Upvotes: 10
Reputation: 1052
Thanks for all good suggestions, which helped me fixed my mismatch with deployment target and missing mutable-content. But for me I still had issues getting the NSE to be called. I found the solution in the source code from this blog, https://medium.com/gits-apps-insight/processing-notification-data-using-notification-service-extension-6a2b5ea2da17. I was missing Embed App Extensions that copied the extension to my app. Why this was missing, I'm not sure, I have not seen this as a required step in the different tutorials I have read.
The Embed App Extension is just a "Copy File Phase" that has been renamed, as explained here https://stackoverflow.com/a/71031519/3080858
This tutorial was also very helpful setting up the different App Ids, App Groups, Profiles etc: https://blog.logrocket.com/implement-push-notifications-react-native-onesignal/
Upvotes: 1
Reputation: 574
I'm currently working on Xcode 12.3 and Swift 5.2, and when I backed off the Main Project Target and Notification Service Extension Target from iOS 14.2 to iOS 13.2, it worked!
Upvotes: 1
Reputation: 4308
And if you've done everything correctly, don't forget to attach it to the process.
After running the app that contains the extension:
Upvotes: 29
Reputation: 111
You must set the deployment target to be the same on all your targets. I wonder why this is not done automatically by XCode :/ .. Apple loves to waste the developers' time smh...
Upvotes: 11
Reputation: 547
After struggling with this I finally made this work for me by just changing 2 things.
Note: Make sure you have "mutable-content" : 1 in remote payload.
Hope this helps someone.
Upvotes: 4
Reputation: 4846
The system executes your notification content app extension only when a remote notification’s payload contains the following information:
The payload must include the mutable-content
key with a value of 1
.
The payload must include an alert dictionary with title, subtitle, or body information.
Specifying the remote notification payload:
{
“aps” : {
“category” : “SECRET”,
“mutable-content” : 1,
“alert” : {
“title” : “Secret Message!”,
“body” : “(Encrypted)”
},
},
“ENCRYPTED_DATA” : “Salted__·öîQÊ$UDì_¶Ù∞è Ω^¬%gq∞NÿÒQùw”
}
Upvotes: 0
Reputation: 617
For anyone looking to just trigger a breakpoint in your app’s notification extension, the process is pretty simple in Xcode 11.3:
Edit Scheme
.Debug executable
. By unchecking this, you are informing Xcode to debug the extension instead of the parent app. This is key to getting Xcode to stop within the extension’s breakpoints. Automatically
under the Launch
option. Unless some other stuff triggers Xcode’s moodiness, the above settings should ensure that whenever you select and run the extension scheme, the breakpoints within the extension will be hit. You can go back and check Debug executable
in step 4 if you want Xcode to stop at breakpoints within the parent app.
Pro-tip: Don’t forget to add "mutable-content": 1
within the notification JSON payload, otherwise you will have a major sad (iOS won’t invoke the extension without that key).
Here’s a picture of my scheme editor dialog for the notification extension:
Upvotes: 6
Reputation: 9836
Other possibility is to check category name in plist file of UNNotificationContentExtension.
String value of "UNNotificationExtensionCategory" in plist and "category/click_action" of payload should be same.
Upvotes: 1
Reputation: 81
In my case it was what I forget to select NotificationServiceExtension in Scheme as particular app instead of "my application" where I try to use it. So I've been running "my app" and waited for breakpoints in code of another app (NotificationServiceExtension) and and that's why they never showed up. I tried every suggestions before that.
Upvotes: 3
Reputation: 139
Had the same problem, what solved it for me was removing the extension from Embedded Binaries and adding it again.
Upvotes: 7
Reputation: 121
If you are using Firebase, then try changing the payload as:
{
“aps” : {
“category” : “SECRET”,
“mutable_content” : true,
“alert” : {
“title” : “Secret Message!”,
“body” : “(Encrypted)”
},
},
“ENCRYPTED_DATA” : “Salted__·öîQÊ$UDì_¶Ù∞è Ω^¬%gq∞NÿÒQùw”
}
The mutable_content field maps to the mutable-content field on APNs. For more details, go through this link.
Upvotes: 11
Reputation: 8151
My issue was two fold. The first probably was that I had set the Info.plist
property NSExtensionPrincipalClass to bundle.identifier.NotificationService
instead of ProductModuleName.NotificationService
. Module name is the default, but I had erroneously changed to the identifier when debugging some other things related to different schemes and different targets.
The second issue was that I tested by running the notification service target. For me it worked much better when running the app target. I saw some other people recommending to use the notification service target to enable debugging. But that works fine when running the app target as well. You'll have to attach the debugger to your notification service manually though.
The way I discovered the above was to create a new test project with minimal code. In hindsight I definitely recommend that approach instead of trying out all the different solutions found on stackoverflow etc
Upvotes: 2
Reputation: 2975
It seems like your plist is mixing 2 plists. There are 2 extensions in play:
Here is the plist for Notification Content Extension
target:
Here is the plist for Notification Service Extension
target:
Upvotes: 7
Reputation: 16298
Came here the second time. The first time, this answer helped me, the second time, it didn't. After a lot of (internal) swearing I found out that I had somehow accidentally removed the extension from Embedded Binaries in my main app target. When I added the extension back, my extension would be called again.
So check this:
Upvotes: 9
Reputation: 267
After trying many of the possible fixes already given without success, it dawned on me that a framework had been mistakenly added to our extension target rather than the unit test target.
Removing the framework and targeting 10.2 allowed my extension to be called once again.
If you are curious as to which framework for whatever reason you can find it here: https://github.com/plu/JPSimulatorHacks
Upvotes: 4
Reputation: 11
Be sure that you have 'None' configuration set. Look at the screenshot. With other parameters didReceive
doesn't work.
Upvotes: 1
Reputation: 4546
What also might do the trick is check your deployment target for the extension. Mine was set at 10.2
while the device I was testing on was (still) using 10.1
After altering the deployment target to 10.0
the UNNotificationServiceExtension
instance was called perfectly
Upvotes: 78
Reputation: 1173
Finally I have this working correctly, and this is what I remember from this issue.
1) Do not use devices with iOS10 beta version, because one of the problems I had was because I was using a beta version.
2) only the app requres APNS entitlements, this is not required for the privisoning used for the extension.
3) I was using a provisioning profile matching the id of the extension (not wildcard), anyway I cannot confirm if it works fine or not with wildcard.
4) NSExtensionAttributes are not required, just use NSExtensionPointIdentifier and NSExtensionPrincipalClass for the extension .plist. Unless you are using your own layout
5) This is working even using iOS 9 token registration methods.
6) don't forget mutable-content value in the payload coming in the push notification, this is the only mandatory value you need from the server to go through the extension.
I think this covers all the problems I had
Upvotes: 16
Reputation: 2975
The public func didReceiveNotificationRequest(request: UNNotificationRequest, withContentHandler contentHandler: (UNNotificationContent) -> Void)
method in UNNotificationServiceExtension
has changed between swift versions.
Some of the online examples are not up to date.
Make sure the method you're overriding in your custom subclass of UNNotificationServiceExtension
I had:
func didReceive(request: UNNotificationRequest, withContentHandler contentHandler:(UNNotificationContent) -> Void)
which didn't work until i changed to:
func didReceiveNotificationRequest(request: UNNotificationRequest, withContentHandler contentHandler: (UNNotificationContent) -> Void)
Upvotes: 2