I'm working on a messaging app and I have a dilemma about how to send data from server to client.
I'm using a centralized server design, where clients uses NSURLConnection to send messages to the server, the server doesn't keep and manage open sockets and can't send a message for one of the clients. So clients use a timer and query the server every 2 seconds to see if new data is waiting for them.
The problem with this approach is that polling the server every 2 second seem to kill the battery very fast, so I thought maybe instead of clients polling the server, to use APNS* so when the server has some new information ** for the client, the server will send a push notification *** to the client, then the client will fetch the data from the server.
* use APNS - if client allows it, client can of course disable this option. So I will check if push allowed every time the app enter foreground and if not I'll return to the polling approach.
** New information can be anything from text messages to server admin messages. (and there are a lot of admin messages...)
For example, in my app users can see their friends status (online/offline), so if user1 and user2 are friends, and user2 just change his status from online to offline, then server needs to send this new info (admin message = user2_offline) to user1.
*** The push notifications server sends are empty (with no data/sound), it's just a trigger for the client to fetch the new info, so if a push was sent to the client and the client app was close, he will not notice anything. (if the app is running, then it will fetched the new info from server)
Will this approach work with a massive messaging app requiring massive push notification uses?
To be clearer my main concerns are:
1. Is APNS reliable enough that I can use it as my core server-to-client messaging mechanism?
2. Will apple approve potentially thousands or hundreds of thousands push notifications a day from my server?
Is APNS reliable enough that I can use it as my core server-to-client messaging mechanism?
NO. Just for the sake of being complete let me iterate over the reasons.
Apple itself disclaims the reliability read the Programming Guide
Also, APNS, has a QoS component which may increase the reliability at the cost of being realtime (For Eg. I can ask APNS to deliver the notification anytime within 4 weeks and retry if devices are not reachable) which is not useful in your case.
As per your requirement, if you send a silent push (a push with no user visible message), it can not be sent as a HIGH priority push which decreases the reliability even further. Here is a relevant quote
"Silent notifications are not meant as a way to keep your app awake in
the background, nor are they meant for high priority updates. APNs
treats silent notifications as low priority and may throttle their
delivery altogether if the total number becomes excessive. The actual
limits are dynamic and can change based on conditions, but try not to
send more than a few notifications per hour."
Will apple approve potentially thousands or hundreds of thousands push notifications a day from my server?
Generally, APNS will not have any issues with this in terms of load, but it has throttling in place and they might throttle your notifications, see point 3 above
IMHO, you should look at XMPP as this protocol is designed just use-cases like yours and they have wide community support on all platforms. I will suggest you look at something like https://github.com/robbiehanson/XMPPFramework and setup an XMPP server at your backend which will handle the messaging and presence messages as well as admin messages.
If you have already evaluated XMPP and do not want to go with it, I would suggest you need to put together an intelligent system in iOS App which employs different strategies based on App State, something like following, you can have following strategies
A Realtime Socket based approach -> Establish a permanant socket connection and keep the data in sync as much as possible (This is when your app is running into foreground or background)
The Polling System You talked about in question, which can be utilised when your app is invoked for background fetch/location updates etc.
Use APNS with user visible messaging + custom data, when your server detects that the device does not have active socket and also have not polled for a very long time
I have worked in this area for a while and from my modest experience I think your approach to solve your problems will reach you nowhere. Allow me first to highlight some important facts on the APN characteristics:
APNs are not reliable, they are not 100% guaranteed to reach the client.
As of Apple's documentation, APNs are best effort, so many times they might not reach.
APNs don't hold data inside them, so even if they reach your client app they hold nothing inside them for the app.
APNs are just notifications for the user that something related to your app has occurred, while there message (the text that appears in the Alert Box of the APN) is handled by the iOS and not your app. This is why devices with iOS 4 will display the APN in a different way than devices with iOS 5, it is OS job not your app.
The badge value that appears on your app icon when notifications come is the responsibility of your server, and not the device OS. Put differently, when an APN reaches the device it should come having the new notification count value for your app. The OS won't do anything for this.
Having said that I would like to explain a bit how usually such applications are designed. First, it is not done by URL Connections and the clients don't check the server every period of time. Usually you have a client/server architecture where your client is the app on the device and the server is a real server program that resides on a server machine. The server could be Microsoft (using C# for example) or MAC (using Objective C). The server has a database that it stores information inside it. Some important information (related to your question) is the APN Count Value, the Message that you want to deliver, the state of the client if online or offline.
When a client likes to send something to another client, or when the server wants to send something to a client (or all the client), a check is made to the recipient client to see if he is online or offline. If he is online the message is sent directly, and usually the communications are done on TCP Sockets. If the user is offline then the server will store the message that needs to be sent to the client, increase the APN Count value, send an APN to that recipient. When that recipient becomes online, the server will notice that (because there is establish connection and handshaking) and therefore will fetch all undelivered messages from the database and send them to him...
It is a long process, I hope I was able to explain things a bit to you. In all cases I don't think your way is practical or enables you to reach real work.
Related
I am writing a messaging app in Swift where people can chat similar to how text messages or other popular chat apps work. The supporting API is on AWS, written in C#.
There are some points of interest here:
Hoping to avoid third party stuff like Firebase, etc, but open to listening to advice
Alert notifications are not desired for now - no popups, banners, etc. Simply want to show message bubbles arrive in real time on one viewcontroller - if and only if the person is staring at the message screen. If they're somewhere else on the app, nothing happens.
We don't want to prompt the user to ask them if they're OK with this app sending notifications because we're not sending them banners or anything visual, aside from a new chat arriving. Is that a requirement with APNS? I feel like this means someone can say NO, and then we have no way to update the chat app in real time, which won't fly.
I assume a simple approach would be some sort of timer/loop that runs from the message viewcontroller, where every second or two it hits the API and asks if there are new messages, but that seems inherently wrong to me - the app must be robust, and there could be thousands or hundreds of thousands of people using this - that's a lot of API requests, and in many cases there could be no new messages, thus a wasted call. This is clearly not the way to go, correct?
Question # 1
I was thinking, then, that I should use APNS, however am not sure if it requires you to prompt the user to ask them for permission to receive anything from Apple? Again my concern is the chat bubbles should come in at real time and don't want to give the user the ability to somehow not see these (breaking the app)
If APNS is the way to go, and I must prompt them, then I assume the flow is I will gather my device ids (created in appdelegate, saved in my C# db, and associated to each message thread) and whenever someone types a message, it goes to my API, I save it in the message database table, and then I send out a message to APNS to everyone's device id.
Apple queues this up, and sends to everyone, and if they're on the screen, then the message comes in.
Is this how I should leverage APNS to achieve what I want?
Question # 2 I've seen others recommend using SNS (in conjunction with APNS) however I don't understand why. Doesn't APNS both act as a proper queue, as well as a notification service, thus invalidating the need to use AWS's SNS/SQS at all? It seems redundant to me but maybe I just don't understand the idea behind why you need both technologies.
Appreciate anyone's time in advance if they can shed some light on this for me!
Thanks!
Question 1
Even if you're using WebSockets (As #stevenpcurtis mentioned), you still need to inform user about the fact that user received message when application is in background/suspended. And yes, you must "force" your user to enable notifications for the application and explain why he needs it. Empirically, if user installs messenger, he understands what are notifications used for and why he enables it.
Question 2
From the mobile perspective SNS will still deliver Push notifications when user receives notification while the application is in background or suspended. From the backend perspective you can use SNS.
Conclusion:
From the mobile perspective you have 2 modes:
Application is active - it's generally up to you how to receive messages. (Web Sockets, pushes, e.t.c.)
Application is in the background or is suspended: You need a tool to inform user about changes without having a control on application. This is the job for Push Notification Service. The way you will send pushes from the backend is up to you.
You can also check This question to get some more information.
I am trying to write an iOS app that will notify the user on price changes of products I access as JSON information via an API. I want to have a background task that will repeatedly check the server every n minutes for new JSON and send the user a notification if certain conditions are met. What would be the correct way to do this?
As previous posters mentioned, this is better done server side rather than via polling. However, using Apple Push Service to notify the client device is not the ideal solution. The issue is that delivery is not guaranteed (per Apple) and you cannot confirm delivery. The user could decline push notifications, Apple could decline to send the notification if you are sending too many, etc. You are much better off using a service like PubNub or Pusher, which push notifications to the client in a reliable way and both have iOS APIs. They are very inexpensive. If you wanted to reinvent the wheel and save money, you could look up how they work and write your own version.
You could of course do client side polling, in which case an asynchronous NSOperation is particularly well suited (it will run on a background thread and you can post notifications to NSNotificationCenter when things change). You can find out more about how to implement that here.
This does not work well. Here is a probably better solution:
Set up a server that polls the JSON data source.
When the data source changed, use Apple Push Service to notify the user.
Upon receiving of the notification, start a background fetch session.
I want to create an application which will be notified by server for new events. (lets say I have a shop and I need to inform all my iPhone users for my sales or something like this) Users who will download my application and run it and then put it in background wil have to be notified by this. Im quite new to iOS and Objective-C but if im not wrong this could be done via apple push notifications. Ive been reading about this and found out there are some providers that let you send this notifications. My question is, are there ways to create your own notification "center" in lets say c# and send notifications to iPhone-s by yourself, also if this could not be done are there any free providers?
and another thing. In objective-c app you have to subscribe your app to listen to that kind of events. Could you create app in phonegap or some other technologies so it will work with notifications? could you lets say embeed your app in objective-c (like web app in objective-c)
For sure you can do your own C# program that will push APNs to your clients (in fact I did that myself in many apps). What you have to understand is that the architecture of APN has 2 critical facts:
APNs are best effort, so no guarantee that they will reach every time.
APNs can not hold a lot of information with them when they reach your client (they have a limited number of bits, refer to the Apple documentation).
Due to these facts you might need to have your own server application (also could be in C#) that will handle sending the real information to the clients and will make sure that the data reached your client as well. Needless to say, this server application should sit and run on a real server. Maybe due to this fact some developers start looking for a third party solution, but personally I prefer not to use a third party and I do everything myself.
Other than having your own server application, your iPhone app will need to have some sort of database (probably SQLite3) to store the received news and display them later on.
EDIT: Answer of your questions in the comments below:
For the first question "why iPhone app must have sql db". In fact it is not a must, as I said in my answer above, it is probable or a possibility. To know if you will need a database or not this depends on the nature of your app itself. For example you might be pushing text and images to your clients and in that case you can not fit such data in the payload of the APN. Another possibility, you might want not to lose the sent notification even if the user discarded the APN message, you might want to show it again when he opens the app later on... So the nature of the app decides whether you will need a server or not.
For the second question "you said you dont need to send notification via third party", let me clarify something in my answer. As an Apple developer I don't consider Apple servers as third party. Put differently, the real APN will only be sent via Apple servers and we can not change this fact (nor do we want to change it too). So at the end of the day the real APN will be sent to Apple servers and Apple servers will work on delivering it to the actual client. What I consider a third party is someone that has his own server, you send the message you want to him, and then he sends it to Apple servers. In that case there is someone between you and the Appl APN servers and this is what I called a third party, and this third party can be avoided as your C# code can directly connect to the Apple APN servers and ask it to send the message to the client. I hope I clarified my point.
Yes, you can use APNS with the phonegap application: Receiving push notification on PhoneGap for iOS
Regarding the server, there is another option for you besides doing everything from scratch. You can use the third-party server via API, seems that pushwoosh (http://pushwoosh.com) guys offer this option (and they provide phonegap integration as well)
I am using Titanium to develop an iPhone application, in which has a small chat component between the iPhone users (not SMS, but actual client-server chat)
This is my approach: my back end will be in ASP.NET, every time a user sends a message, it will store [message_id, from_id, to_id, message_content], and then the receiver will have a timer that refreshs every 5 seconds to pick up new messages from the ASP.NET server database.
But this raises a concern. If I keep doing a refresh every 5 seconds, it will constantly stream and exhaust the receiver's bandwidth. Is there a better to way to implement a listener/receiver when there is a new message?
I have heard of socket programming but is it a good approach for this situation and how do i get started with it?
Thank you
You won't just use bandwidth, you'll eat up battery power too. Use push notifications instead.
It would be advisable to use push notifications only for when the application is running in background, not for when the user is actually chatting. That's what push notifications were designed for in the first place.
Polling the server via http is a good solution and there are techniques to save bandwith that you can use such as updating the frequency of the polling depending on user activity (no chats since a few minutes, reduce the polling time to 30 seconds).
You cannot use push notifications for a chat application because you cannot obtain so many notifications per minute to make the chat appear to be in real-time. And a simple http poll to a server can be as small as one binary package and not affect the user's bandwith significantly.
Why don't you just use Apple's push notification system?
Whenever a user receives a message your back end can send a push notification to the iphone and the iphone either downloads new messages whenever it receives a push, or if the message isn't too long you just send the message directly in the push notification
How are push notification better than pull notification on iPhones?
Are there any links with more information about this?
Any help would be appreciated.
Pull notification requires the user to be running your app, and your app to be wasting battery power constantly polling some server (or waiting on some network socket in another thread , or using the new background services).
Push notifications, when enabled by the user, and if the phone has a network connection, allows a message to be sent to a phone even when it's not running your app, prompting the user that your app wants some attention. It uses a much lower power network connection than any frequent polling method.
If you want to know about push notifications, I'm guessing you are interested in the Apple Push Notification Service.
You can read about its architecture here:
http://developer.apple.com/iphone/library/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/ApplePushService/ApplePushService.html
There is no such thing as a "pull" notification, but using APNs gives you the advantage that you don't have to manually poll a server every so often within an app, which usually saves you a lot of battery life in the long run if you are interested in telling the user about sporadic, infrequent events. Using push notifications also allows you to interrupt the user if they are not currently running your app, which of course can be very useful in certain use cases.
You should think about what kind of message flow you expect to see between your app and any server components in your system. Push notifications make the most sense where some event external to your app is going on which requires the app to be updated in some way, and where the frequency of those updates is low or highly variable.