1

I am aware that when a push notification arrives on the device (and app does not opens it), there isn't a way to check that (I might be wrong). But there is one such case in my app, where it is imperative to know that the notification has arrived the device.
I have multiple tabs in the app out of which 2 have badge implementation depending on push notification. So basically there are two different types of push notifications.

Suppose if one type of notification arrives the device and user chooses not to see the notification. That way, the badge count of a specific tab is to be incremented by 1. But the issue is, which one. Because at the time, I open the app, I don't have the information, which notification type has arrived. Or to be precise, which tab badge count is to be incremented. So in a nutshell, how do I know, notification has arrived the device (not received)?

mfaani
  • 33,269
  • 19
  • 164
  • 293
Nitish
  • 13,845
  • 28
  • 135
  • 263
  • 1
    You can pass `"badge" : count` in your notifications payload from server, wont that work? – Bhumit Mehta Jul 25 '16 at 10:50
  • @BhumitMehta : The issue is, in this case, didReceiveRemoteNotification is never called from where we get the payload, as I don't open the notification. – Nitish Jul 25 '16 at 10:53
  • 1
    Yes but badge should automatically be set if notifications payload contains "badge" key with non 0 value. – Bhumit Mehta Jul 25 '16 at 10:55
  • 1
    @BhumitMehta : That is the application badge I guess. And even if I have the badge value, I have no idea at the time I open the app, which tab badge I need to set. – Nitish Jul 25 '16 at 10:58
  • There is no guarantee you will get apns payload always. You may miss something, In somecase like if user didn't tap the notification. To make sure you have the correct badge count do a sync up with your server when your app launches. In that way, you will have an updated badge count. – SaRaVaNaN DM Aug 02 '16 at 11:40
  • Not getting your explanation of why you can't use the badge functionality supplied with apns... – Wain Aug 03 '16 at 06:48

5 Answers5

1

You might be able to solve this by using background fetch-modes for your push notifications. Storing your special badge-number to some kind of persistent storage (perhaps user defaults) and using that value when you open the app.

For background fetch, look into this question: Will iOS launch my app into the background if it was force-quit by the user?

However, be aware that the user can choose to opt out from background fetch.

Community
  • 1
  • 1
ullstrm
  • 9,812
  • 7
  • 52
  • 83
1

So basically, to sum up what others have said, you will have two user-cases. But before you'll need to specify in your payload which badge has to be increment (as @Andrew suggested). Here are the user-cases:

  1. The app can call didReceiveRemoteNotification. In that case, that means the app is in background, or in foreground or was launch by a tap on the notification. You will have to implement your logic to handle this case. Just parse the payload of your notification (in json) and determine which badge you should increment.
  2. The app cannot call didReceiveRemoteNotification. In that case, the user has killed your app, or the device is turn off or the user has block fetch background feature for your app. To handle this case you'll need more logic in your app and on your server as well. What you could do is store on the server side all pending notifications that were sent. Once the app on the user device has receive AND parse the notification (didReceiveRemoteNotificationwas called) you make a new call to your server asking to delete the notification from the pending data base. Finally, implement a call to your server asking for all pending notifications at the launch of your app, so that in the case your app was kill or the device turn off, when ever the user open again the app, he will have all notifications he missed. You could also set a timer on the server to send again a notification every x days/hours (which is not really advised, you don't want a user deleting your app because you are spamming him).

Also as others said, it is way better to trust your server on which number should be display in your badges than the notification itself. The logic above was used in a Tinder-like app I was working on lately, to display how many matches the user had ;)

RomOne
  • 2,065
  • 17
  • 29
1

There is no way to get this information using public API's.

From Local and Remote Notifications Programming Guide:

Let’s review the possible scenarios that can arise when the system delivers a local notification or a remote notification for an app.

The notification is delivered when the app isn’t running in the foreground. In this case, the system presents the notification, displaying an alert, badging an icon, perhaps playing a sound, and perhaps displaying one or more action buttons for the user to tap.

The user taps a custom action button in an iOS 8 notification. In this case, iOS calls either application:handleActionWithIdentifier:forRemoteNotification:completionHandler: or application:handleActionWithIdentifier:forLocalNotification:completionHandler:. In both methods, you get the identifier of the action so that you can determine which button the user tapped. You also get either the remote or local notification object, so that you can retrieve any information you need to handle the action.

The user taps the default button in the alert or taps (or clicks) the app icon. If the default action button is tapped (on a device running iOS), the system launches the app and the app calls its delegate’s application:didFinishLaunchingWithOptions: method, passing in the notification payload (for remote notifications) or the local-notification object (for local notifications). Although application:didFinishLaunchingWithOptions: isn’t the best place to handle the notification, getting the payload at this point gives you the opportunity to start the update process before your handler method is called.

For remote notifications, the system also calls the application:didReceiveRemoteNotification:fetchCompletionHandler: method of the app delegate.

If the app icon is clicked on a computer running OS X, the app calls the delegate’s applicationDidFinishLaunching: method in which the delegate can obtain the remote-notification payload. If the app icon is tapped on a device running iOS, the app calls the same method, but furnishes no information about the notification.

As you can see, only tapped notification is to be examined when app is starting from killed state or undocked.

Another important point is:

Quality of Service

Apple Push Notification service includes a default Quality of Service (QoS) component that performs a store-and-forward function. If APNs attempts to deliver a notification but the device is offline, the notification is stored for a limited period of time, and delivered to the device when it becomes available. Only one recent notification for a particular app is stored. If multiple notifications are sent while the device is offline, the new notification causes the prior notification to be discarded. This behavior of keeping only the newest notification is referred to as coalescing notifications.

If the device remains offline for a long time, any notifications that were being stored for it are discarded.

So, long story short, delivery & presence of push-notifications are highly expectable, but not guaranteed. Also, path of push notification on device is not to be controlled programmatically - as an app, you subscribe to APNS daemon on device and you're dependent on it in terms of push notifications.

That is why, if your app has some business logic (in you case, counters update), you shouldn't rely on push notifications. You should use more reliable / controllable mechanism of syncing data between your app and backend. I've achieved this goal few times by using REST and dedicating Notification entity in my app's problem domain - user can GET notifications, mark them as read/unread, delete them etc via REST API.

Petro Korienev
  • 4,007
  • 6
  • 34
  • 43
  • 1
    Thanks for the explanation. Makes sense. It seems that apps like Facebook, linked use private api's for this purpose. I like your approach of creating separate entity for handling notifications. Makes the functionality much clear. – Nitish Aug 03 '16 at 07:08
  • I believe, facebook and linkedin doesn't use private API's for this - AFAIK, they have separate counters for each tab (messenger, notifications, friend requests when it goes about facebook and almost same at linkedin). I think, they use REST or some websocket mechanism to get an updates and some kind of caching. If you have badges counts in Facebook app early on start - they are 99,99% obtained from the cache and then updated from the network upon network connection – Petro Korienev Aug 03 '16 at 07:52
  • Can you give more details about your last sentence: "I've achieved this goal few times by using REST and dedicating Notification entity in my app's problem domain - user can GET notifications, mark them as read/unread, delete them etc via REST API" – mfaani Jul 08 '17 at 12:16
0

You could add some parameters into json data which receive into push notification, like "type":1 to identify type of notification. See Examples of JSON Payloads. But load count of notifications from API is better then count each type of notification into app.

Andrew Bogaevskyi
  • 2,251
  • 21
  • 25
-1

You can only get notification payload information if user opened app by clicking notification or if app is open. In both case didReceiveRemoteNotification will call. Beside these case, you can call a service on server which contain notification count information when app opens.