CloudKit subscriptions and UNNotificationServiceExtension - ios

So in iOS 10 you can now write notification service extensions that "intercept" push notifications so that you can download stuff and handle them before displaying them to the user.
However they require that the push payload has the 'mutable-content' key in aps set to 1. CloudKit subscriptions do not seem to return this key in the userInfo dictionary (At least CKDatabaseSubscription doesn't), and so the service extension doesn't get called.
Is there a way to get CloudKit subscription notifications to work with UNNotificationServiceExtensions?

This is now possible in iOS 11, look for the shouldSendMutableContent property in CKNotificationInfo

Currently, this does not appear to be possible.
(There is a post on Apple's forums where a developer suggests that someone create this as a feature request. Someone already did, I plan on duplicating the request.)

Related

FCM Notifications not arriving on iOS

This bounty has ended. Answers to this question are eligible for a +500 reputation bounty. Bounty grace period ends in 5 hours.
Scorb wants to draw more attention to this question.
I have a cross platform flutter app. I am using FCM to send notifications and they are not arriving on the iOS app in any state (foreground, background, terminated). I am testing on a physical device.
The notifications work on Android, so I know the topic subscription and send code is correct.
I have followed these steps for configuration defined here...
https://firebase.flutter.dev/docs/messaging/apple-integration/
To verify I have:
added and initialized firebase using google-services-info.plist.
created and added my APNS key
created the app identifier in the Apple Developer center and confirmed it matches my apps bundle id (and added push notification
capability for the identifier.
added push notification capability to the app in xcode
added background fetch and background remote notification capabilities to the app in xcode.
It seems like I have addressed every step to configure FCM on iOS. But none of my notifications arrive.
When the app is minimized, no system tray notification is triggered, and when in the foreground the FirebaseMessaging.onMessage is never triggered, like is is when on Android.
An important note is that this is the second iOS app added to this project, and the first iOS app works correctly. Though there is no indication that there are any special steps for a second app.
We saw a similar problem (for a native iOS app) where FCM would deliver to one app in the project but not the other. The mistake we made was not repeating the configuration in Firebase for the other apple bundle id since each app in our project has a different bundle id. Given it works for one of your iOS apps but not the other on the same project, it sounds like you've got the same issue.
Also, a good diagnostic step is to use the Firebase Console to manually send off a Push Notification to a particular app. It means you can then discount errors further upstream in your backend that may not have caused FCM to be invoked.
Have you tried to send testing notifications via firebase console?
You can log your device token in your app.
Background notification must work if you have done correct with firebase and APN settings despite without implementing some methods of AppDelegate file for remote notification on the next step.
Your question is very blur to have a specific answer but you can separate your concerns to find the issue and then try to resolve that:
1. Make sure about the APNs configuration
First, try to send a notification to your iOS app, directly using the APNS key. If you get the notification, it means you have configured the APNS correctly
2. Make sure about the firebase setup
Check with both the Android and iOS app and see if there are connected to the firebase console. You can use the real-time event to confirm that.
3. Make sure you have implemented the correct methods.
Firebase and apple have different methods for push notifications. Make sure you are implementing the correct one. Also, it may vary based on the configuration file of firebase. search for iOS firebase swizzling for more information
4. Make sure you got the right permissions from the user
You should get the notification permission from the user before trying to show any notification. Make sure you've done that
Note that you may have already tried some of these but I've mentioned them for the sake of completeness. Hope it helps you and others.

Critical Alert support on OneSignal not working

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

CKSubscription not working if record owner is self

If I create a CKRecord using CKDatabase.saveRecord, no CKSubscription notification is triggered when that record is inserted by myself. Apparently I only get notifications if somebody else inserted a record, but I'd like to uniformly receive notifications, regardless if the record was created by me or somebody else.
Also I didn't find a mention about this behavior in the docs.
I tried for ages to receive notifications after creating the record on the same device, but it only finally worked if i created an artificial record in the dashboard.
Is there a flag to change this behavior?
You only receive subscription notifications for records created, deleted or modified off the device. If you insert/change/delete a record on your device you need to handle this directly.
From the Cloud Kit Quick Start guide (emphasis added)
Test Subscriptions
You can initially test subscriptions by running your app through Xcode and using CloudKit Dashboard to create, modify, or delete records, as described in Add, Modify, and Delete Records. Then fully test subscriptions by running your app on multiple devices. Use one device to make changes and another device to receive the subscription notifications. You use multiple devices because a notification isn’t sent to the same device that originated the notification

Fetching data from server & adding notifications

I am working on an app which fetches student info from a server, like absences and events and grades. I have no access to the server, I only have the API.
I am asked to implement push notifications in the app, such that if a teacher marks a student absent, that student get a notification about that. I searched and found several approaches:
1- Background fetch: I tried using background fetch to check if the student logged in to the app was marked absent today, if yes, show a local notification. It worked when I simulated w background fetch, but never worked on the physical device.
2- I searched for using Apple Push Notification Service, and they all wanted me to build a server, and I dont know how to start. Can I build a server which pushes notifications to devices in a way facebook does it? That is, one user triggers a notification at another user, in other words: I dont want to use broadcast notifications.
3- Using third party, like backendless, firebase or any alternatives. Would that be a useful approach?
With Backendless your app (on the student side) can register itself to receive push notifications. This is done with an API call that registers the device on the servers provided by Backendless. Then you would build an additional application (could be a browser web app or a mobile app) for the teachers. The system allows to send targeted notifications, so when a student is marked as absent, you could use the API to deliver a push notification specifically to the student's device. Would be happy to discuss in detail, you can post your question to the Backendless support forum.
For my app I have designed Push service using Java APNS library.
Or You could use Microsoft Azure Mobile services to push a notifications to devices.

How can we notify mixpanel to send push notification programatically in ios

I have an app which is using Mixpanel. In that app I am using push notification. I could able to send the push notification manually to the registered devices list from Mixpanel profile.
My requirement is user can set reminder for persons who are in his phone book contact. Those persons should get the push notification who are using my app and accepted to recieve push notification. How can I do this if this is possible ?
I did not get any reply to this post. After that I asked to support Team. This is the reply to my question.
What is the use of People Analytics? Can it help to notify Mixpanel to send push notifications? if so how?
People Analytics is a platform that allows you to generate lists of user profiles in Mixpanel and compile unique attributes to it. For example, I created a profile for myself, where my favorite music is classical here. I can then aggregate all users who's favorite music is classical, and send a targeted push notification to them. The goal with Mixpanel People Analytics is to help you deliver targeted notifications to your users. So it's definitely the right platform to help you send push notifications through! Here's how you start storing user profiles, and here how is how you set up push notifications.
How can we send the reminder note to Mixpanel which will be send as push notification to the concerned person?
All through the UI! Through Mixpanel, you set up the push notification to have it look exactly how you want (here) and then you define the targeted criteria of users you'd like to reach.
How can we notify mixpanel to send push notification to the particular person ?
Once again, as long as you can identify those users through the unique attributes (for example, all users who's favorite music is classical) you can send them those notifications (here).
Mixpanel JQL API enables your to retrieve user device tokens via the properties $ios_devices and $android_devices. Using Apple APN and GCM endpoints, i guess your could push your own notifications via your own code with this (i've managed to retrieve the tokens, havent tried actually pushing my own way yet).

Resources