show method
Shows a notification with a title
and an optional body
and icon
.
Use payload
to embed information into the notification.
Implementation
Future<void> show(
String title, {
String? body,
String? payload,
ImageFile? icon,
String? tag,
String? image,
}) async {
Log.debug(
'show($title, $body, $payload, $icon, $tag, $image)',
'$runtimeType',
);
// Don't display a notification with the provided [tag], if it's in the
// [_tags] list already, or otherwise add it to that list.
if (_foregroundSubscription != null && tag != null) {
if (_tags.contains(tag)) {
_tags.remove(tag);
return;
} else {
_tags.add(tag);
}
}
// If application is in focus, the payload is the current route and nothing
// is obscuring the screen, then don't show a local notification.
if (_active && payload == router.route && router.obscuring.isEmpty) {
return;
}
// Play a notification sound on Web and on Windows.
//
// Other platforms don't require playing a sound explicitly, as the local or
// push notification displayed plays it instead.
if (PlatformUtils.isWeb || PlatformUtils.isWindows) {
AudioUtils.once(AudioSource.asset('audio/notification.mp3'));
}
if (PlatformUtils.isWeb) {
WebUtils.showNotification(
title,
body: body,
lang: payload,
icon: icon?.url ?? image,
tag: tag,
).onError((_, __) => false);
} else if (PlatformUtils.isWindows) {
File? file;
if (icon != null) {
file =
(await CacheWorker.instance.get(
url: icon.url,
checksum: icon.checksum,
responseType: CacheResponseType.file,
)).file;
}
await WinToast.instance().showCustomToast(
xml:
'<?xml version="1.0" encoding="UTF-8"?>'
'<toast activationType="Foreground" launch="${payload ?? ''}">'
' <visual addImageQuery="true">'
' <binding template="ToastGeneric">'
' <text>$title</text>'
' <text>${body ?? ''}</text>'
' <image placement="appLogoOverride" hint-crop="circle" id="1" src="${file?.path ?? ''}"/>'
' </binding>'
' </visual>'
'</toast>',
tag: 'Gapopa',
);
} else {
String? imagePath;
// In order to show an image in local notification, we need to download it
// first to a [File] and then pass the path to it to the plugin.
if (image != null) {
try {
final String name =
'notification_${DateTime.now().toString().replaceAll(':', '.')}.jpg';
final File? file = await PlatformUtils.download(
image,
name,
null,
temporary: true,
);
imagePath = file?.path;
} catch (_) {
// No-op.
}
}
// TODO: `flutter_local_notifications` should support Windows:
// https://github.com/MaikuB/flutter_local_notifications/issues/746
await _plugin?.show(
// On Android notifications are replaced when ID and tag are the same,
// and FCM notifications always have ID of zero, so in order for push
// notifications to replace local, we set its ID as zero as well.
PlatformUtils.isAndroid ? 0 : Random().nextInt(1 << 31),
title,
body,
NotificationDetails(
android: AndroidNotificationDetails(
'default',
'Default',
sound: const RawResourceAndroidNotificationSound('notification'),
styleInformation:
imagePath == null
? null
: BigPictureStyleInformation(
FilePathAndroidBitmap(imagePath),
),
tag: tag,
),
linux: LinuxNotificationDetails(
sound: AssetsLinuxSound('audio/notification.mp3'),
),
iOS: DarwinNotificationDetails(
sound: 'notification.caf',
attachments: [
if (imagePath != null) DarwinNotificationAttachment(imagePath),
],
),
macOS: DarwinNotificationDetails(
sound: 'notification.caf',
attachments: [
if (imagePath != null) DarwinNotificationAttachment(imagePath),
],
),
),
payload: payload,
);
}
}