Check availability of server backend periodically in the background - ios

In my iOS App, which depends on a server backend, I want to offer the user a periodic check, whether the backend is available after the app failed to connect to the backend.
In most cases this should not be necessary, but in case there is a server problem my iOS shopping app can not proceed and right now just displays a view with very little information, which is available offline, and a button to "Try again" until the server is (hopefully very soon) available.
Now I would like to provide a better UX and make the button a "Notify me, when the shop is back online"
The idea is to check the shop server in periodic intervals and once it is back online to send a local notification to the user.
Now I might register for a background task, to download data in the background and inform the user about "new content", which might even not require a local notification.
That would be a UIBackgroundMode with a value of "fetch". But I have doubts, if that's a good approach. In 99.9% of the cases it will never happen and I also only need that background task, IF the server is not available AND IF the user taps on "Notify me". The docs however look like, this background fetch will ALWAYS run in the background. And that is not what I want.
How do other apps go about this problem? That should be a common task, isn't it?

Related

Schedule UILocalNotification based on changes to Core Data

I'm making a simple app with a Today Widget extension that logs events.
The user can tap a button in the app or the related Today Widget to log an event. These events are saved with Core Data any time the button is pressed either place.
Whenever a new event is logged in the app, I run a function called updateLocalNotificationsFromCoreData(). It handles the setup of UILocalNotifications based on the most recent event in Core Data after clearing the appropriate existing notifications.
However, when a new event is logged from the Today Widget, I can't use this function because I need to register the Local Notification with UIApplication.sharedApplication().scheduleLocalNotification(), and UIApplication is not available in the Today Widget extension.
I realize I'll probably need do something unconventional or hacky to get this working, so I'm trying to evaluate possible approaches and come up with a relatively robust solution.
Basically, I want to find a way I can call my
updateLocalNotificationsFromCoreData() function right away any time a new event is logged.
If I can't do it every time an event is logged, an alternative would be to trigger the updateLocalNotificationsFromCoreData() function periodically (somewhat frequently) another way. Here are some solutions I was thinking about using, but I don't like any of them:
Do it in AppDelegate when the app is launched (or another state change)
One approach I'm thinking about is running my updateLocalNotificationsFromCoreData()function in AppDelegate somewhere, like didFinishLaunchingWithOptions.
The downside is that it would require the user to open the app periodically. If the user didn't open it much the notification behavior would be inconsistent. I'd prefer a solution where a user could interact with only the Today Widget and reliably get Local Notifications without ever opening the app.
Sync the events to a server and use Push Notifications
I've thought about syncing the data in Core Data to a server, then setting up Push Notifications to the user's phone based on that.
I don't like this, because I want the user to still be able to get notifications without an Internet connection. It also introduces a lot of extra overhead of syncing the data with a server.
Ping a server, and send a content-available Push Notification
When someone logs an event with the widget, I could ping a server. That server could send back a silent content-available push notification to trigger the app to run updateLocalNotificationsFromCoreData() in the background.
I found a similar question (Scheduling local notification from within a Today extension) where one answer proposes a similar solution. Unlike the previous solution, an Internet connection is not needed to receive the notifications, but an Internet connection would be required to make sure the notifications are up to date when a new event is logged.
Background fetch
I thought about using Background Fetch to fetch something arbitrary from a server, then run the updateLocalNotificationsFromCoreData(). This would be a way to trigger the update in the background, although it seems silly to fetch data if that data isn't being used, and seems like something for which an app could be rejected. There also seems to be a risk of the system not calling the background update regularly if the user doesn't open the app much and mostly uses the Today Widget.
Use background location updates
This seems like the dumbest approach, but I thought I would mention it anyway since I thought about it. I could use one of the low accuracy background location update modes to trigger updateLocalNotificationsFromCoreData().
It would require the user to allow location in the background, which would be hard to explain. And, it would require the user to at least move around a few blocks to trigger the function, which could provide an inconsistent user experience. Also, it would increase power consumption of the app for a silly reason.
I'd really appreciate fresh ideas about how I might be able to reliably schedule local notifications when Core Data changes on a device that doesn't have an Internet connection!
Or, if that doesn't seem possible, I'd appreciated feedback on which approach seems to make the most sense.
EDIT: I came up with a new solution. It's not ideal, but I think it's better than these other approaches I was considering. When someone taps the button to log the event, I launch the full app. It's annoying because I have all the data I need at that point to give the user feedback and log the event within the Today Widget without launching the app, but by launching the app I have the opportunity to check and schedule local notifications.
Also, in iOS 9 the annoyance on the user is slightly minimized because the system-wide "back" button will appear and let the user go back to the previous app easily once my app has launched from the Today Widget.
In the future I may try a solution where one of the server-based approaches above is used when an Internet connection is available, and I would then fall back to this system of opening the app only when the network connection is not available and I need to schedule the local notifications within the app.

