---
title: Foreground Service
description: Display a notification when running an ongoing headless task.
---

Foreground services are an advanced Android concept which allows you to display notifications to your users
when running long lived background tasks. The notification acts like any other notification, however it cannot be removed
by the user and lives for the duration of the service.

<Vimeo id="386254150" caption="Android Foreground Service" />

The service task can run for as long as required whilst the application is open, alive or killed. Once the task has complete
the service is stopped and the notification is removed. Examples of when to use a Foreground Service are:

- Capturing on-going information (such as current location for a fitness or delivery app).
- Playing media to the user.
- Displaying important information to the user, such as directions.
- Showing the status of a local device task, such as deleting files.

> Only a single Foreground Service can be running at any one time for an application.

To create a long running task, Notify Kit exposes a `registerForegroundService` method. It should be registered
outside of any React components as early as possible in your code (e.g. within the project `index.js` file).

> The Foreground Service is not persisted between hot reloads.

## Creating a service

Let's create our foreground service which we'll later hook into. The callback we register must be a promise, and is passed
a notification object when called.

```js
import notifee from 'react-native-notify-kit';

notifee.registerForegroundService(notification => {
  return new Promise(() => {
    // Long running task...
  });
});
```

Whenever you call `stopForegroundService`, the foreground service will close and the notification will be removed. The service can be
stopped by the device (e.g. low memory) or if the user force quits from the application settings.

### Attach a notification

To attach a new notification to the service, the `asForegroundService` property on the notification object can be set to
`true`:

```js
import notifee, { AndroidColor } from 'react-native-notify-kit';

notifee.displayNotification({
  title: 'Foreground service',
  body: 'This notification will exist for the lifetime of the service runner',
  android: {
    channelId,
    asForegroundService: true,
    color: AndroidColor.RED,
    colorized: true,
  },
});
```

Running this code will create a foreground service notification which is bound to the runner we registered with
`registerForegroundService` above. As our example never returns the promise, the notification will exist for the lifetime
of the application.

You may also notice we have provided `color` and `colorized` properties. When setting `colorized` to `true` on a
foreground service notification, the `color` will be used to change the entire background color of the notification,
which is not possible on standard notifications.

### Building a long lived task

To simplify the experience for developers, a long lived task will continuously run until you call `stopForegroundService`. This allows us to create intervals, or subscribe to events which we can use to update the notification.

For example, we could build a task which subscribes to an event handler:

```js
notifee.registerForegroundService(() => {
  return new Promise(() => {
    // Example task subscriber
    onTaskUpdate(async task => {
      if (task.complete) {
        await notifee.stopForegroundService();
      }
    });
  });
});
```

The example code above would show the notification to the user until a new task event with `complete` being true is
sent.

### Updating an existing notification

Foreground notifications behave like any other notification, and can display anything (progress indicators, images etc).
Whilst our service is running, we can also update the current notification to display different content:

```js
notifee.registerForegroundService(notification => {
  return new Promise(() => {
    // Example task subscriber
    onTaskUpdate(async task => {
      if (task.update) {
        notifee.displayNotification({
          id: notification.id,
          body: notification.body,
          android: {
            ...notification.android,
            progress: {
              max: task.update.total,
              current: task.update.current,
            },
          },
        });
      }

      if (task.complete) {
        await notifee.stopForegroundService();
      }
    });
  });
});
```

Above we've updated the callback handler for the `onTaskUpdate` method. Each `task.update` call would update the current notification with a new progress indicator
position. It is important we update the existing notification by ID, otherwise the foreground service would stop and restart. Only a single foreground service
notification can exist for your application at any one time.

### Handling interactions

Much like other notifications, we can subscribe to [events](/react-native/events) when the user interacts with the
Foreground Service notification. The service task runs in its own context, allowing us to subscribe to events within itself.

For example, to stop the foreground service when a user presses an action, we can subscribe to the event inside of the
task:

```js
import notifee, { EventType } from 'react-native-notify-kit';

// Create the task runner
notifee.registerForegroundService(notification => {
  return new Promise(() => {
    notifee.onForegroundEvent(async ({ type, detail }) => {
      if (type === EventType.ACTION_PRESS && detail.pressAction.id === 'stop') {
        await notifee.stopForegroundService();
      }
    });
  });
});
```

