Websockets vs. iOS Push Notifications - ios

Take an iOS app like Instagram. Instagram is fundementally a real-time application that updates its UI whenever a user interacts with you. For example, if someone likes your post and you are using the app, the UI is updated to trigger dopamine release and inform you that something has hapened to one of your posts. Similarly, when someone sends you a direct message on instagram, while using the app, you see the message spring down from the top, all in real-time.
In terms of implementing such real time features it is obvious that a naive HTTPS polling approach is far too inefficient. Thus this leaves two strategies:
1.) APNS Push Notifications:
When a user likes a post, sends a direct message, comments (etc.), send an HTTP POST to a backend server that will then update the database and send a silent Apple push-notification to the device of the recipient. The recipient, which is using the app, will receive the pushed payload and will send an HTTP GET to the backend server to fetch the needed data (ie. the contents of the direct message sent). The UI is updated in quasi "real-time".
2.) Websockets:
Whenever any user opens the iOS app, connect the user to the server via a websocket. This means, that all users currently using the app are connected to the server via their own websocket. When a user likes a post, sends a direct message, comments (etc.), the app sends a message to the server through the socket indicating the action. The server, before updating the database, finds the socket associated with the recipient and forwards the message through the socket to the recipient. Upon reception of the message, the UI is updated in real-time
Which of these approaches is scalable and better suited for a production environment?

