I know that it is possible to localize the message and title of a push notification, using title-loc-key, title-loc-args and loc-key, loc-args. So, that the system searches for the localized-title-formatted-string(title-loc-key) in the app bundle and substitutes the format-specifiers with title-loc-args.
My questions would be that is it possible to localize the arguments of a push notification? So that the system substitutes the format-specifiers of the formatted-string with the localized title-loc-args(arguments substituted with the localized values found in the app bundle).
For example:
Notification:
`title-loc-key`= "localization_key_shipping"
`title-loc-args`= ["localization_key_headset"]
Localization En:
"localization_key_shipping" = "Your %# is ready for shipping"
"localization_key_headset" = "headset";
Can I make this work to see "Your headset is ready for shipping" ?
Thanks for all of your advices and comments.
No, your server side code is expected to feed in localized text for arguments. See Apple docs.
Look at the Notification Service Extensions. That is how you can modify the content of a push notification before is shown to the user.
https://developer.apple.com/documentation/usernotifications/unnotificationserviceextension
A UNNotificationServiceExtension object provides the entry point for a notification service app extension. This object lets you customize the content of a remote notification before the system delivers it to the user. A notification service app extension doesn’t present any UI of its own. Instead, it’s launched on demand when the system delivers a notification of the appropriate type to the user’s device. You use this extension to modify the notification’s content or download content related to the extension. For example, you could use the extension to decrypt an encrypted data block or to download images associated with the notification.
Related
We are having trouble using the new iOS Critical Alerts feature with OneSignal. The app we have is built using Apache Flex and the push notification payloads are being compiled/generated through Distriqt ANE and sent through the OneSignal iOS SDK. We have been approved by Apple for Critical Alerts but when attempting to send the payload through OneSignal, it does not work.
The Distriqt team has built in support for Critical Alerts, which is great, but once it is sent through OneSignal, the payload isn't delivered successfully and the critical alert is not generated. To be clear, general push notifications work fine.
OneSignal has documentation on Critical Alerts, though it is over simplified. The payload needed to trigger Critical Alerts on iOS is clear but there is no way to construct a payload like this through the OneSignal iOS SDK.
In the link, we have performed #1 (Update OneSignal App Payload Structure for iOS) but #2 is unclear. What does the payload need to look like? The code provided does not make that clear. Additionally, what is the referenced 'notification category extension' and if that code is identified, what are we needing to do at that point?
We have contacted OneSignal and have been unsuccessful in understanding how to successfully construct this payload. The documentation says 'iOS features OneSignal SDK supports' but from their support we received this:
Unfortunately our SDK is not setup to handle critical alerts.
One user reported he achieved this with our additional data parameter like this:
"data": {"CRITICAL_ALERT":"YES","CRITICAL_PAYLOAD":{"CRITICAL_VOLUME":"1.0","CRITICAL_SOUND":"Alert.wav"}}
Though that doesn't work. Although a relatively new feature, I am hoping someone in the community has been successful at this and can help. Thanks!
TL;DR Building an iOS Notification Service Extension is the solution. The OneSignal documentation mentions this but in far less detail.
When Critical Alerts was introduced by Apple, they changed the sound parameter that is passed through with an APNS payload. Previously, the sound was only ever a string. For example:
{
“aps” : {
“sound” : “critical-alert-sound.wav”
}
}
With Critical Alerts, it is a dictionary. Example:
{
“aps” : {
“sound” : {
“critical”: 1,
“name”: “critical-alert-sound.wav”,
“volume”: 1.0
}
}
}
The string version is still valid and is used for non-critical alerts. Based on inference and testing, when passing the sound parameter to OneSignal, it only supports the initial 'string' version. When OneSignal sends the payload to Apple, it passes it as a string thus even trying to pass a sound dictionary to OneSignal won't work because it gets parsed down before it gets to Apple. By the time Apple communicates back with your device, the dictionary is gone, thus preventing the device from ever recognizing it as a Critical Alert.
This is where the Notification Service Extension comes in. From Apple's documentation:
A UNNotificationServiceExtension object provides the entry point for a Notification Service app extension, which lets you customize the content of a remote notification before it is delivered to the user. A Notification Service app extension doesn't present any UI of its own. Instead, it is launched on demand when a notification of the appropriate type is delivered to the user’s device. You use this extension to modify the notification’s content or download content related to the extension.
In short, you can intercept the notification JSON payload coming from Apple and modify it just before the user sees it.
In order for the information to be passed to the device correctly from OneSignal->Apple->Device, you need to:
1) Set the additional_data_is_root_payload value on your OneSignal account to true. This is done through an Update an App API call on OneSignal. I used Postman for this. To be clear, this is needed to be done one time, it is not something needed to be repeated every time you make an notification API call.
2) In your OneSignal API payload, set the mutable_content parameter to true.
As mentioned above, you can use values in the OneSignal data parameter of the payload. The data payload is an open field that can be used for any additional information you want to pass through the OneSignal->Apple->Device flow and does get delivered to the device/app which you can then parse however you would like. In my example, we use:
"data": {"CRITICAL_ALERT":"YES"}
The data payload is arbitrary, it just needs to match the checks you do in the Notification Service Extension.
We then create our Notification Service Extension in XCode. There are some great step-by-step instructions here on creating an extension. This is done through XCode so if you are building a native app, it's simply done through your XCode project for your application. If you are using a framework like Adobe AIR, it is quite a bit more complicated and I will detail that in a different post. Keep in mind that the Notification Service Extension is basically a separate 'app' bundled with the parent app. It is compiled into a file with extension 'appex' and even though it is a separately bundled binary, it is specifically targeted to your parent app.
Once the extension is created, your XCode project will have a file named NotificationService.swift with a class that has the didReceive method within it. We then added this code:
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
if let bestAttemptContent = bestAttemptContent {
// Modify the notification content here...
if ((request.content.userInfo["CRITICAL_ALERT"] as? String) == "YES"){
bestAttemptContent.sound = UNNotificationSound.defaultCriticalSound(withAudioVolume: 1.0)
}
contentHandler(bestAttemptContent)
}
You can see that we check the data payload (request.content.userInfo) to see if the CRITICAL_ALERT key is set with a value of YES. If so, we add a 'critical sound' to the notification which effectively turns it into a critical alert. In this case, we kept it simple with the defaultCriticalSound function but you can also use criticalSoundNamed if you want to define your own sound. You could also pass the sound you want to use for the alert through the data payload and then parse it and add it in the Notification Service extension if you wanted to create specific sounds for specific notifications.
At this point, we tested this through the OneSignal interface once we had deployed the app to our devices. This can be accessed by logging into your OneSignal account and then going to 'Messages' -> 'New Push' and choosing the devices you would like to send the push to:
Hopefully this is helpful to others using OneSignal for Critical Alerts (and hopefully they update their system soon to no longer need a Notification Service Extension).
Is it possible to send an Apple-specific tag in an Azure NotificationHub notification custom template? I would like to send "content-available":1 to an app without switching the server to send native notifications, but I can't figure out how.
I have an iOS app using Azure Notification Hub's custom templates to send push notifications.
My template works well, until now, when I have a new type of push message where I want the app to fetch info in the background.
I know how to do this on native iOS. If I subscribe to native notifications in my app and test send this as an apple native notification from Azure:
{"aps":{ "content-available":1} [ other parameters...] }
Then the application (didReceiveRemoteNotification, fetchCompletionHandler) function gets called in my App delegate, and I can use the other parameters from the native notification to get the info, even if the app is closed or in the background.
I have two problems trying to do this in a template though. First, I can't figure out where to put the content-available parameter in the custom template.
Second, I can't subscribe to a template if I mention that parameter because "content-available" has a "-".
MyHub!.registerTemplateWithDeviceToken(mobiledeviceToken!, name: "none", jsonBodyTemplate: "{\"aps\": {\"alert\":\"$(message)\",\"content-available\":\"$(content-available)\"}", expiryTemplate: "", tags: tags)
I get this error:
PM</Detail></Error>" UserInfo={NSLocalizedDescription=Fail to perform registration operation. Response:<Error><Code>400</Code><Detail>Property name is content-available. Only ASCII-7 alphanumeric characters and '_' are permitted in the property name.
How can I send this parameter in a custom template, so that an iOS app can see it, and how do I subscribe to that template?
Or, do I have to switch to native notifications?
It looks like you should use \"#(content_available)\" instead of \"$(content-available)\". Notice that "-" is not alphanumeric character and also "#" will result "content-available":1 appears in actual payload while "$" would make "content-available":"1" which you don't want.
Here you can find a nice article about NH templates.
I am working on an app in which, I have implemented Push Notifications. Now I have to give support for Multiple language for Push notifications.
Please suggest whether, Localization for push notifications should be on App side or Server side.
And How to handle the language of push displayed on Banner when app is not running?
Thanks In Advance
This is an old question but it deserves a new answer.
Localized push notifications can be solved either server side or in the app.
To send localized notifications server side requires that the server knows the users language preference and like aronspring suggested, a good time to do that is when registering the push token.
To do it locally on the phone you need to supply all possible notifications and their translations in the app bundle Localizable.strings file. The server would then instead of sending the text to be displayed, send the key to the corresponding translation in Localizable.strings.
Example aps payload:
"aps" : {
"alert" : {
"loc-key" : "SOME_MESSAGE"
}
}
For a better explanation read more here: Local and Remote Notification Programming Guide
Like you've just pointed out, in the scenario when your app is not running the OS will receive the notification and not run any code within your app to translate them, and will display them as they are received. So they will need to be translated server side before being sent. The app shouldn't have to worry about what language they are sent in - no code needs to be written app side for this.
It might be an idea to store the device locale when you register the push token to known what language the device is set to.
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.
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.