How to change sound of iOS remote notifications without changing push payload - ios

I want to change the sound of remote notifications in iOS. But I do not want to send the sound name in push payload. I want to set it from the device itself.
This is possible in Android.
But no idea how to do it in iOS.
Please help.
Thanks,

In iOS 10 it is possible via UNNotificationServiceExtension.
You would need to send mutable-content flag as 1 in your payload. This will trigger your notification service extension to intercept notification before showing the same to the user.
You can modify content of this notification in extension's method:
func didReceive(UNNotificationRequest, withContentHandler: (UNNotificationContent) -> Void)
For further reference, link to a good introductory tutorial.

Related

Swift Cancel Push Notification Before Showing

I developed an app with Swift for IOS 10.2 . I use Apple Push Notification from server. In this app I use UserDefaults for user settings. I want that If the user wants to receive news of the day, My Application Allow showing push notification for news category. As a result Can I manage push notification before showing to user ? Do I have to keep the settings on the server ? Any suggestion ? Thanks.
Apple introduced Notification Service Extension in iOS 10. You can use this extension to modify the content of the notification sent by APNS. This extension allows you to download image/video/gif content before showing to the user or modify the content of the notification like title, subtitle, description. But, you won't be allowed to cancel the notification altogether.
Although if you save the Notification settings in Suite UserDefaults(by making use of AppGroups), you have access to those settings in your Notification Service extension and after reading from the settings you can change the content of the notification to a general notification and use API to send the notification settings to your external server and stop sending that particular notification to the client. But yes, the logic of cancelling/stopping particular notification has to be written on the server.
Hope this helps you.
Apple notification team sometimes (almost every time) takes some pretty stupid decisions, as:
Hightely attatched categories identifiers with action buttons and
Notification Content Extension, resulting in a vast and unnecessary
cartesian product of registered category identifiers on the system.
initial fire date remotion from the new UNNotificationTrigger in iOS 10
or higher.
Creating UNPushNotificationTrigger and losing all the others
UNNotificationTrigger capabilities for push
notifications.
...and not be able to cancel a push notification using Notification Service Extension is a pretty good example of it. Why do not cancel a invalid or corrupt push notification before it shows to the user using Notification Service Extension?
There is no other valid explanation for this but development team dementia or ill will.
BUT you can "troll the system"! YES!!!
Build a invalid and empty notification content and send it back to Notification Service to digest and dies choked up.
Inside your UNNotificationServiceExtension:
public override func didReceive(
_ request: UNNotificationRequest,
withContentHandler contentHandler: #escaping (UNNotificationContent) -> Void
){
self.contentHandler = contentHandler
self.content = (request.content.mutableCopy() as? UNMutableNotificationContent)
if let content = content {
print("Valid FCM received")
contentHandler(content)
}
else {
// Invalidates the notification
print("Invalid FCM received")
contentHandler(UNNotificationContent())
}
}
Take that, big brother.

How can I cancel or stop push notification from a client?

I have a webserver that sent a client a push notification. The client can intercept the push notification with UNNotificationServiceExtension on iOS 10 and change the content. Now I want to cancel a push notification from showing on client side on certain notifications. How do I do that? I tried to do
self.contentHandler(nil);
but it didn't work. How to do it?
It look like it might not be possible, but not sure. From the docs:
You can modify any of the content from the original request. You might
customize the content for the current user or replace it altogether.
You can use this method to download images or movies and add them as
attachments to the content. You may also modify the alert text as long
as you do not remove it. If the content object does not contain any
alert text, the system ignores your modifications and delivers the
original notification content.
https://developer.apple.com/reference/usernotifications/unnotificationserviceextension/1648229-didreceivenotificationrequest?language=objc
Calling the block with nil just displays the original notification?
It's now possible since iOS 13.3. You need to pass an empty UNNotificationContent to contentHandler (not nil) and add the new filtering entitlement.
// Determine whether you should suppress the notification.
let suppress = myShouldSuppressNotification(request: request)
if suppress {
// Don't deliver the notification to the user.
contentHandler(UNNotificationContent())
} else { ///...
Reference : https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_developer_usernotifications_filtering
I think the easiest way would be to send every push notification as a silent notification by default and only show the ones that you want to show. When you get a silent notification in
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any])
You check your notification and determine if it should be displayed to the user. If not, you do nothing with it. If it needs to be shown then create a local notification and display it UILocalNotification (iOS 9 and earlier) or UNNotification (iOS 10).
I should add this has the disadvantage that no notifications will show if the app is not resident in memory (because the app needs to make the silent notification into a local notification), but if you were to take the opposite tact then you have the problem that something might be shown that shouldn't be show.
On iOS 10 and above you can send you a "silent" notification:
Apple doc: configure silent notification
Then you can decide if the notification should be shown to the user, if so, just create a user notification and show it:
Apple doc: local and push notifications
#Jorge Arimany's answer is to send the silent notification to wake up devices to do something, I think it's not the solution this user wants. And I think we still will get the general notification if we do nothing in our UNNotificationServiceExtension class
Pre iOS 10: I dont think it is possible. Here are the reasons. Once when the server sends a push notification to the client to Apple APNS server to send it to the clients, you lose the control of the push notifications. This is one of the reasons apple doesn't always promise 100 percent delivery of the notifications. This implicitly tells you that the Push notifications on the iPhone is handled by the iPhone operating system rather than your App.
Even the push notifications displayed in the Apple iPhone Springboard/dashboard is not in your control.
Users can either control whether he wants to receive the notifications or not.
So i don't think you can control the notifications partly after it is sent from your server.

