iOS10 UNNotificationServiceExtension not called - ios

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:
I have my app up and running with push notifications and the right provisioning profile
I added a new target to my app, a Notification Service Extension
Implemented my own code (it doesn't matter really because is not even entering to the new class)
Also I had to set a provisioning profile for this extension, I just use one with a wildcard, I don't see any documentation specifying if the extension target has to enable push notifications capability, in that case I would need a specific provisioning for this one, at the moment I just use a wildcard prov, anyway it matches (it must match) the profile I use in the app target, and push notifications capability is enabled for the app target only.
I added UNNotificationExtensionCategory and NSExtensionPointIdentifier. Also Im sending the category as part of the push payload from the server.
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?

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

And if you've done everything correctly, don't forget to attach it to the process.
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

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

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.

Swift 5 Easy way
this is very easy way just do it like this

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...

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:
Click on your app project to the left.
Click on your main app target.
Choose General.
Under Embedded Binaries, make sure your extension is listed, if not, add it.

Had the same problem, what solved it for me was removing the extension from Embedded Binaries and adding it again.

It seems like your plist is mixing 2 plists.
There are 2 extensions in play:
Notification Content Extension - responsible for displaying the content via a view controller
Notification Service Extension - responsible for fetching content in the background before notification is displayed
Here is the plist for Notification Content Extension target:
Here is the plist for Notification Service Extension target:

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

For anyone looking to just trigger a breakpoint in your app’s notification extension, the process is pretty simple in Xcode 11.3:
Select the scheme of the extension (not the parent app scheme).
Select Edit Scheme.
Select the Executable to be your parent app.
Uncheck 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.
Select Automatically under the Launch option.
Run the scheme of the extension (not the parent app).
Send your device a notification. Profit.
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:

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.

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

After struggling with this I finally made this work for me by just changing 2 things.
The bundleID of the NotificationServiceExtension target must be a different one. Preferred style com.companyname.appname.notificationservice(whatever). Setting the same bundleID of the app causes a failure in building to device.
The main thing is the deployment target. I was double checking this with app's target but we must also check the deployment target of the newly created NotificationServiceExtenion's target which is by default the latest version. Set that to the minimum iOS version you would like to support but greater than ios 10.
Note: Make sure you have "mutable-content" : 1 in remote payload.
Hope this helps someone.

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)

Be sure that you have 'None' configuration set. Look at the screenshot. With other parameters didReceive doesn't work.
Configuration

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.

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!

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”
}

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/

Related

iOS Push Notifications stopped working (possibly due to entitlement error)

In the last couple of days we were getting some bug reports due to our Push Notification Feature not working anymore.
We use React Native with react-native-notifications (newest version). The build we have up in the app store is from the beginning of October and has worked just fine.
Now, out of nowhere when i press the button that is linked to requesting the PushToken, nothing happens - not even the Failure-Callback is triggered.
When i open the device console i just get these two errors when i click the button:
error 14:11:19.891971+0100 SpringBoard Entitlment 'com.apple.private.usernotifications.bundle-identifiers' for online.*.* required to request user notifications
error 14:11:19.892050+0100 SpringBoard [online.*.*] Requesting authorization failed because of missing entitlement
But obviously the entitlement for Push Notifications is set (and always has been).
Any of you got any ideas what to check? I'm a bit clueless right now.
Best!
Just a quick heads-up. Problem was, that my Product Name (Target -> Your App -> Build Settings -> Packaging -> Product Name) had german special characters.
See also: https://developer.apple.com/forums/thread/660648

iOS extension "Failed to find a valid app with bundleID" & "Error was encountered trying to find service extension"

