---
title: Notification
description: Update the Android notification
---

# Notification

When you listen for background location, a notification is displayed on Android. This methods allows you to update the notification.

```dart
Future<bool> changeNotificationOptions({
  String? channelName,
  String? title,
  String? iconName,
  String? imageName,
  Uint8List? iconBytes,
  Uint8List? imageBytes,
  String? subtitle,
  String? description,
  Color? color,
  bool? onTapBringToFront,
})
```

`iconName` is the name of the small icon to display.
It should be in the `res/drawable` folder with the same name. By default, the library gives you a transparent icon.

`imageName` is the name of a large image shown on the notification (the Android
"large icon"). Like `iconName`, it resolves a drawable in `res/drawable` by name.
Leave it `null` (the default) for no image. Android only.

Both are resolved at runtime by *name* (`Resources.getIdentifier`), not by a
compile-time reference. Android's release-build resource shrinker only sees
resources referenced directly in code/XML, so it can strip a drawable that's
only ever looked up by its string name — showing up as a blank/transparent
icon in release builds while working fine in debug. If that happens, tell the
shrinker to keep it by adding a `res/raw/keep.xml` to your Android app:

```xml
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
    tools:keep="@drawable/your_icon_name,@drawable/your_image_name" />
```

See Android's [shrink, obfuscate, and optimize your
app](https://developer.android.com/build/shrink-code#keep-resources) guide for
details.

### Setting an icon without a drawable resource

`iconBytes`/`imageBytes` are an alternative to `iconName`/`imageName` for apps
that don't want to manually add a drawable resource to their Android project
— e.g. to use one of Flutter's own `Icons` instead. Render it to PNG bytes at
runtime and pass the bytes directly; when both a name and bytes are provided
for the same icon, the bytes take precedence.

```dart
Future<Uint8List> iconDataToPngBytes(IconData icon, {double size = 24, Color color = Colors.white}) async {
  final recorder = PictureRecorder();
  final canvas = Canvas(recorder);
  final painter = TextPainter(textDirection: TextDirection.ltr)
    ..text = TextSpan(
      text: String.fromCharCode(icon.codePoint),
      style: TextStyle(
        fontSize: size,
        fontFamily: icon.fontFamily,
        package: icon.fontPackage,
        color: color,
      ),
    )
    ..layout();
  painter.paint(canvas, Offset.zero);
  final image = await recorder.endRecording().toImage(size.ceil(), size.ceil());
  final bytes = await image.toByteData(format: ImageByteFormat.png);
  return bytes!.buffer.asUint8List();
}

await location.changeNotificationOptions(
  iconBytes: await iconDataToPngBytes(Icons.location_on),
);
```

Android's small-icon convention expects a white silhouette on a transparent
background (the system tints it to match the status bar) — render your icon
accordingly for it to look right; this plugin decodes whatever bytes it's
given as-is.

## Examples

### Updating the notification with the current location

The notification will only appear on Android

```dart
final location = Location();
location.enableBackgroundMode(enable: true);
_locationSubscription = location.onLocationChanged
    .listen((LocationData currentLocation) async {
        await location.changeNotificationOptions(
            subtitle:
                'Location: ${currentLocation.latitude}, ${currentLocation.longitude}',
            onTapBringToFront: true,
        );
    }
);

...

_locationSubscription?.cancel();
```

### Fully custom notification content

`changeNotificationOptions` covers the common fields, but Android identifies
the foreground service's notification purely by its channel and notification
ID — any code that posts to that same ID replaces its displayed content, the
same way this plugin's own updates do internally. Call
`changeNotificationOptions` once to obtain that ID, then use another
notification plugin (e.g.
[`flutter_local_notifications`](https://pub.dev/packages/flutter_local_notifications))
to post whatever content you want to it:

```dart
final notificationData = await location.changeNotificationOptions();
if (notificationData != null) {
  await flutterLocalNotificationsPlugin.show(
    notificationData.notificationId,
    'Fully custom title',
    'Fully custom body, any layout flutter_local_notifications supports',
    NotificationDetails(
      android: AndroidNotificationDetails(
        notificationData.channelId,
        'My channel name',
      ),
    ),
  );
}
```

Note that calling `changeNotificationOptions` again afterwards will overwrite
your custom content back to this plugin's own notification builder.