IOS Silent Push Notification to send custom Key/Value

I have a use case where I need to send a custom key/value pair. Please see the example below:
{
"aps":{"content-available":1},
"test_data":{"Name":"Vinay"}
}
I have done this exercise at my end but I am not able to send this, Also I have not find a clear proof where Apple restrict this. Can anybody support me on this context.
Yes Apple authorize it the silent push. In fact, Apple explain how to to so:
To support silent remote notifications, add the remote-notification value to the UIBackgroundModes array in your Info.plist file. To learn more about this array, see UIBackgroundModes.
And, in Configuring a Silent Notification:
The aps dictionary can also contain the content-available property. The content-available property with a value of 1 lets the remote notification act as a silent notification. When a silent notification arrives, iOS wakes up your app in the background so that you can get new data from your server or do background information processing. Users aren’t told about the new or changed information that results from a silent notification, but they can find out about it the next time they open your app.
-
For a silent notification, take care to ensure there is no alert, sound, or badge payload in the aps dictionary. If you don’t follow this guidance, the incorrectly-configured notification might be throttled and not delivered to the app in the background, and instead of being silent is displayed to the user.
Update:
But it seems to be impossible to have a totally silent push AND custom data. It's not well documented, but take a look at this: https://stackoverflow.com/a/36327058/2846494
Source:
https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/TheNotificationPayload.html#//apple_ref/doc/uid/TP40008194-CH107-SW6
https://stackoverflow.com/a/36327058/2846494
there is no issue with this until and unless you have configured well. For configuration details refer apple documentation. I have created a POC and it is working perfectly fine and I noticed only once issue if we are utilising Artisian SDK(older version) so it will swallow your payload and that is the only Issue what I was facing.
To be precise:
We can invoke app in background without notifying user by using silent notification. And we can send our custom data as shown in below example:
{"Data":"Vinay","aps": {"content-available": 1}}

Is it possible to modify incoming Push Notification Text on iOS

I have a usecase where a notification provider ends up sending me push notification text in a format that I'd like to change. Can I do so in the app's ObjectiveC/Swift code?
Since iOS 10, it is possible to modify the text of push notifications (unless they are silent notifications) by creating a UNNotificationServiceExtension for your application.
The extension is created as a separate Target in Xcode and provides a NotificationService class with two functions, one that allows you to modify the content of the push notification (didReceive withContentHandler) and one that notifies your application if didReceive withContentHandler did not complete in time (serviceExtensionTimeWillExpire).
For this to work, the push notification that is sent to your application also needs to be modified to include the key/value pair mutable-content with a value of 1 so that iOS knows to invoke the UNNotificationServiceExtension for your application.
Apple's UNNotificationServiceExtension Documentation
Your iOS app does not get a chance to modify the incoming push notification data before it is displayed to the user.
No you can't change the notification alert message(text), which user will see when app is not in foreground state. The use will see the same text what the notification payload contains.

How don't allow iOS to start application when specific type of push notification arrives?

I want PHP server send to my iOS application two types of push notifications:
New income message. For this push I want iOS start my application if it was suspended, show badge, play sound, etc.
New friend request. I don't want this push to start my application and I only want to handle if the app is in the foreground.
How can I achieve this? How can I handle different push notifications differently?
I'm not sure if it will work, but you should try for your 2nd scenario to send a notification that contains only custom properties. In this case there will be no alert to display, sound to play nor badge to update, so I think this notification will only reach your app if it's already running.
For the 1st scenario, send a notification with pre-defined properties (alert, sound, badge).
Application-side handling for remote notifications should start with the method in the application delegate protocol application:didReceiveRemoteNotification:.
However, in order to avoid the application launching in the first place, you need to make sure the PHP server crafted notification doesn't offer the option to launch the application.
See the documentation on the Apple Push Notification Service here:
http://developer.apple.com/library/ios/#DOCUMENTATION/NetworkingInternet/Conceptual/RemoteNotificationsPG/ApplePushService/ApplePushService.html#//apple_ref/doc/uid/TP40008194-CH100-SW9
In particular, you want to focus on the content of the aps dictionary as documented in The Notification Payload section. The aps dictionary received can badge your application's icon without opening the app at all.

Resources