I'm working on a chat app and I need to know when a push notification is received to reload the conversation view with the new message. It's working well if the user allows the app to send push notifications to his device (with the notification dialog). However, if he taps "No" in this dialog, the following code, which registers the user device token to my database, is not executed :
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
// Update the OneSignal id for this current installation
oneSignal!.IdsAvailable({ (userId, pushToken) in
if (userId != nil) {
let installation = PFInstallation.currentInstallation()
installation.setDeviceTokenFromData(deviceToken)
installation.setValue(userId, forKey: "oneSignalId")
installation.saveInBackground()
}
})
}
Then, how to get the user device token, if he taps "No" in the notification dialog, so I can still target him to send silent push notifications ?
Thanks!
Actually it is possible to do it but not with OneSignal.
Apple push notification does support push on the background, That means even if user doesn't grant access to notification it would just not show on his screen when he gets one.
With OneSignal the issue is that the system doesn't send a push to users who have disabled push notifications. That means that your notification won't ever reach your app because it won't ever be sent through Apple Push Service.
I suggest you use another vendor for that (it works with Parse-Server by the way).
If you want to fetch the data in background instead of using push I suggest you use "Background fetch", That would wake your app from time to time and let you run a bit of code to check if there is anything new.
Sorry mate, you can't send apple push notifications to a device if the user doesn't allow Push Notification in settings, in that case you need to follow other methods to detect change in data.
You can implement sockets. i.e UDP connection which listens to the server for any incoming messages. You need to start the connection in the chat ViewController and and if you receive a packet indicating there is a chat message, you can reload data. Also there is live messaging service such as xmpp which is kind of the same but more improved with much more chat support. Chat services like Whatsapp uses them.
Another option is to reload data every 4 or 5 seconds using a NSTimer object. Call the api in background, so the user won't know it is constantly refreshing and update if there is new data. Also invalidate the timer once you go out of scope of the chat. The one i used, used the same technique with calling the api service both in chat view controller and conversation view controller.
Related
my client wants to have an UISwitch control in Settings view in his app which is: 'Disable Notifications during night time'. He would like pushes that his API will be sending to mobile to be ignored if this option is turned on and it's a night time. Is this possible? I know that I can register and unregister for remote notifications, but this requires an App to be turned on. Is it possible to have it working like he wants?
The only way to do this is to have a configuration in the back-end. Notifications are sent from a server, and only handled in the app. There is no way, besides unregistering the phone from receiving notifications, to have the phone deny a notification in a certain time frame.
The user can set a time preference in the app, send it to the server, and have the server do a check so it only sends the notification to the user in the preferred time period.
Check out this 3rd party repo to send your push notifications and just write in your own check before pushing the notification.
https://github.com/nomad/houston
You can register or unregister for push notifications, i hope in your code switch you can make something like this:
let application = UIApplication.shared
//Didnt receive push
application.unregisterForRemoteNotifications()
//Receive push
application.registerForRemoteNotifications()
and if your client wants make this in Backend you can put a value on some database table with field receive:Bool, and the backend just take all the receive == true to send push notification on this devices
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.
Is it possible in iOS 7/8 not to show push notifications? In push userInfo I receive some data. Is it possible to check this data and show/not show this push notification? I need this when user have to logout from my application.
Sorry, You can not stop notification from being shown in notification panel. When your app is in background/terminate state. First Notification is shown in notification panel.
You can control show/hide notification in your application. When your app method didReceiveRemoteNotification is called.
You can ask your back-end developer to send some flag whether this notification should be displayed or not.
Yes,it is possible in server side.when you get notification at the same time ask server side to send save that in one web service from that you have to get and show the details to user.
In app is open that time you able get notification data in didReceiveRemoteNotification.
I have an iOS app that needs to update its content while running in foreground automatically. My app does NOT need to update if in background.
There is a existing way to do so, which is APNS(Apple Push Notification Service).
Because I don't want users to see notification message while in background, using push notification without alert or message might be a solution.
However, if using APNS, iOS would ask users to confirm if they want to receive notifications by my app. I think that users may be confused when being asked by the OS since my app does not actually push notification to users.
The current method I use is keep pulling my API every 30 seconds to see if new content is available. This method would fail if there are too many users.
Is there any 3rd party push-notification-like service that provides notification while app runs in foreground only? (no need to get notification while in background)
You can use Silent notification for that, in this
In the WWDC 2013's "What's New with Multitasking" presentation, there is a section about Silent Push Notifications. if you send the APS payload with just the content-available set to 1, users will not be notified of the notification.
And the notification arrives in application:didReceiveRemoteNotification:fetchCompletionHandler:
Your payload is like
{
aps: {
content-available: 1,
sound: "default"
}
}
In case of push notification, it is necessary for user to accept push notification on application 1st run. You can set a silent push notification also and for this user will not get any alert of getting a notification during application run loop.
If you want to avoid push notification, then you can only set a NSTimer that you are doing already.
There can be a 3rd case, Application only sync with the server when it comes to foreground. And for this you can refer to my this post.
I have a iOS 5.1 application that registers to the APNS service to receive notifications. The register is successful and I receive the notifications correctly. The problem comes when I try to handle the notifications.
Once the application is running, the method didReceiveRemoteNotification in the AppDelegate is called correctly and so the notification is handled as intended. This, however, only happens when the application is running on the foreground.
However, when the application is running on the background or is simply stopped, that method is not called. I've read that you should add some lines to the method didFinishLaunchingWithOptions method to obtain the notification from the userInfo dictionary, and handle it. This works just fine, but ONLY when the application is opened by clicking on the notification at the Notification Center. This means that if you open the application by clicking on its badge, or simply by changing context if you were running it on the background, the app never realises that a notification came in. Additionally, if more than one notification was received, we can only handle one of them at once by clicking on the Notification Center, which is a pain :-)
Is there any way to read the pending notifications in the Notification Center? I know there is a way to flush them using the method cancelAllLocalNotifications but I haven't found a way to just read them. And I really need to handle all of them. I thought of implementing a communication protocol with the third-party notification server to retrieve the information again when the application comes to the foreground, but since the information is already in the operating system I would find it strange if it's impossible to access it somehow.
So, does anybody know a way to do it? Thanks in advance.
When a push notification arrives and the user clicks 'cancel', your app has no way to read that push notification again. You have to implement a separate functionality (most probably on server-side) to fetch a list of notifications sent to this device.
For example, if a chat functionality is provided in your app and you send chat messages via push notifications then you should also keep chat messages on the server. If a user clicks 'Cancel' on any push notification then that chat message will not be displayed on the iOS device. In that case when a app comes in foreground later, you make a call to the server and fetch all the past chat messages (sent via push notification).
Ok, So a possible solution would be to have another database table with the messages in with a 'read' flag and a messageID field? Which by default the read flag is NO, then when the app successfully reads this and displays, it updates the flag to YES?
And with only 256 bytes to play with, what sort of ID field length would be necessary?
Edit,
Executed this plan and its working successfully.