Search code examples
iosapple-push-notificationsbackground-process

How to get notifications in background and data synchronization


I have here some requirements and now I want to check if these requirements are possible and how they could be reached. It is about notifications and running in background:

  • The app should show notifications if new data is available and the app is in background (if the app is not running there should be no notifications)
  • Also the app should synchronize the data so that the data is up-to-date
  • The user should be able to choose an interval when the synchronization should take place (5 seconds, 30 seconds, ...)
  • The app should run on iOS 6 and above.

Notifications:
The problem with local notifications is that you only can set seconds, minutes, hours ... as interval. It is not possible to set a custom interval. But this type would only be appropriate if I have a background task, which searches for updates and if an update is available, it immediatetly displays a local notification.

Remote notifications on the other side needs an additional server for the notifications. Also the port 5223 has to be open to receive the notifications (but most of the time cellular network is used and here the port should be open). How many remote notifications can be send and presented to the user? For local notifications it is 64.

Running in background:
Only in iOS 7 Background Fetch and Remote Notficiations are available. The problem with the Background Fetch is that only small data should be transferred and the OS determines when the app gets a timeslot (own algorithm which learns from the user). Sources reports a max. execution time from 30 seconds, but I didn't found an official statement from Apple.

Remote Notifications also seems to need a provider. But here the user would get a notification and the app could download/sync the new data in background (again max. 30 seconds).

What about iOS 6?

Another option would be to let the app run in background / have a background thread which checks for updates/synchronize at a certain intervall and than creates a local notification. But how long does the app run in background? I read about 5 seconds which would be to short.

And another one would be to use push notifications and if the user starts the app it does the synchronization process.

beginBackgroundTaskWithExpirationHandler seems not to suite here for my case.

How would I get notifications when running in background together with synchronization?


Solution

  • As you probably know, backgrounding on iOS is rather limited. iOS will not let your application just run in background indefinitely. If you use beginBackgroundTaskWithExpirationHandler, your app will get some background runtime (10 minutes on iOS 6, 3 minutes on iOS 7), but you can't "renew" that time while app is still background. Thus, your second option ("let the app run in background / have a background thread which checks for updates/synchronize at a certain interval") isn't practical unless you are willing to abuse other backgrounding modes (which is likely to fail AppStore review process).

    Starting from iOS 7 it became possible to send "silent" push notifications (i.e. ones having content-available set), e.g. notifications that will be delivered directly to the app (instead of displaying alert and only launching app only when user confirms it). This makes important difference for backgrounding and is quite convenient actually. Whenever your app receives such push notification, it can check for new data, sync data, etc (you get around 30 seconds of runtime). Apple claims to throttle "silent" push notifications, but not much details on this. In my practice sending them every 15 minutes seem to work.

    You may argue that 30 seconds is way to little to sync data. That's true. To solve this iOS 7 introduced background downloads and uploads that you can initiate via NSURLSession configured with [NSURLSessionConfiguration backgroundSessionConfiguration:]. Download/upload will then be handled by the system and once it completes your app will be woken to handle it.

    To the best of my knowledge this is the best approach you can take for regular data synchronisation from background apps. This won't work for iOS 6, though.

    Alternatively, if your server can decide if new data is available and if user should be alerted, traditional push notifications should be sufficient. In this case there's no need for your app to run in background and check for new data (server can do this and send remote notification with an alert/sound). This will obviously work on iOS 6, too.