📜 ⬆️ ⬇️

Work iOS App in the background

There was a task for the program to send the current coordinates via a web socket at a user-specified interval. In addition, the program should work in the background and if the user or iOS for some reason unloads it from memory, it is desirable that it restarts and continues to work in the background.
The task should be solved only by means of iOS without changing the server part (no Push Notifications).

Sending coordinates by timer when the program is minimized to the background is no problem, for this you can use background location mode to get coordinates and long-running tasks for timers.

But since iOS does not have such charms as Android Background Services, then if you manually end the program, the code stops running. Therefore, the main difficulty lies in how to run the program as quickly as possible in the background, so that it continues to perform its task further if it has been unloaded from iOS for some reason, or if the user has rebooted the device, or if he manually “killed” the program.
')
Now that helped solve this problem in an acceptable way:

- VOIP background mode
When this background mode is enabled, iOS restarts the application after the device reboots or if the program was for some reason unloaded from the iOS memory itself.
Also, if the program is minimized to the background, this mode tells iOS that it does not close the socket of the connection marked with the NSStreamNetworkServiceTypeVoIP flag.
Example:

[NSStreamInstance setProperty:NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType]; 

But if the program is manually unloaded from memory by the user, then it closes with a zero exit code, and then iOS closes the connection socket, and the program does not restart after that.
As practice shows, iOS just does not always restart the program if it was unloaded from the memory of iOS itself.

- Significant-change location
Restarts the program in the background of the coordinate change event if it was unloaded from memory. The method is not entirely reliable, since it is difficult to predict in which case iOS will launch the program in the background, this can happen both immediately after the program ends and after a significant period of time (especially if the device is not touched).
This service is enabled by calling the method:

 [CLLocationManagerInstance startMonitoringSignificantLocationChanges]; 

- Region monitoring location
Allows you to specify the region for the input or output from which iOS will monitor and wake the program in case of these events.
Therefore, as an additional measure, when the user unloads the program from memory, by the applicationWillTerminate event, we set the region for tracking with the center in current coordinates and a radius of 5 meters (some minimum value). And when the user departs, as practice shows, somewhere 100 meters from the center of a given region, iOS restarts the program for the didExitRegion event.

This method works much more accurately and more reliably than significant-change location.
Example:

 @implementation AppDelegate - (void)applicationWillTerminate:(UIApplication *)application { CLCircularRegion* region = [[CLCircularRegion alloc] initWithCenter:userLocaton.coordinate radius:5 identifier:@"wakeupinbg"]; region.notifyOnEntry = YES; region.notifyOnExit = YES; [CLLocationManagerInstance startMonitoringForRegion:region]; } @end 

- Local Notifications
It is used to notify the user if the program is suddenly unloaded from memory and is not restarted.
It works like this:
1) Local Notification is set which will ring after 10 minutes
2) Set a timer that ticks every 7 minutes and checks the remaining time before the Local Notification ringing
3) If the remaining time to Local Notification is less than 4 minutes, the program deletes the current Local Notification and installs a new one (point 1)
4) If, for some reason, the program is unloaded, the timer will not be executed, Local Notification will not be reset (point 3 will not be executed), Local Notification will ring at the designated time and if the program is not opened, it will ring every minute and notify the user that The program is unloaded from memory and it must be started.

Some important points of using these approaches:

- Do not forget to enable the Background modes in the project settings, the tab “Capabilities:



- You need to add the NSLocationAlwaysUsageDescription field in info.plist:



- After creating the CLLocationManager, you need to request permission to get the coordinates from the user:

 [CLLocationManagerInstance requestAlwaysAuthorization]; 

- In iOS9, you must enable getting coordinates in the background for the CLLocationManager object:

 if ([CLLocationManagerInstance respondsToSelector:@selector(setAllowsBackgroundLocationUpdates:)]) { [CLLocationManagerInstance setAllowsBackgroundLocationUpdates:YES]; } 

A test project that you can run and see in more detail how this solution works - here lies: github.com/vaskravchuk/BGModesTest
The same application with a similar solution (only without voip) is on the market: Track-kit .

PS The customer uses the Apple Developer Enterprise Program, that is, the program will not be tested by Apple, because possible difficulties with this are not taken into account.

PSS If you have information on how best to solve the problem of keeping the program running in the background, I will be very happy.

Source: https://habr.com/ru/post/271505/


All Articles