TL;DR You'll love websockets + Combine framework, event driven to update your UI smoothly. APNS can be somewhat unreliable in terms of deliverability and resource/database costs, and to me is more of an information center.
Reasons to like websockets:
Decreases DB costs (e.g. finding device to send to)
You know when the user is not using the app, decreasing outbound data costs
Latency and faster practically speaking (more in depth in the websocket paragraph)
To answer the question: websockets are scalable based on your user count obviously. APNS is not server side testable in the CI, not cross platform, and not exactly feasible in terms of resource consumption.
I have a bias with websockets. But to present why I like it more, think about the efficiency given by your Instagram example.
To me, websockets == Event Driven, APNS is a simple information center.
APNS:
You sign up with APNS and you save the device in your backend. Great, every time an action is performed, like someone liking your post, query your backend, find the device that is linked to the OP, then send it outbound (which costs money if you think cloud computing costs). And you have to do that every single time someone likes your post (obviously you can aggregate, but why bother when you have websockets?). So database costs is one thing to think about. Additionally, a user could be muting their notifications. I don't have Instagram, but something efficiency wise they could have done (if not by sockets) is updating their UI based on incoming notifications for likes/hearts rather than a websocket connection. That's slow in terms of latency, costly, and unreliable if marked as spam. However, APNS has the benefit of not needing authorization unlike websockets, but...
Websockets:
When we approach websockets, you only authorize once (at least for mobile applications). You're removing outbound data costs (in terms of $$ and latency) by removing stuff like headers. You want to send small chunks of data, and sockets are just sending text/binary (I like to create commands out of them using JSON. A notable example is GitHub). When your user is done with the app, you close the connection and you don't need to send anymore data via APNS. Your server itself can be communicating with a single websocket via something like Redis PubSub in order to update your UI when someone uses a POST request to heart a post without needing to send some push notification. That's a win for the liker (who doesn't need to wait for that push notification to be sent) or the other way if you offload it to a background task (the OP doesn't need to wait). Websockets == Event Driven:
Small data chunks that are constantly delivered (as in a lot) is much better than having APNS in which it can be slow to actually deliver, especially if you're flooding Apple/your user with notifications, marking you as spam. Although, disclaimer, that's just my personal belief and speculation depending on your use case.
You're removing those unnecessary database costs.
A downside would be keeping the connection alive.
Personally, I've used websockets with the combine framework recently for a chat application, but it can be used in so many different circumstances. Updating a Facebook feed/comment section, live notifications via the websocket instead of APNS, even posting content.

APNS is not guaranteed to be delivered, especially if you have a lot of notifications - I don't remember where I read that, but after some threshold per min it'll stop working. Also, you'll have to send them to all your users, not just online ones. It's possible to send silent notifications, but it's still not optimal.
That's why websocket is a preferred way. Also you can use something like https://github.com/centrifugal/centrifugo, which is a helper for your server, that'll hold all the connections, and is very stable.

It is not one out of two, even the web-socket isn't failsafe, but all of above should be considered for an effective communication, when the app is in foreground use a web-socket to listen for any updates from the server, expect a confirmation from client when something is delivered by socket, if the web-socket connection is not active or the there is no confirmation response deliver the update through APNS/FCM, as APNS/FCM it is not guaranteed to deliver, deliver the updates when next Socket connection is successful.

Related

iOS - Push notifications and background threading

I have a service that allows user to enter the type of events they like, and whenever a new event that fits those criteria is available in my database, I want them to get a notification.
I have been looking around at the best way to handle it and I have found two possible solutions, but I'm not very clear with which one I should use and how.
First, a solution that looked great was the didReceiveRemoteNotification method and the usage of remote silent notifications to tell the app that new content was available. But my questions remains: how can I send this remote notification to the user if I don't know which criteria he has. I mean, how can I send this notification using PHP? I'm a bit lost here.
So I found another possible solution that does look a lot like a hack (iPhone - Backgrounding to poll for events), to be able to make your app execute a method every XX minutes while it is in background. This would be way more battery consuming and I'm not even sure it would be accepted by Apple, but at least it is clear as to how it works: the app downloads data from a link with the parameters that fit the special criteria, and if there is new data, it sends a notification.
How could I combine both these methods?
EDIT
I think the main issue on my side is that I don't understand how I could check a certain PHP file whenever new data is added into mysql and make sure that it fits the criteria of the user and then send the notification. That is the part that I don't understand in the backend PHP usage.
Your flow should be like this -
Mobile -> BackendServer(PHP) -> APNS server -> Notifications->Back on device.
User will submit her/his criteria to server then server will process on that and send request to APNS server.
The APNS server will send remote notification on her/his device based on criteria requested.

ROR Push Notification Engine

I have recently been assigned a task to develop a notification engine. For the notifications we are going to use Push Notification. I am looking for the best possible solution for the engine because in future we have to scale the application to other devices also. Following are some details of the project
Backend:
Backend of the application is developed in Ruby on Rails as webservices
Devices that will have push Notification
iPhone, Android, Pebble (smart watch), Web application
Current Solution:
Currently, we are thinking to make a back-end database table for notifications. A worker class in Rails will run after 1 minute and it will push all the notifications to the devices stored in the database. From the webservice methods, we will insert the data in the notification table.
For pushing notications we do not want to use services like UrbanShip. We are only going to implement them using Ruby Gems. Currently, we made a small demo based on GCM gem for android push noticiations.
Questions: Is my approach to the solution is correct ? or is there any better solution for this kind of problem.
EDIT:
I think that my previous description of the problem was a little confusing.
Ultimately we are going to use GEMS in Ruby to send push notifications. Forexample for iOS we are going to use Houston or Grocer gem and for Android GCM.
Problem: We need some database tables where we will store notifications so that the GEMS (mentioned above) can use them to send the notification to users. Now, to fill the database tables we need to write the logic somewhere so that we can insert the notification in the table.
Forexample, lets say that when a user first registers in the application we send him a notification. Now, to do this we need to write the code for adding the notification in the Register function.
like
public void Register()
{
//Registration logic
//Add a notification in the notification table
}
Now, this is a problem because we need to add the notification logic in all the functions that need to send notification. Is there any other good solution in ROR or in general ?
Some design pattern ?
I've spent a fair amount of time looking at Ruby based push notification solutions. The best one is RPush https://github.com/rpush/rpush. RPush is very well tested at this point (We use it to send millions of notifications), and handles a lot of difficult edge cases well. I wouldn't recommend building your own from scratch since there are so many potential pitfalls and edge cases. RPush doesn't support Pebble or Web App notifications, but could be extended to do so.
If you decide to explore other alternatives, make sure they:
Handle closed connections gracefully for APNS - In many cases, Apple may close the connection to their server, and your push notification library must handle this correctly otherwise thousands of subsequent notifications can go undelivered
Communicate with Apple's feedback service - Apple requires you to poll one of their endpoints for a list of devices to stop sending notifications to. If you fail to do this, you can get rate limited.
Can send notifications at a fast enough rate for your requirements.
Outside of Ruby, the best push notification libraries seem to be PushSharp (C#), and Node-Apn (NodeJS, iOS only)
Finally, it sounds like you have specific needs that require you to do this yourself. But for others, I would strongly encourage you to use a 3rd party services. Reliably sending push notifications at a high volume is difficult and there are many 3rd party services that will do it for you at low cost. For instance, UrbanAirship, Parse, and OneSignal (My service) are all great 3rd party solutions.
Update to address revised question:
The best design pattern is to have a a second daemon process or Cron Job that handles message delivery. It's not practical to try to do this inside of a Ruby on Rails application.
The RoR application can insert rows into the Notification table as a queue like you describe. Then the daemon process or cron job can fetch notifications from the queue and deliver them.
If you use RPush, this is the pattern that it follows. It comes with both a Gem to load into your Rails application that inserts notifications onto a database queue, as well as a daemon that you keep running on your server that periodically checks for new notifications to send and delivers any that get queued up.
I wonder if this question is still open or you already have a solution, but I'd like to propose this gem I've recently published: https://github.com/calonso/ruby-push-notifications
It's really simple to use, flexible enough to fit your architecture and works!
At the moment is just the gem itself, but I'm working on building a whole Rails plugin around it, with all the tables structure and stuff. You can see some work in progress here: https://github.com/calonso/rails-push-notifications
This article describes a very simple but fairly comprehensive approach to handling push notifications on your Rails backend.
In a nutshell:
Implement a Device model together with some controller actions to record users's device tokens in your DB.
Create a Notification model, which in the article is a Redis list but you can also use ActiveRecord if you don't really want to use Redis.
Create a background worker that is actively running through the incoming notifications and sending them as push notifications. The article mentions grocer and GCM to send them to iOS and Android respectively but you can also use other useful gems such as rpush, houston, etc.
Having a separate worker processing notifications is a good idea because you don't want to be constantly opening and closing connections to Apple and Google's servers with the risk of getting locked out, since it might look like a Denial of Service attack (depending on the frequency of your notifications).

iOS Push Notifications: App as Provider?

I understand the basic concept of having a provider talk to Apple's Push Notification Server which then pushes the notification to the phone. Usually, the provider is an app server running on some machine somewhere completely separate from the app.
However, we don't currently have a separate server, and don't yet need one as everything is currently handled in-app. So, is there any way we can use the app itself as the provider to send a notification to Apple's server and thus to another phone?
Basic concept: we have a game and when a user completes 70% of the level, we'd like to notify his competitors that he's close to finishing the game (or that he has finished at 100%).
If it's possible, are there any security concerns with this approach?
P.S. The app already knows who the competitors are because it displays them in a UITableView.
Technically it's possible. If you include the push certificate with your app, and you have a way to send the device token of each device to all other devices that may need to push to that device, you can push a notification directly from one device to another.
However, in practice, that would require opening and closing many connections to the APNS servers frequently (you'll need a connection for each device, and every time a device loses network connection - which may happen often - you'll have to re-open that connection), which will probably cause Apple to block your app from connecting to their APNS server (since they would interpret it a DDoS attack).
Therefore you should use a server.
For future visitors to this question: we wound up ditching Amazon SNS since we spent nearly 8 hours and couldn't get it working the way we wanted. Instead, we setup Parse Push in rough 15 minutes with exactly what we wanted to do, so I would definitely recommend giving it a look.

Best way to notify iOS app on server database updates

I am quite new into programming and I cant find efficient solution for my problem. Could someone point me in the right direction please?
I have an app which is heavily relying on server data. Data on server is unique for each user and may change every minute as well as only every few hours. Currently I am updating local data when app becomes active but I also need a way of notifying app to trigger updates when app stays in active state and data has changed on server. I thought about few solutions:
1) NSTimer set to one minute and triggering url request to check if there is new data on server. Server after comparing lastModified value would return new data if available.
I don't really like that solution as I don't want to overload my server with number of requests, especially that data in the database may change only every few hours or even longer.
2) APNS - sending notifications from server every time data will change and than update local data with server database when notification received.
It seems like a good solution but only if it would be possible to restrict remote notifications to be received when app is in active state. As far I know it is not possible and as I mentioned before data may change even every minute so I don't want to spam users with number of notifications when app is not running.
3) TCP Sockets using NSStream/CFStream?
This is something I never did before, so I am not even sure if I am going in the right direction researching about this one.
This is a hard topic in general, but more technologies are coming out to help with it. Couple thoughts on each of your solutions:
The NSTimer solution is effectively polling, which is the worst option I feel. You'd be hitting your server pretty hard for each user.
This would be a better solution. APNS now supports silent notifications, so you can send push notifications to a user without worrying about notifying them. You can send a silent notification by including the content-available key in the payload and not including the alert key. More info here: http://hayageek.com/ios-silent-push-notifications/. It is rate limited, though. You may go minutes to hours without getting a delivery, so if that's important you'd be best to go to option 3.
This is your best solution. It would require a persistent connection with your server. AFNetworking 2.0 supports this kind of connection based on Rocket. Here's Rocket's documentation: http://rocket.github.io. Take a look at server-sent events.
Hope that helps!

