I cannot seem the have my head around this. APNS as stated in the documentation has best-effort delivery, i.e. delivery is not guaranteed. However, if I am to use the push-notification model in my client/server application, I have to use them somehow.
The general model looks as follows: there is new data on the server -> the server then sends a push notification informing the client(s) that there is new data available -> client downloads new data.
The question is then, if I cannot rely 100% on the notification to be delivered, what kind of fallback mechanism can I use so that I can ensure that the client receives the new data available on the server ? What is the way to ensure that the client has the most-up-to-date data using APNS ?
What is the way to ensure that the client has the most-up-to-date data using APNS ?
There is no way to do this with just APNS. Your client needs to query your server when the app is brought to the foreground to see if there is new data, regardless of any push notifications you may have lost or received.
It all depends on how you are planning on using APNS.
Lets say you were making an App that sold items like eBay. You have:
- bids being placed by multiple users
- countdown to item closing time
You would not use APNS to update the timer on the persons device or notify them of the current price of the item. These are too crucial to rely on a best-effort delivery and was not the intended use of APNS.
It would be best if, in this scenario, you had the app poll the server every X seconds for updated information. You could then user APNS for non-crucial features like notifying the user if they are outbid or if they have won the item.
Related
Suppose I have an e-commerce ios app (like snapdeal, flipkart etc.) and I want to make my app notified when there is any change in the data stored on the server.
For instance, take an example of price change of any product in any category, so how can I update the price for that product without putting it to user's knowledge, whether the user is on that particular screen (currently seeing that product for which the price is changed) or on any other screen.
is it possible to do? if YES, how can I achieve that?
Thanks in advance!!
You have to use Apple Push Notification Service to do that.
It allows your server to send data to your app, that warns user or not (you choose), and your app is awake by this push a can work on background mode.
In order to allow you app to work in background, you have to enable Background fetch options
From Apple Background execution guide :
Apps that need to check for new content periodically can ask the system to wake them up so that they can initiate a fetch operation for that content. To support this mode, enable the Background fetch option from the Background modes section of the Capabilities tab in your Xcode project. (You can also enable this support by including the UIBackgroundModes key with the fetch value in your app’s Info.plist file.)
Edit about BaaS
As mentioned in comments, implementing the whole push notification system yourself can be difficult, especially if you are doing it for the first time.
That's why you can use a BaaS (Backend as a Service) that handle push notification for you like Parse.com, Firebase or whatever you want. It simplify a lot the process, but it remains APNS on the back, so it's important to understand how it works.
I'd recommend, like Mr. Blackus said in his answer, to use Apple Push Notification service. However, I will add one bit of information -
Don't use the service to send the actual data, only send a small packet of information telling your application to request more data from the server.
The process should be something like this:
Server asks Apple service to send Push notification to your app.
App receives push notification (but does not show any badge to the user).
App interprets the data sent from the server as a "refresh data" notification.
Fire POST or GET request upon determining type of notification received.
Update your data from the request response.
1.) Polling - app asks for list of products whose prices has changed. You can setup a timer, which triggers itself after every X seconds.
2.) Socket connection - between app and the server. App can generate a unique token (such as identifierForVendor), and use it in the socket conenction. Server can notifiy all the apps (using this token), to notify about the changed prices.
Approach 2 is better, as it is less expensive ( in terms of networking).
Hope this helps.
How can an iOS app be notified that it needs to update its content?
I would like to have an app that listens for update alerts that trigger a download rather than doing a data request to be able to stay in sync with the server.
What is the correct way to have an iOS app that needs to be in sync with a server stay in sync while minimizing network activity?
Im aware of using a cache locally, NSURL Cache or Core data etc. and adhere to the timeout in the http header etc. but I would like to correctly setup a sync mechanism without having an update button that a user needs to press to get updates.
I have thought of implementing a dispatch_source on a socket but wont that keep the network active and drain battery?
Rather than request a token for the version of the data to sync from the server I would rather like the server to notify the device that it needs to update. Is this practical?
How does the OS handle listening to push notifications? Is it on POSIX level?
You really have two options here:
Client Side Polling: call the server and ask every so often. For 99% of apps this is fine as it's not that big a deal for someone to run the old version during the interval between polling.
Real-time Server Push: If for some reason you need to disable the old version as soon as you push a new version, you could do a server side push. You would not want to use APNS for this (user may deny APNS, delivery not guaranteed, etc). You would want to use a cheap push service like PubNub or Pusher for this to guarantee real-time delivery. Or code you own version using the same principles of these services, but really why re-invent the wheel?
There are two common, as far as I am aware, approaches to doing this on iOS;
Regular GetUpdates calls to the server at an interval (Fairly standard across any platform I think)
Apple's Push Notification Server(APNS) if anything changes on the server you can push a notification to the device.
At work we typically implement both options because there are a few issues with APNS;
They are not guaranteed to reach the device, if the device is offline the APNS service will store the Notification for a limited time in the APNS system upon which it is forwarded (if it hasn't expired)
If multiple Notifications are sent while the device is offline only the most recent notification is sent
If the device is offline for a long enough period of time all stored notifications will be discarded
the user has to allow Push Notifications to be sent to their device because it suppliers and identifier that you can use to determine the device
I'm currently struggle with annoying store-and-forward function limitation of APNS. Here is a quote from the Apple docs:
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 application is stored. If multiple notifications
are sent while the device is offline, each new notification causes the prior
notification to be DISCARDED.
I specifically make ALL CAPS for the keywords of my problem. In Google Cloud Messaging notifications service their store and forward function have much more capabilities:There is a limit on how many messages can be stored without collapsing. That limit is currently 100. If the limit is reached, all stored messages are discarded. - so Google service can store up to 100 push messages for a max time of 28 days. And in addition to this they have also coalescing (collapsible) notifications but for 4 different collapsible messages. And in APNS all we have is - one recent
notification for a particular application is stored - it is quite a limited behaviour for my app (I need to store at least four different push notifications while the device is offline at one given moment of time).
So I'm interested are there some ways I can improve store and forward capability of APNS?? Can I in some way make APNS to store more push notifications for a specific device?Or at least store several coalescing notifications as in Google collapsible messages? Some third party solutions or whatever? May be I missed something in APNS docs? I know we can orchestrate apple push notification on google platform - but I think it is not a solution because of its unjustified complexity.
As you found yourself in Apple's APNS docs, there is no way to store more than one notification per application for a single device. If you want to compare it to GCM, APNS server acts as if all notifications have the same collapse key.
No third party solutions can work around that, since Apple doesn't return an acknowledgment of delivery to the sender of the notification, so the server (whether it's implemented by you or by some third party provider) has no way of knowing which messages to store and resend (assuming that all the messages are valid and were not rejected by APNS server).
Apple Push Notifications are not intended to deliver important data. Their purpose is to notify the user of the app that new data is available at the server, which allows the app to load that data if the user chooses to open the app. That's the reason why they don't store more than one message per app for the same device.
I need to update my users for things that happened around their current location while the app is in the background.
To my understanding:
If my server sends a Push Notification to a client, the client would immediately show that message.
I can set up the app so that there is a specific location, with a given radius could fire a message.
So what I want to understand if it is even possible to update my users about things that are new in their locations.
I was thinking of two possible solutions, I am not sure they are possible.
One, I guess if the Push Notifications would allow a function to run prior to its display,
deciding if the message should appear.
For example: something happened in area x,y - The server initiates a message to all devices. Only the devices within range of x,y and a radius z, would show the message to the users.
Maybe the Regional Monitoring service can send a message to my server and my server can then decide if to send a Push Notification back to the client...
For example
The user has entered a defined location, determined by the app. The app sends a message to the server. The server decides if a message is due.
Any ideas? is that even possible?
Filtering push notifications by topic is something you need to do on the server side, not the client side. Apple specifically states not to send messages to users that aren't relevant and you won't be able to block them when the app isn't running. Additionally, if you are using a service to manage your push notifications you don't want to pay for messages that aren't relevant.
So when you register a device into your database, you should register what topics that person is subscribing to (ie. save a list of topics that user is eligible to receive). Then when the event is triggered that generates the push notification only send to devices that are registered to that topic. I believe a number of push platforms have this capability already built in. On UrbanAirship and Azure Notification Hubs you can use their tags feature. Or you can develop it yourself if you do your own push server.
Take a look at Parse. They have this kind of functionality baked right in, just send the push to clients that match a geoPoint query.
I want to create an iOS chatting app using APNS. If I have 10,000 active and they are continuing chatting, will apple block my developer account ? Is there any limitation regarding this?
I would discourage you from using APNS as a backbone of an "chatting app".
If you need fast chatting functionality you should write your own TCP-socket based server.
If every-few-second syncing is o.k. you can get away with a HTTP-based server backend (but all the pull-syncing can be hard on network traffic - so TCP-socket is still better choice).
You could however use APNS for fallback - when your app on certain device is not responding (i.e. is not connected to server) you can send an initial message trough APNS (to wake up your app & to notify the user there is a message waiting for him).
As soon as the user opens your app you should switch back to your TCP-socket or HTTP request based server communication.
As for your question: no, Apple would most probably (one can never know for sure) not reject your app just because of using APNS for chatting. But note (as the others said allready): messages between two users will get "lost" if they would interact too frequently - see the link Roman Barzyczak gave you.
"If you are sending multiple notifications to the same device or computer within a short period of time, the push service will send only the last one."
more information: http://developer.apple.com/library/ios/#technotes/tn2265/_index.html
but Apple wont block your developer account :)
You can use them for messaging but you are going to quickly find out that there is no guarantee they will arrive. This is known as the black hole of push notifications. ;-)
I like this answer here.
First try to use an APNS only solution.
Make your push notifications stateless (they only serve as "Hey you have some new stuff in the server").
So when the client gets a push notification it asks the server for new data (messages or other stuff).
Use OneSignal to simplify the code that sends push notifications (from the back-end). If a user in your app gets a message after 10 seconds he dose not care if you used TCP,socket.io or xmpp...
Even Whatsapp's messages can take couple of seconds to arrive.
A chat app is not a realtime game. A delay of couple of seconds will be acceptable by end users.