Android foreground service for location
On Android, an app that reads location after the user leaves it does so from a foreground service: a service the system treats as visible to the user, with a notification that stays up while it runs. Since Android 8, almost every release has added a rule about how that service is declared, started and permitted.
The rules, version by version
Section titled “The rules, version by version”Android 8 (API 26): background limits
Section titled “Android 8 (API 26): background limits”- Apps in the background get location updates only a few times an hour. A foreground service counts as foreground, which is why tracking apps use one.
- Apps in the background cannot start ordinary services. They call
startForegroundService(), and the service must callstartForeground()with a notification within five seconds, or the system stops the app. - Notifications need a channel. Android 9 adds the
FOREGROUND_SERVICEpermission, granted at install.
Android 10 (API 29): service type and background permission
Section titled “Android 10 (API 29): service type and background permission”ACCESS_BACKGROUND_LOCATIONis a separate permission. Fine or coarse location alone means “while the app is in use”.- A service that uses location declares
android:foregroundServiceType="location". Started while the app is in use, it keeps location access after the user leaves the app, even with only while-in-use permission.
Android 11 (API 30): background location is a second step
Section titled “Android 11 (API 30): background location is a second step”- Foreground and background location requested together are both refused. Apps ask for foreground location first, then for background location separately.
- The background request has no dialog option. The system opens the app’s location permission page in Settings, where the user picks “Allow all the time”.
- A foreground service started from the background gets no location without background permission.
Android 12 (API 31): no starts from the background
Section titled “Android 12 (API 31): no starts from the background”- Starting a foreground service from the background throws
ForegroundServiceStartNotAllowedException. Exemptions include: an activity of the app is visible, the app has just receivedBOOT_COMPLETEDorMY_PACKAGE_REPLACED, or the user has exempted the app from battery optimization. - Users can choose approximate location, as long as the app asks for fine and coarse together.
Android 13 (API 33): notification permission
Section titled “Android 13 (API 33): notification permission”POST_NOTIFICATIONSis a runtime permission. Without it the foreground service still runs, but the user does not see its notification.
Android 14 (API 34): declared types and type permissions
Section titled “Android 14 (API 34): declared types and type permissions”- Every foreground service declares a type, and the app holds that type’s permission:
FOREGROUND_SERVICE_LOCATIONforlocation. startForeground()with typelocationthrows aSecurityExceptionunless the app holds location permission. With only while-in-use permission, the app has to be in the foreground at that moment.
What Long Ping does
Section titled “What Long Ping does”The service declaration
Section titled “The service declaration”Gradle merges the library’s manifest into your app:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /><uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /><uses-permission android:name="android.permission.FOREGROUND_SERVICE" /><uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" /><uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application> <service android:name="com.longping.engine.LongPingService" android:exported="false" android:foregroundServiceType="location" android:stopWithTask="false" />
<receiver android:name="com.longping.engine.LongPingBootReceiver" android:exported="false"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="android.intent.action.MY_PACKAGE_REPLACED" /> </intent-filter> </receiver></application>It also declares WAKE_LOCK, INTERNET and ACCESS_NETWORK_STATE. stopWithTask="false" keeps tracking
running when the user swipes the app away; set stopOnTerminate: true to stop it instead.
Starting the service
Section titled “Starting the service”Long Ping starts the service with startForegroundService(), and the service’s first action is
startForeground() with the notification and, on Android 10 and newer, the location type. If that call
fails, the service stops itself straight away.
- On Android 11 and newer, when the app is not visible and “Allow all the time” is not granted, Long Ping does
not try to start the service. It emits an
errorevent (PERMISSION_DENIED) and starts the service when the app comes to the foreground again. - When Android refuses a start (
ForegroundServiceStartNotAllowedExceptionon 12+,SecurityExceptionon 14+), Long Ping catches it and emits anerrorevent instead of crashing your app. A WorkManager check every 15 minutes tries again. - After a reboot or an app update, the boot receiver restarts tracking if it was on and
startOnBootistrue(the default).
So call LongPing.start() while the user is in your app, for example from an “On duty” button: that works on
every Android version, with either permission level. Restarts from the background need “Allow all the time”,
and on Android 12+ a battery-optimization exemption helps them through; see
Android battery managers.
requestPermission('always')
Section titled “requestPermission('always')”The only Long Ping call that shows a permission dialog follows the Android 11 rule:
- It asks for
ACCESS_FINE_LOCATIONandACCESS_COARSE_LOCATIONtogether, so Android 12+ can offer approximate location. It skips this step when location access is already granted. - On Android 10 and newer, if foreground access was granted, it asks for
ACCESS_BACKGROUND_LOCATIONin a separate request. On Android 11+ the system opens the permission page in Settings, and the promise resolves when the user comes back. Android 9 and older have no second step.
import { PermissionsAndroid, Platform } from 'react-native';import LongPing, { AuthorizationStatus } from 'react-native-long-ping';
// From a visible screen, after your own disclosure:if (Platform.OS === 'android' && Platform.Version >= 33) { await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS);}
const status = await LongPing.requestPermission('always');if (status === AuthorizationStatus.ALWAYS || status === AuthorizationStatus.WHEN_IN_USE) { await LongPing.start(); // WHEN_IN_USE: runs, but cannot restart from the background}The call needs an Activity in the foreground and rejects NO_ACTIVITY without one.
Permissions has the full flow and the status values.
The notification
Section titled “The notification”Long Ping builds the notification from the notification config:
await LongPing.configure({ // …the rest of your config notification: { title: 'On duty', text: 'Sharing your location with dispatch', smallIcon: 'ic_stat_location', // a drawable or mipmap in your app; default: the app icon priority: 'low', },});Each priority gets its own channel, since Android fixes a channel’s importance once it exists. Tapping the
notification opens your app; debug: true adds the last fix’s age and the queue size. On Android 8.0, where an
adaptive small icon crashes the app, Long Ping uses a system location icon. All keys and defaults are in the
config reference.
Long Ping neither declares nor requests POST_NOTIFICATIONS. Request it as in the snippet above, and declare
it in your app’s manifest, because Android only prompts for declared permissions:
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />Google Play
Section titled “Google Play”Play Console asks apps that target Android 14 or newer to declare their foreground service types, and apps with
ACCESS_BACKGROUND_LOCATION to declare background location. Long Ping’s merged manifest needs both; see
App Store & Google Play review.