We have an extension in our iOS project (Broadcast Upload Extension). The extension works well when doing local builds, however whenever we do a TestFlight build a distribute it we encounter following exception (found in device logs):
Error getting proxy for beta app with bundleID
com.foo.bar.screenshareextension: Error
Domain=ASDTestFlightFeedbackErrorDomain Code=5 "Failed to find a valid
app with bundleID com.foo.bar.screenshareextension"
UserInfo={NSDebugDescription=Failed to find a valid app with bundleID
com.foo.bar.screenshareextension}
one more error lists:
[com.foo.bar] Error was encountered trying to find service extension:
error=Error Domain=UNErrorDomain Code=1904 "Unknown application"
UserInfo={NSLocalizedDescription=Unknown application}
the bundle IDs are set correctly (meaning the container app has "com.foo.bar" bundle id while the extension has com.foo.bar.extensionname".
The extension is referenced through
var bundleUrl = NSBundle.MainBundle.GetUrlForResource("Foo.iOS.ScreenShareExtension", "appex", "PlugIns");
I can confirm actually that the extension appex file is physically in the archived file for distribution.
The only difference is that the min OS version is set differently in the container app & in the app extension. However when doing local builds this doesn't seem to matter.
What could be the reason for not being able to target the extension? (seems like it's missing?)
ps: we are using Xamarin.Forms
Not sure if this helps: I encountered a similar error today, the reason is that the default build target of the notification extension is 13.6(the latest OS), while my testing device is in 13.5. After I changed the build target, everything works fine.
I've got same error with native Swift code on iPhone 6 (12.4.8).
I'm still not sure what causes this bug, but for me it fixes only by changing device. On iPhone 8 (13.6) the absolutely same code works just fine, rebuilding for iPhone 6 and it's not even trying.

Will Firebase Analytics work from the simulator in Xcode?

In an IOS app I have
and I ensured the plist "defeat" entry is not there, and then I have analytics events like
Analytics.logEvent("touchedButton", parameters: nil)
In fact, if I run the app just in the Xcode simulator .. are these events reported to Firebase Analytics and show up?
Or perhaps if you build to an iPhone?
Or does it only work if it's an actual build which has gone through TestFlight?
Surprisingly I couldn't find this info anywhere.
Is it precisely here that such custom events will show:
Yes, both simulator or device will work.
If you haven't already read, read their getting started tutorials, it covers most of it https://firebase.google.com/docs/analytics/ios/start
A couple of points
Make sure when you configure your Firestore settings , you enable analytics
AnalyticsConfiguration.shared().setAnalyticsCollectionEnabled(true)
I do all of this initial settings in AppDelegate
something like
//init Firebase
FirebaseConfiguration.shared.setLoggerLevel(.min)
FirebaseApp.configure()
Fabric.with([Crashlytics.self])
let _ = FirebaseConfig.sharedInstance // This is a custom singelton class where I enable the analytics
In Scheme settings for your target you need to add -FIRAnalyticsDebugEnabled
As you can see I have also a disable option there, sometimes analytics goes crazy and spams the console , so I'd like to disable it with . -FIRDebugDisabled
Analytics clusters your events unless you specify it is a custom event.
For example I use following to tag the viewcontroller names
func logEvent(eventTitle:String , eventContent:String)
{
Analytics.logEvent(AnalyticsEventSelectContent, parameters: [
AnalyticsParameterItemID: "AppName-\(eventTitle)" as NSObject,
AnalyticsParameterItemName: eventTitle as NSObject,
AnalyticsParameterContentType: eventContent as NSObject
])
}
But int the firestore these are clustered under select_content section because I used AnalyticsEventSelectContent key when creating the log.
Under main events screen , select_content my view controlers logged with above function
4.There is a specific DebugView in the FirestoreConsole that works with a device, it updates every 60 seconds as long as settings for -FIRAnalyticsDebugEnabled is true in the scheme.
There is a significant delay in the Event Section of Firestore console, I don't know why this happens, but sometimes there is a delay up to 15 - 30 mins. Havent researched that issue yet, it really doesnt bother me.
Just follow https://firebase.google.com/docs/analytics/ios/start
To enable Analytics Debug mode on your development device, specify the following command line argument in Xcode :
-FIRDebugEnabled
It works perfectly for Simulator and device.
Note: For react-native debugging, launch app from xcode with the selected scheme and not with 'yarn ios', then it works perfectly for Simulator also

Debug Notification Extensions

I'm building a set of Notification Extensions (Service/Content).
I'm unable to connect to Xcode debugger or even log out to the device log or console.
Is there any way to see any kind of output?
Change the target to run the extension
then select run and choose your app from the 'Choose an app to run:' window.
I have tried as per brendan's Answer but is not working for me at all!
I am getting below error in console
Program ended with exit code: 0
Then after searching on google i have checked this answer. however this also not worked for me for while!
Then i have tried same steps again as given in answer, After stopping my current running app. then follow same steps.For clarity i am writing this steps as below:
After running the app that contains the extension,
1) Set your breakpoint in the extension
2) Select Debug / Attach to Process by PID or name
3) Enter the name of the extension target
4) Trigger the push notification
Before step 2 make sure to stop your current running app.
This worked for me to stop at breakpoints in the extension and see the extension log:
Choose the notification extension scheme, not the main app scheme
Run the app and select the main app from the list Choose an app to run
Stop the app in Xcode and terminate it manually on the device; not terminating it manually results in Message from debugger: Terminated due to signal 9 after step 6.
[Update: Terminating the app manually on the device doesn't seem to be necessary, try either way if it doesn't work.]
Select Menu Debug > Attach to Process by PID or Name
Enter the correct extension name, not the main app name
Send the push notification
Notification service extension (NSE) is not actually a part of your app but an extension that said it has a different process id (PID) from your app. You can have XCode listen to every process on your phone by going to the “Debug” tab, scroll down to “Attach to Process” and look to see if your NSE is listed under “Likely Targets”. If it's not there than try to sand another push notification to your device and attach to it when it appears.
Now in debug navigator you can see the NES process and you can successfully debug it.
In my case all methods above had some mistakes. Main point, that you need to send push one time, then connect through debugger, then send push to debug. So, full list:
Launch app (not extension).
Stop app from XCode.
Send one push.
Connect via "Attach to Process by PID or Name..." to your extension process.
Send another push.
If you have tried all the above solutions and still scratching your head and wondering why break point point is not being called. Then try checking the deployment target of your extension it should be less or equal to your device OS.
For me, the deployment target was higher than the device OS.
In my case (Xcode 11.1) debug starts after this steps:
run notification extension target with main app
switch app to background
lock the phone !
send push to device
I followed solutions mentioned here but nothing helped. I found out that problem is when payload of notification does not contain flag to enable content to be mutated. Notification without this flag are not handled by NotificationExtension at all. After I added "mutable-content": 1 to the payload and followed answers here I was able to alter content of push notification and to debug code in NotificationExtension.
{
"aps": {
"mutable-content": 1,
"alert": {
"title": "Push Title",
"body": "Push payload body"
}
},
"data": "what ever you need to be in userInfo"
}
Not sure if this will be helpful, but we have multiple builds of the same app (alpha, beta, etc). Kept getting a "don't have permissions to attach" error when trying to debug. Opening up the processes list, I noticed that there were 2 processes named notification-extension so xcode must have been defaulting to the one of the other build. By manually selecting the right one, or deleting the other builds from my phone things started working again.
The only way that worked for me was to see logs. I use xcode 10.1. The logs were available from Window -> Devices and Simulators -> Choose your device -> click on 'Open Console'.
This way i could see logs from extensions as well.

WCErrorDomain Code=7007 when adding localized InfoPlist.strings

I have developed iPhone app with watchOS 2 app, but I met a strange problem.
Everything is ok before I localize InfoPlist.strings of watchOS 2 target (not watchOS 2 extension target).
If I localize InfoPlist.strings, the app will get the error
Error Domain=WCErrorDomain Code=7007 "WatchConnectivity session on
paired device is not reachable."
UserInfo={NSLocalizedDescription=WatchConnectivity session on paired
device is not reachable.}.
I have no idea why. Here is my test project: https://dl.dropboxusercontent.com/u/31258390/TestApp.zip
Thanks!
I just wanted to say that I've had the same issue, and I found a radar (#23096604) detailing a similar problem:
If you have localization on the watch extension (even empty strings files), the only part of WCSession that seems to work is sending data via the applicationContext. The transferUserInfo method just queues up data and it is never sent. The sendMessage function is also unreliable in this case.
Closed as duplicate of 22682390.

Resources