We usually say that an app is “sent to the background” either when the user minimizes it, when another app is shown on the screen, or even when the user blocks the smartphone. On the contrary, the app “is in the foreground” when it is the app that the user sees on the screen.
Apps that are in the foreground are always running. Apps that are “sent to the background” may or may not run. This is because Android / iOS may not assign computing resources to the app (or even suspend/kill it).
For some apps, this is not an issue since they should only run in the foreground (e.g. wayfinding apps, where the user is expected to be interacting with the screen while being guided). For other apps (e.g. tracking apps), this will cause many inconveniences. Luckily, Situm provides mechanisms to avoid this and ensure that your apps keep up & running in the background.
Android #
As explained in the Android documentation (see Optimizing for Doze and App Standby and Background execution limits), Android may suspend your app if it is running in the background in order to increase the battery life of the smartphone. If this happens, Situm SDK will stop.
Wayfinding apps #
When a wayfinding app goes to the background, Situm SDK may stop as explained above. In wayfinding apps this is usually not an issue, because the goal is not to generate the user locations at all times.
When the application resumes, Situm SDK will not start on its own again (you’ll have to do it when the application resumes or starts again). Therefore, you’ll not be able to locate the user and show his location.
There are 2 ways to avoid this. Both are OK, the choice depends on your preferences / application use case.
Option 1 – Stop & start manually Situm SDK #
A simple way to handle this is to:
- Stop Situm SDK when going to the background by using the removeUpdates method (more details here).
- Start Situm SDK when app restarts/resumes (goes back to foreground) by using the requestLocationUpdates method (more details here).
Take into account that when Situm SDK starts, positioning may be a bit inaccurate until it converges. This can be alleviated by using the Location Cache feature.
This option is recommended if you want to make sure that user locations are never generated except if the application is showing.
Option 2 – Don’t stop Situm SDK and wait for the SDK to restart it automatically when returning to foreground #
Another option is to just wait for the SDK to automatically restart the positioning when the app returns to foreground. This will happen if the app stays more than 30 seconds in background. If it is less than 30 seconds the positioning just will continue without restarting.
Tracking apps #
In tracking apps, the fact that Situm SDK stops when the app goes to the background is a huge issue. Luckily, Situm SDK provides different ways of overcoming it.
Option 1 – Running Situm SDK as a Foreground Service (recommended) #
The first and the most recommended method is to enable the Situm SDK option that allows to run it as a Foreground Service (this option also implements other advanced configurations to maximize the chances that Situm SDK keeps running). This comes at the following costs:
- Users will see an always-on status bar notification. Starting from Android SDK 3.15.0, the notification will include a default button to stop positioning. More details below.
- Battery consumption will obviously grow, since positioning will run continuously.
This option is enabled by default. You may enable/disable it using Remote Configuration.
Less recommended, you may disable it by setting the useForegoundService() method of the LocationRequest you use for positioning. This is an example for Java Android:
LocationRequest locationRequest = new LocationRequest.Builder().useForegroundService(false).build();
Customizing the persistent notification (Android only) #
Running Situm SDK as a Foreground Service will show your users an status bar notification, as required by Android’s Policies. You may customize this notification in order to:
- Provide your users with information about why the application is being executed in the background.
- Manage interactions with the application from the notification drawer.
New features in Android SDK version 3.15.0
Starting from version 3.15.0, the Android SDK includes several new functionalities and changes:
- Tap Action customization:
A new method tapAction(TapAction) has been added to ForegroundServiceNotificationOptions.Builder. This method allows you to configure the behavior when tapping the notification. There are three predefined behaviors:- LAUNCH_APP (default): Launches the app’s main activity using the information returned by PackageManager#getLaunchIntentForPackage(String).
- DO_NOTHING: No action is taken when the notification is tapped.
- LAUNCH_SETTINGS: Launches the operating system settings screen for the current app.
- Default behavior changes:
- The Foreground Service Notification will now launch the app by default when tapped (corresponding to the aforementioned LAUNCH_APP). You may need to review the Android documentation for Activity Launch Modes if you encounter problems (or disable this behavior, as described below).
- The showStopAction option in ForegroundServiceNotificationOptions is now true by default. This causes the stop button to appear in the notification, allowing users to stop positioning at any time. You can use your LocationListener callbacks to handle LocationStatus.STOPPED statuses in such a case (or disable this behavior, as described below).
How to customize
You can further customize the persistent notification using the methods provided by ForegroundServiceNotificationOptions.Builder. Here are the available methods:
- title(String title): Sets the title of the notification.
- message(String message): Sets the message of the notification.
- showStopAction(boolean showStopAction): Specifies whether to show the stop action button in the notification.
- stopActionText(String stopActionText): Sets the text for the stop action button.
- tapAction(ForegroundServiceNotificationTapAction tapAction): Configures the action to be performed when the notification is tapped.
Example usage:
ForegroundServiceNotificationOptions options = new ForegroundServiceNotificationOptions.Builder() .title("My App Title") .message("My App is running in the background") .showStopAction(true) .stopActionText("Stop") .tapAction(ForegroundServiceNotificationTapAction.LAUNCH_APP) .build(); LocationRequest locationRequest = new LocationRequest.Builder() .useForegroundService(true) .foregroundServiceNotification(options) .build();
Alternatively, you can also choose to provide your own Notification to the foregroundServiceNotification() method of your LocationRequest:
LocationRequest locationRequest = new LocationRequest.Builder() .useForegroundService(true) .foregroundServiceNotification(notification) .build();
For more information on these topics, please refer to PendingIntent and Building a notification.
Option 2 – Running Situm SDK from your own Foreground Service #
The previous option may not be adequate for your app. For instance, your app may need to execute another Foreground Service to run your own code, and you may not want to show two status bar notifications (Situm’s and your own). If this is the case, you may run Situm SDK in your own Foreground Service, provided that you declare its type as “location” (see the Android docs for more details).
In theory, this should have the same effect as the previous option. Be aware, however, that we still recommend the previous option (run Situm SDK as a Foreground Service), since this applies some other configurations to maximize the survival chances.
Option 3 – Running Situm SDK from a background service with the ACCESS_BACKGROUND_LOCATION permission (not recommended) #
There’s a way to allow apps to run in the background indefinitely without showing the user the always-on status bar notification: you may achieve this if the user grants you the ACCESS_BACKGROUND_LOCATION permission. However, we do not recommend this method because this is a highly sensitive permission and, so according to Google guidelines you will need to justify why you need it before publishing your app in Google Play.
Encourage the user to open your app #
In case the system closes the app, there will still be ways to re-launch it. In case it does not open it, there might be ways to do it. Some common ways:
- Push notifications. With Firebase Cloud Messaging you can remotely send notifications to a user who has your app installed. Keep in mind that the notifications should be sent at appropriate times and not spam them as it can cause the users to ignore them.
- Geofencing. You can monitor geofences and notify the user when they are near a building you use in your app. With this API you will receive updates of when a user enters, stays in or leaves a geofence. This is a great way of prompting the user to use your app because you know that they are in the location where your app is intended to be used. Although this seems like a great option you should know that geofencing is not always reliable and there can be times when the app is not notified despite being inside a geofence. Also you should know that you will need the permission ACCESS_BACKGROUND_LOCATION.
- The Work Manager allows you to execute tasks periodically. You can use this to execute small portions of your code and notify the user when you see it convenient. You might want to try to check the user’s location (using Android’s standard location APIs) but this is not guaranteed to work at all times.
- QR codes or marketing campaigns. Another effective way to achieve new users for your app is to display QR codes (e.g. “Scan to know where you are”) or marketing signage promoting your app.
Please note that these are not silver bullets. In our experience, the OS may still kill your app discretionally or these mechanisms may not work well in all situations / phones / OS versions.
iOS #
As Android, iOS doesn’t allow apps to compute while they are on the background unless you take some things into account.
Wayfinding #
Contrary to what happens in Android, when the app goes to the background iOS usually doesn’t kill / suspend it, and Situm SDK doesn’t stop. It just “freezes” (no processing takes place) and when the app goes back to the foreground, Situm SDK is able to resume without re-starting. This is due to how iOS works.
Anyway, just as in Android, you may call the requestLocationUpdates several times but it will only start positioning once (unless you change the LocationRequest).
Tracking #
Background constant execution is a bit trickier iOS than in Android. In order to achieve it, you’ll need to configure your project to run in Background mode as explained in Apple Docs (another way of achieving the same outcome is to add the UIBackgroundModes to your Info.plist). This will allow to keep the application running in the background forever (or at least, for long periods of time).
This mode requires a special permission (allowBackgroundLocationUpdates) that has to be approved by:
- The user: as any other permission.
- The App Store: before distribution. Apple evaluation includes, among other things, a verification of the reasons why the app wants access to the user’s position (e.g. they should be in the legitimate interest of the user).
It’s important to take into account that while iOS offers this mode, the Operating System might introduce discretionary limitations to the background execution of the app, reducing its performance or even killing it. There is not much information available about this, but an important factor will be the battery consumption of the app: the higher it is, the higher the change the OS might kill it. This is specially true if the “Battery Saver” mode of the OS is activated.
Our experience at Situm is that iOS apps can run for hours/days with the appropriate permissions. Eventually, the system may close it, but there are ways to alleviate this.
Encourage the user to use the app #
In case the system closes the app, there will still be ways to re-launch it. In case it does not open it, there might be ways to do it. Some common ways are:
- Significant Change of Location and Visits. The Visits service monitors locations visited while the Significant-change service tracks major location changes using less power. According to Apple docs, you might be able to re-launch your app using these service.
- Region Monitoring. Allows apps to perform limited actions in response to a user entering or exiting predefined geographic areas (e.g. showing a notification), even if the app is terminated.
- Push notifications. Local notifications in your app are triggered based on specified conditions such as time or location, while remote notifications are generated by your server and delivered through Apple Push Notification service (APNs). You may prompt the user to take certain actions such as opening your app.
- QR codes or marketing campaigns. Another effective way to achieve new users for your app is to display QR codes (e.g. “Scan to know where you are”) or marketing signage promoting your app.
- See the article “About the background execution sequence” for other ideas on alleviating this potential issue.
Please note that these are not silver bullets. In our experience, the OS may still kill your app discretionally or these mechanisms may not work well in all situations / phones / OS versions.
Alternatives to the Apple Store regarding app distribution #
There are essentially 4 ways of distributing an iOS app:
- App Store. This is the standard way. Keep in mind that Apple needs to aprove your app. If your app needs to run in Background Mode, you will need the apropriate permissions and Apple will review your app to decide whether it grants them.
- Enterprise App Store. This is a private store that allows large organizations to develop and deploy proprietary, internal-use apps to their employees. In principle, Apple will not need to approve your app or the permissions it asks. The usage of this program is restricted to large organizations (100+ employees), for internal apps only. More details here.
- TestFlight. This is a private channel designed to distribute beta versions of apps to internal & external testers (up to 10000 external users). Apps can be accessed during 90 days (after which you need to re-upload them & users need to re-download them). More details here.
- Signed IPA. Just like in Android you can send APKs that users can download & install in their phones (e.g. over email), in iOS you can send IPA files with the same purpose. The caveat is that the app needs to include the Apple ID of all the smartphones where you want it to run. Therefore, if you want to send the IPA to a new user, you will need to include the Apple ID of her smartphone in the app’s source code & recompile.