Receive update from web server to iOS App and synchronize data

i'm writing an app that manage a sqlite database, and i have write a web server, i want the user register in my web server with username and password, i already know how make a request from ios app to server and receive the response, but i want enable also the synchronization of the sqlite database to other device, i now that with core data i can use iCloud synchronization, but for now i prefer use sqlite, and find a way to synchronize it, for example i want create this:
make a change in the sqlite in the iPhone app;
the app send this change to the server for that user;
then the server have to send this update to other device connected at that user;
and now i can't go over, how the server can send this change to the other device? the device has to be always listen to the server? or there is a way to send this update directly to some device and handle it? like an apple push notification?
EDIT: if it's possible use an apple push notification to do this, i doesn't want alert with text sound and badge the user, but send a "silent notification" it's possible?
As a high-level there are a few different ways to approach this, all of which have pros and cons. Two name two examples you can do a polling method, active push or a hybrid approach.
Polling: at some pre-determined interval the app tries to "phone home" and send the delta db changes up to the server. Here you know that your server will be expecting X number of responses in any given interval so you can appropriately gauge your load.
Active Push: The user decides when they want those changes to be transmitted to the server by hitting a "Sync" button. This allows the user to only push data back up to the server when they know there's a change but an over zealous user may make a change, upload, make a change, upload, etc instead of queueing up a bunch of changes and sending them all at once. This may create frequently unneeded server calls.
Hybrid: You setup a polling schedule within the app AND give the user the ability to Sync at-will in the event there is a critical change that needs to be made ASAP.
Regarding the listener side of the equation you face a similar challenge conceptually. If the original user makes 20 changes and presses Sync 20 times do you bombard the second user's device 20 times as well or do you queue those changes up and send them down every 5 minutes (as an example)? Unless you have both devices paired to each other or are connected to the same network AND visible to each other via your app you're going to need to leverage that back-end server. Push notifications can be very useful in this manner but there is extra development and setup overhead to take into account to properly implement them.
To boil this all down I would recommend laying out what YOU want your syncing model to look like before you start marching down a path.

Resources