A notification can then be created with a [Quick Action](/react-native/android/interaction#quick-actions) which
triggers the event:

```js
notifee.displayNotification({
  title: 'Foreground Service Notification',
  body: 'Press the Quick Action to stop the service',
  android: {
    channelId,
    actions: [
      {
        title: 'Stop',
        pressAction: {
          id: 'stop',
        },
      },
    ],
  },
});
```

It's important to note, for background events there can only be only a single handler registered at one time. It's recommended to listen to your service events in your application's main [`onBackgroundEvent`](/react-native/events#background-events) callback handler so you can continue to listen to other events outside of the service.

### Specifying foreground service types

On Android 14+ (API level 34+) you **must** declare a `foregroundServiceType` on the library's `ForegroundService` component in your app's `AndroidManifest.xml`, otherwise calling `displayNotification({ android: { asForegroundService: true } })` will throw a `SecurityException` (the library logs an early-abort error with the missing declaration before Android crashes).

> **Breaking change in v9.1.13**: the library previously shipped `android:foregroundServiceType="shortService"` on its own `ForegroundService` component, but that default was not safe to force on every consumer (Google Play policy, 3-minute `shortService` timeout, etc.) and was removed. Each app must now pick the types that match its use case and declare them explicitly. Existing apps upgrading from earlier versions must add this declaration.

```xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">
  <application>
    ...
    <!-- Single service type -->
    <service
      android:name="app.notifee.core.ForegroundService"
      android:foregroundServiceType="location"
      tools:node="merge" />

    <!-- Or, multiple service types combined with | -->
    <service
      android:name="app.notifee.core.ForegroundService"
      android:foregroundServiceType="location|camera|microphone"
      tools:node="merge" />
  </application>
</manifest>
```

The `tools:node="merge"` marker tells the Android manifest merger to add the `foregroundServiceType` attribute to the library's existing `<service>` declaration (which has no `foregroundServiceType` of its own). You can also use the older `tools:replace="android:foregroundServiceType"` — both work.

When you create a foreground service on Android 14+, the OS verifies the app holds the matching runtime permissions for the declared type (for example, `RECORD_AUDIO` for `microphone`). If the permission is missing, the system throws a `SecurityException`. You can also scope the types per-invocation by setting `foregroundServiceTypes` on the notification — this is useful when the app has been granted additional permissions at runtime and you want to update the running service:

```js
import notifee, { AndroidForegroundServiceType } from 'react-native-notify-kit';

notifee.displayNotification({
  title: 'Foreground service',
  body: 'This notification will exist for the lifetime of the service runner',
  android: {
    channelId,
    asForegroundService: true,
    foregroundServiceTypes: [
      AndroidForegroundServiceType.FOREGROUND_SERVICE_TYPE_CAMERA,
      AndroidForegroundServiceType.FOREGROUND_SERVICE_TYPE_MICROPHONE,
    ],
  },
});
```

If no `foregroundServiceTypes` property is provided on the notification, the types are taken from the manifest.

If a new permission is granted while the service is running, posting the same notification (same `id` and `channelId`) with the updated `foregroundServiceTypes` array updates the running service with the new types.

### Controlling display timing on Android 12+

Android 12 (API 31) introduced a system-imposed delay of up to 10 seconds before a foreground service notification is displayed, to give short-lived services time to finish before bothering the user. The library overrides this by default so foreground service notifications display **immediately**, matching pre-Android-12 behavior. You can opt out via `foregroundServiceBehavior`:

```js
import notifee, { AndroidForegroundServiceBehavior } from 'react-native-notify-kit';

notifee.displayNotification({
  title: 'Deferred foreground service',
  body: 'Displayed after the platform default delay.',
  android: {
    channelId,
    asForegroundService: true,
    foregroundServiceBehavior: AndroidForegroundServiceBehavior.DEFERRED,
  },
});
```

Values:

- `AndroidForegroundServiceBehavior.IMMEDIATE` — **library default** when `asForegroundService: true`. Displays the notification immediately. Corresponds to `NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE`.
- `AndroidForegroundServiceBehavior.DEFERRED` — restores the Android 12+ deferred behavior (up to 10 s delay). Corresponds to `NotificationCompat.FOREGROUND_SERVICE_DEFERRED`.
- `AndroidForegroundServiceBehavior.DEFAULT` — framework-neutral default. Corresponds to `NotificationCompat.FOREGROUND_SERVICE_DEFAULT`.

The property is ignored when `asForegroundService` is `false` or not set, and has no effect below API 31.

### Warmup (advanced)

For latency-sensitive apps that call `displayNotification({ asForegroundService: true })` very early after process start (e.g. from a launch deeplink), `notifee.prewarmForegroundService()` pre-loads the foreground service classes and warms the `INotificationManager` Binder proxy on a background thread. It's idempotent and safe to call multiple times; on iOS it resolves immediately as a no-op.

```js
import notifee from 'react-native-notify-kit';

// Call early in your app startup — e.g. in index.js or App.tsx
notifee.prewarmForegroundService();
```

Most apps do not need this — the library warms automatically via its `InitProvider` content provider during app startup. The opt-in API is an escape hatch for lazy-loaded libraries, post-splash-screen warmup, or low-end devices where the automatic warmup hasn't completed by the first notification.
