CORE JSC

International Technology Partnership

React Native

Fixing React Native Foreground Service Crashes on Android 14 Due to a Missing Service Type Declaration

A background location tracker or music playback service that has worked reliably for years suddenly crashes with a MissingForegroundServiceTypeException the moment a user's device updates to Android 14. Nothing in the app's own code changed; Android 14 simply started enforcing a declaration requirement that used to be optional.

Core JSC Team·September 27, 2026
React NativeAndroidAndroid 14Foreground ServiceDeveloper Tools

The Problem

A React Native app runs a foreground service — background location tracking, ongoing audio playback, a persistent upload — using a native module or a library like react-native-background-actions. This has worked without issue across multiple Android versions. After a user's device updates to Android 14 (API level 34), the app crashes as soon as the foreground service starts, with a stack trace pointing to MissingForegroundServiceTypeException or a similar security exception. The app's own code, manifest, and dependencies haven't changed — the crash is entirely a consequence of what Android 14 itself now requires that earlier versions didn't.

Why It Happens

Android 14 requires every foreground service to declare a specific type, and enforces it at runtime, not just at manifest-validation time

Prior to Android 14, declaring a foreground service type in the manifest was recommended but largely optional in practice; the system didn't strictly enforce it. Starting with Android 14, the platform requires every foreground service to declare an appropriate android:foregroundServiceType (such as location, mediaPlayback, dataSync) and throws a runtime exception if a service starts without one — turning what used to be a soft recommendation into a hard requirement that surfaces only on the newer OS.

Some foreground service types additionally require a specific runtime permission that older code never requested

Certain service types introduced or tightened in Android 14 — location in particular — require the app to hold the corresponding permission (ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION) at the moment the service starts, not just declared in the manifest. An app that already requests location permission through its normal runtime-permission flow can still crash if the foreground service itself starts before that permission has actually been granted, or if the permission check wasn't updated alongside the type declaration.

Third-party libraries handling foreground services may not have been updated for Android 14's stricter requirements

A library wrapping foreground service creation on the app's behalf needs its own native code updated to declare and pass the correct service type — an app can't work around this purely from the JavaScript side if the library's underlying native implementation hasn't been updated to target the new requirement.

This is easy to miss in testing if the test device or emulator hasn't been updated to Android 14

Because the crash is specific to devices actually running Android 14 or later, a team testing primarily on slightly older devices, or an emulator image that hasn't been updated, can ship a release that appears to work fine in QA and only crashes for the subset of real users on the newest OS version.

The Fix

1. Declare an explicit foregroundServiceType for every foreground service in the manifest

<!-- AndroidManifest.xml -->
<service
    android:name=".LocationTrackingService"
    android:foregroundServiceType="location"
    android:exported="false" />

Adding the appropriate foregroundServiceType attribute — matching what the service actually does (location, mediaPlayback, dataSync, and others Android defines) — satisfies the manifest-level requirement Android 14 now enforces at runtime, not just validates statically.

2. Add the corresponding permission and specify the type when starting the service in code

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
// Starting the service (native Android code)
ServiceCompat.startForeground(
    this,
    NOTIFICATION_ID,
    notification,
    ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION
);

Beyond the manifest declaration, Android 14 introduced type-specific permissions (like FOREGROUND_SERVICE_LOCATION) that must also be requested, and the service start call itself needs to specify the matching type constant — both pieces have to agree, or the runtime check still fails even with a correct manifest entry.

3. Verify runtime permission is actually granted before starting a location-type foreground service

if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION)
        != PackageManager.PERMISSION_GRANTED) {
    // Request permission first — do not attempt to start the foreground
    // service until this actually returns granted
    return;
}
startLocationForegroundService();

Checking the actual granted state of the relevant runtime permission immediately before starting the foreground service — rather than assuming an earlier permission request in the app's flow is still valid — prevents a timing gap where the service attempts to start before the permission grant has actually been confirmed.

4. Update any third-party foreground service library to a version with confirmed Android 14 support

npm outdated react-native-background-actions
npm install react-native-background-actions@latest
# Check the library's changelog specifically for Android 14 / API 34 foreground service type support

Confirming the library's own release notes mention Android 14 foreground service type handling — rather than assuming any recent version covers it — avoids updating to a version that still lacks the underlying native changes this specific requirement needs.

Why This Works

Each fix addresses a different layer of what Android 14 now requires that earlier versions didn't enforce. The manifest type declaration satisfies the platform's static requirement; the matching runtime permission and start-call type constant satisfy the dynamic, code-level requirement introduced alongside it; verifying the permission is actually granted before starting closes a timing gap that a declared-but-unchecked permission can't; and confirming library support ensures the underlying native implementation actually knows about the new requirement, which no amount of correct JavaScript-side configuration can substitute for.

Conclusion

A foreground service crashing specifically on Android 14 isn't a regression in the app's own code — it's Android 14 enforcing, at runtime, a service type declaration that earlier versions treated as optional. Declare an explicit foregroundServiceType matching what the service does, add the corresponding type-specific permission and start-call constant, verify the runtime permission is actually granted immediately before starting the service, and confirm any third-party foreground service library has been updated with genuine Android 14 support rather than assuming a recent version already covers it.