How do bring my App "up to date" - background fetch?

I am looking for a good way how to make my app "upToDate". These are my requirements:
I have an RESTful Webservice, with tasks for different users. Every user has an iOS App, which should get automatically updated when the Server/Service assigned a task to that User.
So first ill created a manuall "Sync" Button, which checks for new Tasks. Fetches the data with Alamofire, and updated the UI.
But, my goal is automatically sync if there are new tasks.
So, ill guess there are 2 different ways to solve that:
1. Make a Background Fetch (with a NStimer?) every xx Minutes and check if there are new tasks.
After checking that tutorial here:
http://www.raywenderlich.com/92428/background-modes-ios-swift-tutorial i am not sure if a background fetch is a good way to solve that. In that case the App uses an scheduler, to check once for new updates, and not every xx minutes.
So in my case i would create an NStimer in the AppDelegate (maybe in applicationDidEnterBackground) and check every xx minutes for new data (but when there are 3 days not any new task, that would be unnecessary battery consumption, or?)
2. Using Push Notifications.
My other idea is to use Push Notifications, so when there is a new task, ill send a Push Notification an manually start the sync. In my opinion that would use less battery, because he will only start the sync when there is a new task available.
Generaly Questions about using Background Services
So ok, if the user finished the task, some data should be automatically uploaded to the server. Normally not a problem, with the manual sync ill check if there is something to upload. But, what if, when there is no internet connection (ill check if before uploading) - and the user do not press on "manual sync".
So i would prefer to check in my "Background Service" if ill got an Internet connection, and if yes - start uploading some data.
Ill know this is not a specific question, but ill think there are lots of users who have the same requirements and it would be great if someone can help me out whats the best way to solve that in the best and practical way.
Thanks in advance!
Background updates sound wonderful until you realise that Apple throttles them heavily: you can ask to be updated as frequently as possible, but iOS decides what that value actually means based on how often users open your app and when they do so. Apple considers background updates the kind of thing that should happen just before a user opens your app so the latest content is right there, rather than something that runs proactively in the background.
Your push notification solution is a better one, particularly if you use CloudKit to subscribe to record change events using CKSubscription and CKNotificationInfo. If you do this you'll automatically get push messages in your app, so you can get what you want with very little work. You can read my tutorial for more information on subscribing to CloudKit to get push messages.

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.

How can I determine if an iOS device has come back into Network coverage if the user has closed the app?

We are building an enterprise class Work Order application where the users will often be in areas with no network coverage. We want to be sure that when they come back into coverage, any work that they have done on locally stored work orders is sent back to the server ASAP. This is easy to do if the user keeps the app running, but in our situation it is very likely that they will switch between apps, and the Work Order app may not be running when they come back into coverage.
We have thought of having the app fire an email to a server side listener when it senses that it is out of coverage. When the device comes back into coverage, the email should get delivered, and the server can send a push notification to the user to open the app. This feels like a bit of a hack... is there a better way to handle this situation?
As you already noticed, push notifications is the way to go, but even with them its not guaranteed that the user will send the data or even open the app.
I would suggest that you make the data itself expire after a limited time and alert the users when they minimize or even close the application.
You can also use local notification to alert about expiration.
So long as this is an enterprise application that doesn't have to be distributed through the App Store, you can abuse the audio background processing mode to keep your application running at all times. All you have to do is play a silent audio file on a loop as if you were a media player. This will keep your application running in the background, where you can retry connections to the server as you'd like.

Would my application be accepted in the app store if it used location as a UIBackgroundMode?

I have a requirment for an application to be capable of having information pushed to it from a server while it is in the background (this information will get displayed to the user, but it should be downloaded first before the user knows it is available therefore Apple Push notifications cannot be used - because with this mechanism a) the user would get the notification from the push server b) they will accept and launch the app c) the app will do a http fetch from a server. Thus there could and probably would be a delay while the client fetches the data, however it is a requirment that as soon as the user is informed there is new data it is instantly available).
A possible way this could be achieved is if the client periodically polls the server to see if there is anything for it (yes I know that's not ideal, polling never is, but is there an alternative?).
However polling could not be implemented unless the client has the ability to execute in the background. And the only way the application can execute in the background is if its a voip/music/location/newstand application.
The application would make use of location awareness sometimes, however location is not is primary focus (the application would be a means of information being pushed/displayed to the user, some of the information, but not all, may be dependant upon location i.e. moving to some area might trigger some information to be displayed).
If this application was submitted to the app store with a UIBackgroundMode of location, would it be accepted? Does an application's main functional focus have to be location based in order to execute in the background with this mode, or is it acceptable for location to be secondary side functionality?)
I don't have an account to access it, but the App Store Review Guidelines should give you a hint. Keep in mind that they are guidelines, i.e., Apple can for any reason deny your app. No one here can definitively say if they'll take it or not.

Resources