Notifications
Show, schedule, and cancel system notifications in your Flet app
using the flet-notifications extension. It wraps Flutter's
flutter_local_notifications package.
The notifications are local: your app posts them itself, either at once or scheduled ahead of time, in which case the operating system delivers them even while the app isn't running. Push notifications sent from a server, through Firebase Cloud Messaging or the Apple Push Notification service, are not supported by this extension.
Platform Support
| Platform | Windows | macOS | Linux | iOS | Android | Web |
|---|---|---|---|---|---|---|
| Supported | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Usage
Add flet-notifications to your project dependencies:
- uv
- pip
uv add flet-notifications
pip install flet-notifications
Requirements
The following sections describe the configuration required for each platform.
Android
The extension adds the receivers that deliver
action buttons and scheduled notifications, and restore schedules after a reboot
or an app update, to your app's manifest, with the POST_NOTIFICATIONS,
VIBRATE and RECEIVE_BOOT_COMPLETED permissions. flet build
also enables the core library desugaring the notifications plugin requires,
through the extension's build settings.
Some features need permissions only your app can decide to request:
exact schedules (see AndroidScheduleMode),
full-screen notifications (see AndroidOptions.full_screen_intent),
and foreground services (see start_foreground_service()).
See also:
Windows
Building the app with flet build windows needs
Visual Studio's C++ ATL for latest build tools component, for the
architecture you build for. The Visual Studio Installer selects the x86 & x64
one with the Desktop development with C++
workload, but not in Build Tools installations, and the ARM64 one, needed on
Windows on Arm, is never selected. Without it, the build fails with
Cannot open include file: 'atlbase.h'. Add it in the Visual Studio Installer,
under Modify > Individual components.
Web
The browser only accepts
Notification.requestPermission()
from a user gesture. Call
request_permissions()
from an on_click handler before calling
show(). Serve the app over HTTPS
or a trusted localhost origin. If permission was denied, the user must change
the site's browser permissions before requesting again.
are_notifications_enabled()
checks browser permission without prompting. It returns False when permission
is denied, undecided, or notifications are unsupported.
Use WebOptions to customize browser notifications.
The browser and operating system determine which presentation options are honored.
NotificationAction buttons are forwarded
on Web, but browser support and the number of visible buttons vary. Inline action
inputs are not supported; provide essential actions within the app as well.
Examples
Basic notifications
import flet as ft
import flet_notifications as ftn
def main(page: ft.Page):
def handle_tap(e: ftn.NotificationEvent):
page.show_dialog(ft.SnackBar(f"Opened notification {e.payload}"))
notifications = ftn.Notifications(on_tap=handle_tap)
async def notify(e: ft.Event[ft.Button]):
if not await notifications.request_permissions():
page.show_dialog(ft.SnackBar("Notifications are turned off."))
return
await notifications.show(
id=1,
title="Notification Title",
body="This is the notification body...",
payload="notif-1",
)
page.add(
ft.SafeArea(content=ft.Button("Notify", on_click=notify)),
)
if __name__ == "__main__":
ft.run(main)
Permissions
Calls open_settings() when the user has turned notifications off, since the system won't ask again. The full-screen and Do Not Disturb buttons appear only on Android, and need the USE_FULL_SCREEN_INTENT and ACCESS_NOTIFICATION_POLICY permissions declared in pyproject.toml.
import flet as ft
import flet_notifications as ftn
async def main(page: ft.Page):
notifications = ftn.Notifications()
android = not page.web and page.platform in {
ft.PagePlatform.ANDROID,
ft.PagePlatform.ANDROID_TV,
}
has_settings = not page.web and page.platform in {
ft.PagePlatform.ANDROID,
ft.PagePlatform.ANDROID_TV,
ft.PagePlatform.IOS,
ft.PagePlatform.MACOS,
}
async def refresh():
enabled = await notifications.are_notifications_enabled()
status.value = "Notifications are on." if enabled else "Notifications are off."
page.update()
async def request(e: ft.Event[ft.Button]):
await notifications.request_permissions()
await refresh()
async def open_settings(e: ft.Event[ft.Button]):
await notifications.open_settings()
async def request_full_screen(e: ft.Event[ft.Button]):
granted = await notifications.request_full_screen_intent_permission()
page.show_dialog(ft.SnackBar(f"Full-screen notifications: {granted}"))
async def request_policy_access(e: ft.Event[ft.Button]):
if not await notifications.has_notification_policy_access():
await notifications.request_notification_policy_access()
async def handle_lifecycle(e: ft.AppLifecycleStateChangeEvent):
# The user may have changed the setting while the app was in the background.
if e.state == ft.AppLifecycleState.RESUME:
await refresh()
page.on_app_lifecycle_state_change = handle_lifecycle
page.add(
ft.SafeArea(
content=ft.Column(
controls=[
status := ft.Text(),
ft.Button("Ask for permission", on_click=request),
ft.Button(
"Open notification settings",
on_click=open_settings,
disabled=not has_settings,
tooltip=None if has_settings else "Android, iOS and macOS only",
),
ft.Button(
"Allow full-screen notifications",
on_click=request_full_screen,
disabled=not android,
tooltip=None if android else "Android only",
),
ft.Button(
"Allow Do Not Disturb access",
on_click=request_policy_access,
disabled=not android,
tooltip=None if android else "Android only",
),
]
)
)
)
await refresh()
if __name__ == "__main__":
ft.run(main)
Action buttons and replies
Button presses arrive in on_action, with the typed reply in input. The Archive button uses foreground=False, so it is handled without opening the app. Inline replies need Android, iOS, macOS or Windows, and Delete asks to unlock the device on iOS.
import flet as ft
import flet_notifications as ftn
def main(page: ft.Page):
def handle_tap(e: ftn.NotificationEvent):
log.controls.append(ft.Text(f"Opened {e.payload}"))
log.update()
def handle_action(e: ftn.NotificationActionEvent):
message = f"{e.action_id} on {e.payload}"
if e.input is not None:
message += f": {e.input!r}"
log.controls.append(ft.Text(message))
log.update()
notifications = ftn.Notifications(on_tap=handle_tap, on_action=handle_action)
async def show_message(e: ft.Event[ft.Button]):
if not await notifications.request_permissions():
page.show_dialog(ft.SnackBar("Notifications are turned off."))
return
await notifications.show(
id=1,
title="Ada",
body="Lunch at noon?",
payload="chat:ada",
actions=[
ftn.NotificationAction(
id="reply",
title="Reply",
input=ftn.NotificationActionInput(label="Message"),
),
# Handled without opening the app.
ftn.NotificationAction(id="archive", title="Archive", foreground=False),
ftn.NotificationAction(
id="delete",
title="Delete",
destructive=True,
require_authentication=True,
),
],
)
page.add(
ft.SafeArea(
content=ft.Column(
controls=[
ft.Button("Show message", on_click=show_message),
log := ft.Column(),
]
)
)
)
if __name__ == "__main__":
ft.run(main)
Scheduling
A naive datetime is device time; attach a ZoneInfo to when to schedule in a specific time zone. Windows schedules one-off notifications only, so the recurring buttons are hidden there. Android delivers these inexactly; see the exact alarms example for on-the-dot timing.
from datetime import datetime, time, timedelta
import flet as ft
import flet_notifications as ftn
SUPPORTED = {
ft.PagePlatform.ANDROID,
ft.PagePlatform.ANDROID_TV,
ft.PagePlatform.IOS,
ft.PagePlatform.MACOS,
ft.PagePlatform.WINDOWS,
}
async def main(page: ft.Page):
if page.web or page.platform not in SUPPORTED:
page.add(
ft.SafeArea(
content=ft.Text(
"Scheduling needs Android, iOS, macOS or Windows. "
"Run this example on one of them."
)
)
)
return
notifications = ftn.Notifications()
windows = page.platform == ft.PagePlatform.WINDOWS
one_off_only = "Windows schedules one-off notifications only" if windows else None
async def refresh():
scheduled = await notifications.get_pending()
# Windows reports pending notifications without their title.
rows = [ft.Text(f"#{n.id} {n.title or ''}") for n in scheduled]
pending.controls = rows or [ft.Text("Nothing scheduled.")]
page.update()
async def in_ten_seconds(e: ft.Event[ft.Button]):
await notifications.request_permissions()
await notifications.schedule(
1, when=timedelta(seconds=10), title="Stretch", body="Time to stand up."
)
await refresh()
async def every_morning(e: ft.Event[ft.Button]):
await notifications.request_permissions()
# A naive datetime is device time, so this follows the user across zones.
next_nine = datetime.combine(datetime.now().date(), time(9))
if next_nine < datetime.now():
next_nine += timedelta(days=1)
await notifications.schedule(
2,
when=next_nine,
title="Good morning",
body="Here is your daily summary.",
match_components=ftn.DateTimeComponents.TIME,
)
await refresh()
async def every_hour(e: ft.Event[ft.Button]):
await notifications.request_permissions()
await notifications.periodically_show(
3,
repeat_interval=ftn.RepeatInterval.HOURLY,
title="Hourly check-in",
body="How is it going?",
)
await refresh()
async def cancel_all(e: ft.Event[ft.Button]):
await notifications.cancel_all_pending()
await refresh()
page.add(
ft.SafeArea(
content=ft.Column(
controls=[
ft.Button("In 10 seconds", on_click=in_ten_seconds),
ft.Button(
"Every day at 9:00",
on_click=every_morning,
disabled=windows,
tooltip=one_off_only,
),
ft.Button(
"Every hour",
on_click=every_hour,
disabled=windows,
tooltip=one_off_only,
),
ft.Button(
"Cancel all",
on_click=cancel_all,
disabled=windows,
tooltip="Windows cancels scheduled notifications one by one"
if windows
else None,
),
ft.Text("Pending", weight=ft.FontWeight.BOLD),
pending := ft.Column(),
]
)
)
)
await refresh()
if __name__ == "__main__":
ft.run(main)
Exact alarms
Exact [schedule modes][flet_notifications.AndroidScheduleMode] need the SCHEDULE_EXACT_ALARM permission, which Android 14+ denies by default. request_exact_alarm_permission() opens the system page where the user allows it, and the example checks again when the app comes back to the foreground. Android only.
from datetime import timedelta
import flet as ft
import flet_notifications as ftn
async def main(page: ft.Page):
if page.web or page.platform not in {
ft.PagePlatform.ANDROID,
ft.PagePlatform.ANDROID_TV,
}:
page.add(
ft.SafeArea(
content=ft.Text(
"Exact alarms are an Android permission. Other platforms "
"deliver scheduled notifications on time without it."
)
)
)
return
notifications = ftn.Notifications()
async def refresh():
allowed = await notifications.can_schedule_exact_alarms()
status.value = (
"Exact alarms are allowed." if allowed else "Exact alarms are not allowed."
)
allow_button.disabled = allowed
allow_button.tooltip = "Already allowed" if allowed else None
page.update()
async def allow(e: ft.Event[ft.Button]):
# Opens the system's "Alarms & reminders" page for this app.
await notifications.request_exact_alarm_permission()
async def schedule(e: ft.Event[ft.Button]):
if not await notifications.can_schedule_exact_alarms():
page.show_dialog(ft.SnackBar("Allow exact alarms first."))
return
await notifications.request_permissions()
await notifications.schedule(
1,
when=timedelta(minutes=1),
title="One minute is up",
body="Delivered on the dot, even in Doze.",
schedule_mode=ftn.AndroidScheduleMode.EXACT_ALLOW_WHILE_IDLE,
)
page.show_dialog(ft.SnackBar("Scheduled for one minute from now."))
async def handle_lifecycle(e: ft.AppLifecycleStateChangeEvent):
if e.state == ft.AppLifecycleState.RESUME:
await refresh()
page.on_app_lifecycle_state_change = handle_lifecycle
page.add(
ft.SafeArea(
content=ft.Column(
controls=[
status := ft.Text(),
allow_button := ft.Button("Allow exact alarms", on_click=allow),
ft.Button("Remind me in exactly one minute", on_click=schedule),
]
)
)
)
await refresh()
if __name__ == "__main__":
ft.run(main)
Progress
On Android, showing the same ID again updates the notification. On Windows, update_windows_progress() updates the bar in place, and returns False once the user has dismissed the notification. Android and Windows only.
import asyncio
import flet as ft
import flet_notifications as ftn
STEPS = 10
async def main(page: ft.Page):
android = not page.web and page.platform in {
ft.PagePlatform.ANDROID,
ft.PagePlatform.ANDROID_TV,
}
windows = not page.web and page.platform == ft.PagePlatform.WINDOWS
if not (android or windows):
page.add(
ft.SafeArea(
content=ft.Text(
"Progress bars in notifications need Android or Windows. "
"Run this example on one of them."
)
)
)
return
notifications = ftn.Notifications()
async def show_android_progress(step: int):
# Showing the same ID again updates the notification in place.
await notifications.show(
1,
title="Downloading report.pdf",
options=ftn.NotificationOptions(
android=ftn.AndroidOptions(
progress=ftn.AndroidProgress(value=step, max=STEPS),
only_alert_once=True,
ongoing=True,
)
),
)
async def download(e: ft.Event[ft.Button]):
await notifications.request_permissions()
if windows:
await notifications.show(
1,
title="Downloading report.pdf",
options=ftn.NotificationOptions(
windows=ftn.WindowsOptions(
# Updates change only the fields the notification was
# shown with, so it starts with a label too.
progress=ftn.WindowsProgress(
status="Downloading", max=STEPS, label=f"0/{STEPS}"
)
)
),
)
for step in range(1, STEPS + 1):
await asyncio.sleep(0.5)
if android:
await show_android_progress(step)
elif not await notifications.update_windows_progress(
1,
ftn.WindowsProgress(
status="Downloading", value=step, max=STEPS, label=f"{step}/{STEPS}"
),
):
page.show_dialog(ft.SnackBar("Download notification closed."))
return
await notifications.show(1, title="report.pdf", body="Download complete")
page.add(
ft.SafeArea(content=ft.Button("Download", on_click=download)),
)
if __name__ == "__main__":
ft.run(main)
Shown notifications
Groups the messages under a summary on Android, where dismissing the summary dismisses the whole group, and in one thread on iOS and macOS. get_active() lists only this app's notifications that are still shown. On Windows, listing and removing them needs an app packaged as MSIX.
import flet as ft
import flet_notifications as ftn
SUPPORTED = {
ft.PagePlatform.ANDROID,
ft.PagePlatform.ANDROID_TV,
ft.PagePlatform.IOS,
ft.PagePlatform.MACOS,
ft.PagePlatform.WINDOWS,
}
MESSAGES = {2: "Ada: Lunch?", 3: "Grace: Slides attached", 4: "Alan: Ping"}
async def main(page: ft.Page):
if not page.web and page.platform not in SUPPORTED:
page.add(
ft.SafeArea(
content=ft.Text(
"Listing shown notifications isn't available on this platform."
)
)
)
return
notifications = ftn.Notifications()
def in_inbox(summary: bool = False) -> ftn.NotificationOptions:
# Android groups by key under a summary; Apple platforms by thread.
return ftn.NotificationOptions(
android=ftn.AndroidOptions(
group=ftn.AndroidGroup(key="inbox", summary=summary)
),
ios=ftn.DarwinOptions(thread_identifier="inbox"),
macos=ftn.DarwinOptions(thread_identifier="inbox"),
)
async def refresh():
shown = await notifications.get_active()
listed.controls = [
ft.Row(
controls=[
ft.Text(f"#{n.id} {n.title or ''}"),
ft.TextButton(
"Dismiss",
data=n,
on_click=dismiss,
),
]
)
for n in shown
] or [ft.Text("Nothing shown.")]
page.update()
async def post(e: ft.Event[ft.Button]):
await notifications.request_permissions()
for id, text in MESSAGES.items():
await notifications.show(id, title=text, options=in_inbox())
await notifications.show(
1, title="3 new messages", options=in_inbox(summary=True)
)
await refresh()
async def dismiss(e: ft.Event[ft.TextButton]):
shown: ftn.ActiveNotification = e.control.data
await notifications.cancel(shown.id, tag=shown.tag)
await refresh()
async def dismiss_all(e: ft.Event[ft.Button]):
await notifications.cancel_all()
await refresh()
async def handle_lifecycle(e: ft.AppLifecycleStateChangeEvent):
# Notifications may have been dismissed in the meantime.
if e.state == ft.AppLifecycleState.RESUME:
await refresh()
page.on_app_lifecycle_state_change = handle_lifecycle
page.add(
ft.SafeArea(
content=ft.Column(
controls=[
ft.Text(
"Windows lists and removes notifications only for apps "
"packaged as MSIX.",
visible=not page.web
and page.platform == ft.PagePlatform.WINDOWS,
),
ft.Button("Post messages", on_click=post),
ft.Button("Dismiss all", on_click=dismiss_all),
ft.Text("Shown", weight=ft.FontWeight.BOLD),
listed := ft.Column(),
]
)
)
)
await refresh()
if __name__ == "__main__":
ft.run(main)
Android styles
The big picture is landscape.png from the example's assets folder, sent as bytes. Android only.
from datetime import datetime, timedelta
from pathlib import Path
import flet as ft
import flet_notifications as ftn
PICTURE = Path(__file__).parent / "assets" / "landscape.png"
async def main(page: ft.Page):
if page.web or page.platform not in {
ft.PagePlatform.ANDROID,
ft.PagePlatform.ANDROID_TV,
}:
page.add(
ft.SafeArea(
content=ft.Text(
"Notification styles are an Android feature. "
"Run this example on Android."
)
)
)
return
notifications = ftn.Notifications()
async def show(id: int, title: str, body: str, style: ftn.AndroidStyle):
await notifications.request_permissions()
await notifications.show(
id,
title=title,
body=body,
options=ftn.NotificationOptions(android=ftn.AndroidOptions(style=style)),
)
async def big_text(e: ft.Event[ft.Button]):
await show(
1,
"Release notes",
"Version 2.0 is out",
ftn.AndroidBigTextStyle(
text="Version 2.0 brings offline mode, a redesigned editor, "
"faster sync and dozens of fixes. Expand to read the highlights."
),
)
async def big_picture(e: ft.Event[ft.Button]):
await show(
2,
"Photo shared",
"Ada shared a photo",
ftn.AndroidBigPictureStyle(
image=ftn.AndroidBytesBitmap(data=PICTURE.read_bytes()),
summary_text="Hills at sunrise",
),
)
async def inbox(e: ft.Event[ft.Button]):
await show(
3,
"3 new emails",
"From Ada, Grace and Alan",
ftn.AndroidInboxStyle(
lines=["Ada: Lunch tomorrow?", "Grace: Slides attached", "Alan: Ping"],
summary_text="work@example.com",
),
)
async def messaging(e: ft.Event[ft.Button]):
me = ftn.AndroidPerson(name="You")
ada = ftn.AndroidPerson(name="Ada")
now = datetime.now().astimezone()
await show(
4,
"Ada",
"See you there",
ftn.AndroidMessagingStyle(
person=me,
conversation_title="Lunch",
messages=[
ftn.AndroidMessage(
text="Noon at the usual place?",
timestamp=now - timedelta(minutes=2),
person=ada,
),
ftn.AndroidMessage(text="Sure!", timestamp=now, person=me),
],
),
)
page.add(
ft.SafeArea(
content=ft.Column(
controls=[
ft.Button("Big text", on_click=big_text),
ft.Button("Big picture", on_click=big_picture),
ft.Button("Inbox", on_click=inbox),
ft.Button("Messaging", on_click=messaging),
]
)
)
)
if __name__ == "__main__":
ft.run(main)
Android channels
A channel's importance, sound and vibration are fixed once it is created: after that, only the user can change them in the system settings. Android only.
import flet as ft
import flet_notifications as ftn
GROUP = "chat"
CHANNELS = [
ftn.NotificationChannel(
id="messages",
name="Messages",
description="New direct messages",
group_id=GROUP,
importance=ftn.AndroidImportance.HIGH,
),
ftn.NotificationChannel(
id="digest",
name="Daily digest",
description="A quiet summary once a day",
group_id=GROUP,
importance=ftn.AndroidImportance.LOW,
play_sound=False,
enable_vibration=False,
),
]
async def main(page: ft.Page):
if page.web or page.platform not in {
ft.PagePlatform.ANDROID,
ft.PagePlatform.ANDROID_TV,
}:
page.add(
ft.SafeArea(
content=ft.Text(
"Notification channels exist only on Android. "
"Run this example on Android."
)
)
)
return
notifications = ftn.Notifications()
async def refresh():
channels = await notifications.get_channels()
listed.controls = [
ft.Text(f"{c.name} ({c.importance.name.lower()})") for c in channels
] or [ft.Text("No channels yet.")]
# Android drops notifications posted to a channel that doesn't exist.
missing = "messages" not in {c.id for c in channels}
post_button.disabled = missing
post_button.tooltip = "Create the channels first" if missing else None
page.update()
async def create(e: ft.Event[ft.Button]):
await notifications.create_channel_group(GROUP, name="Chat")
for channel in CHANNELS:
await notifications.create_channel(channel)
await refresh()
async def post(e: ft.Event[ft.Button]):
await notifications.request_permissions()
await notifications.show(
1,
title="Ada",
body="Are you free?",
# The channel decides how the notification alerts.
options=ftn.NotificationOptions(
android=ftn.AndroidOptions(channel="messages")
),
)
async def delete(e: ft.Event[ft.Button]):
# Deleting a group deletes its channels too.
await notifications.delete_channel_group(GROUP)
await refresh()
page.add(
ft.SafeArea(
content=ft.Column(
controls=[
ft.Button("Create channels", on_click=create),
post_button := ft.Button("Post a message", on_click=post),
ft.Button("Delete channels", on_click=delete),
ft.Text("Channels", weight=ft.FontWeight.BOLD),
listed := ft.Column(),
]
)
)
)
await refresh()
if __name__ == "__main__":
ft.run(main)
Foreground service
Declares the plugin's service with the dataSync type, and the matching permissions, in pyproject.toml. See AndroidForegroundServiceType for the entries of other service types. Android only.
import flet as ft
import flet_notifications as ftn
def main(page: ft.Page):
if page.web or page.platform not in {
ft.PagePlatform.ANDROID,
ft.PagePlatform.ANDROID_TV,
}:
page.add(
ft.SafeArea(
content=ft.Text(
"Foreground services exist only on Android. "
"Run this example on Android."
)
)
)
return
notifications = ftn.Notifications()
async def start(e: ft.Event[ft.Button]):
await notifications.request_permissions()
await notifications.start_foreground_service(
1,
title="Syncing photos",
body="Keeps running while you use other apps",
service_types=[ftn.AndroidForegroundServiceType.DATA_SYNC],
)
async def stop(e: ft.Event[ft.Button]):
await notifications.stop_foreground_service()
page.add(
ft.SafeArea(
content=ft.Column(
controls=[
ft.Button("Start sync", on_click=start),
ft.Button("Stop sync", on_click=stop),
]
)
)
)
if __name__ == "__main__":
ft.run(main)
Description
Provides native local notifications for Android, iOS, macOS, Windows, Linux, and Web.
Create one service per page and keep its reference for sending notifications and
handling responses. It registers with the page automatically and does not need to be
added to the page's visual controls. The native backend initializes when the
service reaches the client, and method calls wait for it to finish. Changing
android_default_icon initializes it again with the new value; a failed
initialization is retried on the next method call. Windows keeps the identity
the app's notifications first registered with until the app exits, so changes
to windows_app_name, windows_app_user_model_id, and
windows_guid apply from its next launch.
show posts from wherever the app's code runs, such as when a download
finishes or a message arrives, so that code must be running. Desktop and web
apps run while their window or tab is open. Android may stop an app's process
some time after it leaves the screen; keep long work going with
start_foreground_service. iOS suspends an app moments after it leaves the
screen, so schedule the notifications iOS users should get later.
Feature support varies: rich styles, progress, and grouping are
Android-specific (see AndroidOptions); calendar
and interval recurrence are available on Android, iOS, and macOS; Windows
supports one-shot scheduling; Linux and Web do not provide scheduling through
this extension. Platform permissions and native configuration still apply. See
the notification service's requirements in the user guide.
Notification response handlers receive
NotificationEvent. A tap that launches a closed app is
delivered once the service initializes. When a background action runs without
the app UI, a native Dart handler persists the event for replay when the service
next initializes; it does not execute Python in the background.
import flet as ft
import flet_notifications as ftn
def main(page: ft.Page):
def handle_tap(e: ftn.NotificationEvent):
page.add(ft.Text(f"Opened {e.payload}"))
notifications = ftn.Notifications(on_tap=handle_tap)
async def notify(e: ft.Event[ft.Button]):
if await notifications.request_permissions():
await notifications.show(
id=1,
title="Download complete",
body="Your file is ready.",
payload="download:42",
)
page.add(ft.SafeArea(content=ft.Button("Notify", on_click=notify)))
ft.run(main)
Inherits: Service
Properties
android_default_icon- Default small Android notification icon.windows_app_name- Name Windows shows for the app's notifications, and in its notification settings.windows_app_user_model_id- Windows AppUserModelID identifying the source of the app's notifications.windows_guid- GUID of the component Windows activates when the user selects a notification.
Events
Methods
are_notifications_enabled- Check application-level notification authorization where supported.can_schedule_exact_alarms- Check Android's authorization to schedule exact alarms.cancel- Remove a displayed notification and cancel its scheduled request.cancel_all- Remove all of the app's displayed and scheduled notifications.cancel_all_pending- Cancel all scheduled notifications without removing displayed ones.create_channel- Create an Android notification channel or update its mutable details.create_channel_group- Create a group organizing Android channels in system notification settings.delete_channel- Delete an Android notification channel on Android 8.0+.delete_channel_group- Delete an Android notification-channel group and all its channels.get_active- Query delivered notifications that have not been dismissed or removed.get_channels- Query the app's Android notification channels.get_pending- Query notifications scheduled for future delivery.has_notification_policy_access- Check whether Android has granted notification-policy access.open_settings- Open the operating system's notification settings for this app.periodically_show- Schedule a notification repeating after a fixed elapsed interval.request_exact_alarm_permission- Request Android exact-alarm access through system settings when needed.request_full_screen_intent_permission- Request access to Android full-screen notification intents.request_notification_policy_access- Open Android's notification-policy access settings when required.request_permissions- Request notification authorization where the platform supports a prompt.schedule- Schedule a notification for a date, a delay, or a recurring calendar match.show- Display a local notification immediately.start_foreground_service- Start an Android foreground service with a visible notification.stop_foreground_service- Stop the Android foreground service started by this extension.update_windows_progress- Update the progress bar of a shown Windows notification in place.
Properties
android_default_iconclass-attributeinstance-attribute
android_default_icon: str = 'flet_notifications_icon'Default small Android notification icon.
Supply a bundled drawable resource name, such as "ic_stat_notify", without an
extension. See AndroidOptions.icon for the icon's
requirements and how to bundle it.
The default is a silhouette of the Flet logo that this extension provides. Android draws the small icon from its transparency alone, so use a silhouette of your own to show your app's brand instead.
windows_app_nameclass-attributeinstance-attribute
windows_app_name: str | None = NoneName Windows shows for the app's notifications, and in its notification settings.
None uses the app's product name, from its executable's version information.
windows_app_user_model_idclass-attributeinstance-attribute
windows_app_user_model_id: str | None = NoneWindows AppUserModelID identifying the source of the app's notifications.
Windows keeps notification settings and history per AppUserModelID, so apps must
not share one. None derives one from the app's executable, such as
"Flet.myapp.3f2a9c1e", that is stable across launches and differs between apps.
Set one when Windows should treat the app as the one with that ID, such as the ID
of its Start menu shortcut or installer.
Windows shows the app's icon, from flet build, on its notifications, and
keeps the icon it first showed for an AppUserModelID: after changing the app's
icon, set a new ID to see the new one.
windows_guidclass-attributeinstance-attribute
windows_guid: str | None = NoneGUID of the component Windows activates when the user selects a notification.
None derives one from windows_app_user_model_id, so it differs between
apps, and registers the app built with flet build as the one Windows starts to
deliver a selection made after the app exited. With a custom GUID, the app's
installer registers that component instead.
Events
on_actionclass-attributeinstance-attribute
on_action: (
EventHandler[NotificationActionEvent[Notifications]]
| None
) = NoneCalled when the user selects a notification action button.
Its handler receives a NotificationActionEvent; use
its action_id to identify
the button and input for
reply text.
- When an action launches the app, this handler is called for it once the
service initializes, as with
on_tap. - On Windows, the event's inherited
datamapping contains reply values keyed byNotificationAction.id. For an action with the ID"reply", reade.data["reply"]. When exactly one value is returned,NotificationActionEvent.inputalso contains that text. - Background Android/iOS actions are queued and replayed on the next service initialization; Python is not run in the background isolate.
- On Linux, an action reaches the app only while it is running; selecting one after the app has closed doesn't launch it.
- On Windows, an app built with
flet buildis launched to receive an action selected after it closed. An app run withflet runor packaged withflet packreceives an action only while it is running.
on_tapclass-attributeinstance-attribute
on_tap: (
EventHandler[NotificationEvent[Notifications]] | None
) = NoneCalled when the user selects the notification body.
The event includes the notification ID and application payload. Full-screen Android notification launches also use this handler.
- When selecting a notification launches the app, this handler is called for it once the service initializes, so set it when creating the service. It is called once per launch; use it, for example, to route the app to the notification's content.
- On Linux, a selection reaches the app only while it is running; selecting a notification after the app has closed doesn't launch it.
- On Windows, an app built with
flet buildis launched to receive a selection made after it closed. An app run withflet runor packaged withflet packreceives a selection only while it is running.
Methods
are_notifications_enabledasync
are_notifications_enabled() -> boolCheck application-level notification authorization where supported.
On Android, queries whether the app's notifications are enabled. On
iOS/macOS, includes provisional authorization, which permits quiet delivery.
On Web, checks the current browser permission without displaying a prompt;
denied, undecided, or unsupported notification access returns False.
This check does not guarantee a particular channel, sound, or alert can interrupt the user.
Returns:
- bool - Native authorization status on Android/iOS/macOS, or browser authorization on Web. Returns
Trueunconditionally on Windows and Linux, without checking system notification settings.
Raises:
- NotificationException - If the bridge reports initialization or operation failure.
can_schedule_exact_alarmsasync
can_schedule_exact_alarms() -> boolCheck Android's authorization to schedule exact alarms.
Android restricts exact alarms from Android 12 onward. This is separate from notification-display permission and channel settings.
Returns:
- bool - Whether the Android backend reports exact alarms are allowed. Returns
Trueon non-Android platforms, where exact scheduling is not restricted.
Raises:
- NotificationException - If the bridge reports initialization or operation failure.
cancelasync
cancel(id: int, tag: str | None=None) -> NoneRemove a displayed notification and cancel its scheduled request.
On Android, a tag applies only to notifications posted immediately; scheduled alarms are identified by ID. On Windows, removal requires an MSIX package identity.
Parameters:
- id (int) - Identifier of the notification to remove.
- tag (str | None, default:
None) - Android tag supplied inAndroidOptions.tag. Matches both tag and ID when provided; ignored on other platforms.
Raises:
- NotificationInvalidArgumentException - If
iddoesn't fit a 32-bit signed integer. - NotificationException - If the bridge reports initialization or operation failure.
cancel_allasync
cancel_all() -> NoneRemove all of the app's displayed and scheduled notifications.
To remove only undelivered requests, use cancel_all_pending. Windows
removal requires an MSIX package identity. Does not remove Android channels
or channel groups.
Raises:
- NotificationException - If the bridge reports initialization or operation failure.
cancel_all_pendingasync
cancel_all_pending() -> NoneCancel all scheduled notifications without removing displayed ones.
Supported on Android, iOS, and macOS. Does nothing on the web, which has
no scheduled notifications. Use cancel to remove a specific
pending request.
Raises:
- NotificationUnsupportedPlatformException - If called on Windows, which can't cancel pending notifications all at once, or on Linux, which doesn't support scheduled notifications.
- NotificationException - If the bridge reports initialization or operation failure.
create_channelasync
create_channel(channel: NotificationChannel) -> NoneCreate an Android notification channel or update its mutable details.
Applies on Android 8.0+. Existing channel sound, vibration, lights, and
importance cannot be reset through this call. See
NotificationChannel for creation-time settings.
Does nothing on other platforms, which have no channels.
Parameters:
- channel (NotificationChannel) - Channel declaration. Post notifications to it by passing its ID as
AndroidOptions.channel. Create its group first when a group ID is supplied.
Raises:
- NotificationInvalidArgumentException - If
channelhas an emptyid. - NotificationInvalidArgumentException - If
channelhas an emptyname. - NotificationException - If the bridge reports initialization or operation failure.
create_channel_groupasync
create_channel_group(
group_id: str, name: str, description: str | None = None
) -> NoneCreate a group organizing Android channels in system notification settings.
Supported only on Android 8.0+. This is distinct from grouping displayed
notifications with AndroidOptions.group. Create
the group before creating channels that refer to its ID. Does nothing on
other platforms, which have no channels.
Parameters:
- group_id (str) - Stable identifier for the channel group.
- name (str) - User-visible group name.
- description (str | None, default:
None) - Optional explanation of the group, supported on Android 9.0+.
Raises:
- NotificationInvalidArgumentException - If
group_idis empty. - NotificationInvalidArgumentException - If
nameis empty. - NotificationException - If the bridge reports initialization or operation failure.
delete_channelasync
delete_channel(channel_id: str) -> NoneDelete an Android notification channel on Android 8.0+.
This does not cancel pending schedules that still refer to the channel; cancel those separately if they should no longer deliver notifications. Does nothing on other platforms, which have no channels.
Parameters:
- channel_id (str) - Identifier of the channel to delete.
Raises:
- NotificationInvalidArgumentException - If
channel_idis empty. - NotificationException - If the bridge reports initialization or operation failure.
delete_channel_groupasync
delete_channel_group(group_id: str) -> NoneDelete an Android notification-channel group and all its channels.
Supported only on Android 8.0+. This also removes channel configuration for the group's channels. Cancel unwanted pending notifications separately. Does nothing on other platforms, which have no channels.
Parameters:
- group_id (str) - Identifier of the group to delete.
Raises:
- NotificationInvalidArgumentException - If
group_idis empty. - NotificationException - If the bridge reports initialization or operation failure.
get_activeasync
get_active() -> list[ActiveNotification]Query delivered notifications that have not been dismissed or removed.
Supported on Android 6.0+, iOS 10+, macOS 10.14+, the web, and Windows with an MSIX package identity. Without that identity, Windows returns an empty list.
Returns:
- list[ActiveNotification] - Snapshots of active notifications, with platform-dependent fields. Unavailable values are
None.
Raises:
- NotificationUnsupportedPlatformException - If called on Linux, which can't list the notifications it shows.
- NotificationException - If the backend reports a failure or returns malformed query data.
get_channelsasync
get_channels() -> list[NotificationChannel]Query the app's Android notification channels.
Returns:
- list[NotificationChannel] - Channel snapshots on supported Android versions, or an empty list on non-Android platforms. Returned values reflect the native channel settings, including changes made by the user.
Raises:
- NotificationException - If the backend reports a failure or returns malformed query data.
get_pendingasync
get_pending() -> list[PendingNotification]Query notifications scheduled for future delivery.
Supported on Android, iOS, macOS, and Windows, where the query depends on package identity. Returns an empty list on the web, which has no scheduled notifications.
Returns:
- list[PendingNotification] - Snapshots of pending requests. These do not include every platform detail and cannot be edited to change the native schedule.
Raises:
- NotificationUnsupportedPlatformException - If called on Linux, which doesn't support scheduled notifications.
- NotificationException - If the backend reports a failure or returns malformed query data.
has_notification_policy_accessasync
has_notification_policy_access() -> boolCheck whether Android has granted notification-policy access.
This access is needed before creating a channel that requests Do Not Disturb bypass; it is distinct from notification-display permission.
Returns:
- bool - Whether access is granted on Android, or
Falseon other platforms.
Raises:
- NotificationException - If the bridge reports initialization or operation failure.
open_settingsasync
open_settings() -> NoneOpen the operating system's notification settings for this app.
On iOS, the plugin tries the app's notification settings and falls back to the app's general settings when necessary. The bridge discards the native success flag, so a successful return does not confirm that a settings screen opened.
Raises:
- NotificationUnsupportedPlatformException - If called on Windows, Linux or the web, where the app's notification settings can't be opened.
- NotificationException - If the bridge reports initialization or operation failure.
periodically_showasync
periodically_show(
id: int,
repeat_interval: RepeatInterval | DurationValue,
title: str | None = None,
body: str | None = None,
payload: str | None = None,
actions: list[NotificationAction] | None = None,
schedule_mode: AndroidScheduleMode = AndroidScheduleMode.INEXACT_ALLOW_WHILE_IDLE,
options: NotificationOptions | None = None,
) -> NoneSchedule a notification repeating after a fixed elapsed interval.
For a specific local time such as 09:00 every day, use schedule with
DateTimeComponents instead.
- The first delivery is one interval after this call, not immediately.
- Supported on Android, iOS, and macOS. Actual timing is subject to the system's power management and alarm policies.
- On Android, schedules are restored after a reboot or an app update,
through the
RECEIVE_BOOT_COMPLETEDpermission flet-notifications adds by default.
Parameters:
- id (int) - Notification identifier. Reuse it to update the same notification; on Android, a tag also participates in identifying immediately shown notifications. Native platforms can impose identifier range limits.
- repeat_interval (RepeatInterval | DurationValue) - Standard repeat interval or a custom duration of at least one minute, such as
ft.Duration(minutes=15). Integer values are interpreted as milliseconds. - title (str | None, default:
None) - Notification title.Noneomits the title. - body (str | None, default:
None) - Notification body.Noneomits the body. - payload (str | None, default:
None) - Application-defined string returned with tap and action events. The service does not interpret this value.Noneattaches no payload. - actions (list[NotificationAction] | None, default:
None) - Action buttons; seeNotificationActionfor platform support and background-response behavior. - schedule_mode (AndroidScheduleMode, default:
AndroidScheduleMode.INEXACT_ALLOW_WHILE_IDLE) - Android alarm precision and idle-mode behavior. The default needs no special access, but Android may deliver the notification some minutes late. Exact modes deliver on time and require exact-alarm access. Ignored on other platforms. - options (NotificationOptions | None, default:
None) - Additional per-platform details.
Raises:
- NotificationUnsupportedPlatformException - If called on Windows, Linux or the web, which don't support repeating notifications.
- NotificationInvalidArgumentException - If
repeat_intervalisn't aRepeatIntervalor a duration of at least one minute. - NotificationInvalidArgumentException - If
iddoesn't fit a 32-bit signed integer. - NotificationInvalidArgumentException - If a value in
actionsoroptionsis invalid. - NotificationPermissionException - If an exact
schedule_modelacks Android exact-alarm access. - NotificationException - If the bridge reports another failure.
request_exact_alarm_permissionasync
request_exact_alarm_permission() -> boolRequest Android exact-alarm access through system settings when needed.
Opens the system settings screen where the user can allow the app's alarms;
it is not a dialog. Returns once the user leaves that screen. On Android 14+,
the access is off until the user turns it on there. Exact-alarm access is
separate from request_permissions.
Requires SCHEDULE_EXACT_ALARM in the app's permissions; without it, the
settings screen cannot grant access and this returns False. See
AndroidScheduleMode for what exact
scheduling involves.
Returns:
- bool - Whether access is granted after the request. Returns
Trueon non-Android platforms, where exact scheduling is not restricted. A grant does not create a scheduled notification.
Raises:
- NotificationException - If the bridge reports initialization or operation failure.
request_full_screen_intent_permissionasync
request_full_screen_intent_permission() -> boolRequest access to Android full-screen notification intents.
On Android 14+, access can depend on the app's permitted use and user
settings. Requires the USE_FULL_SCREEN_INTENT manifest permission. After
obtaining access, enable
AndroidOptions.full_screen_intent on the
notification. A grant does not guarantee full-screen presentation; Android
may show a heads-up notification instead.
Returns:
- bool - Whether the Android backend reports access is granted;
Falseon non-Android platforms.
Raises:
- NotificationException - If the bridge reports initialization or operation failure.
request_notification_policy_accessasync
request_notification_policy_access() -> boolOpen Android's notification-policy access settings when required.
Requires ACCESS_NOTIFICATION_POLICY in the Android manifest. Obtain access
before creating channels with
NotificationChannel.bypass_dnd enabled.
Returns:
- bool - Whether Android reports access after the request, or
Falseon other - bool - platforms. The user can decline the request.
Raises:
- NotificationException - If the bridge reports initialization or operation failure.
request_permissionsasync
request_permissions(
alert: bool = True,
sound: bool = True,
badge: bool = True,
critical: bool = False,
provisional: bool = False,
) -> boolRequest notification authorization where the platform supports a prompt.
The service never prompts on its own; call this when the app is ready to explain why it needs notifications.
- On Android 13+, requests
POST_NOTIFICATIONS; older Android versions do not show that runtime prompt. On iOS/macOS, requests the kinds of authorization selected by the arguments. A previous denial may require the user to change system settings rather than displaying another prompt. - On Web, requests browser notification permission. Call from a user
interaction, such as an
Button.on_clickhandler, over HTTPS or a trusted localhost origin. An existing denial returnsFalsewithout prompting again; the user must change the site's browser permissions. Dismissing the prompt without granting access also returnsFalse. Unsupported browsers returnFalse. - On Windows and Linux, returns
Truewithout requesting or checking permission.
Parameters:
- alert (bool, default:
True) - Whether to request permission to display alerts. iOS/macOS only. - sound (bool, default:
True) - Whether to request permission to play sounds. Whether a sound plays also depends onDarwinOptions.present_sound. Has effect on iOS/macOS only. - badge (bool, default:
True) - Whether to request permission to badge the app icon; set the value withDarwinOptions.badge_number. Has effect on iOS/macOS only. - critical (bool, default:
False) - Whether to request permission for critical alerts, which sound through mute and Do Not Disturb. Requires Apple's critical-alert entitlement in the app; seeDarwinInterruptionLevel.CRITICAL. Has effect on iOS/macOS only. - provisional (bool, default:
False) - Whether to request provisional authorization instead of prompting: notifications are delivered quietly to Notification Center, where the user can keep or turn them off. No prompt is shown. Has effect on iOS/macOS only.
Returns:
- bool - Whether the native permission request succeeded, or
Trueon platforms where no permission request is performed. It does not guarantee delivery through per-channel restrictions, Focus, or Do Not Disturb.
Raises:
- NotificationException - If the bridge reports initialization or operation failure.
scheduleasync
schedule(
id: int,
when: datetime | timedelta,
title: str | None = None,
body: str | None = None,
payload: str | None = None,
actions: list[NotificationAction] | None = None,
match_components: DateTimeComponents | None = None,
options: NotificationOptions | None = None,
schedule_mode: AndroidScheduleMode = AndroidScheduleMode.INEXACT_ALLOW_WHILE_IDLE,
) -> NoneSchedule a notification for a date, a delay, or a recurring calendar match.
To repeat after a fixed elapsed interval rather than at a particular local
time, use periodically_show.
- Supported on Android, iOS, macOS, and Windows. Windows delivers once,
ignoring
match_components. - On Android, schedules are restored after a reboot or an app update,
through the
RECEIVE_BOOT_COMPLETEDpermission flet-notifications adds by default. - iOS keeps at most 64 pending notifications per app. Check
get_pendingwhen scheduling many.
Parameters:
- id (int) - Notification identifier. Reuse it to update the same notification; on Android, a tag also participates in identifying immediately shown notifications. Native platforms can impose identifier range limits.
- when (datetime | timedelta) - Delivery time as a
datetime, or a delay as atimedelta. Naive datetimes are wall-clock times in the device timezone; aware datetimes preserve their exact instant. For calendar recurrence in a particular timezone, use aZoneInfotime zone, such asdatetime(2027, 1, 1, 9, tzinfo=ZoneInfo("Europe/Paris")); other values recur in the device timezone, which falls back to UTC if lookup fails. Native scheduling has at best second precision, and delay fractions are truncated to whole seconds. - title (str | None, default:
None) - Notification title.Noneomits the title. - body (str | None, default:
None) - Notification body.Noneomits the body. - payload (str | None, default:
None) - Application-defined string returned with tap and action events. The service does not interpret this value.Noneattaches no payload. - actions (list[NotificationAction] | None, default:
None) - Action buttons; seeNotificationActionfor platform support and background-response behavior. - match_components (DateTimeComponents | None, default:
None) - Calendar components used for recurrence on Android, iOS, and macOS.Noneschedules once. The first delivery is the next matching occurrence, which may precede the full date inwhen. Windows ignores this argument and schedules once. - options (NotificationOptions | None, default:
None) - Additional per-platform details; seeNotificationOptions. - schedule_mode (AndroidScheduleMode, default:
AndroidScheduleMode.INEXACT_ALLOW_WHILE_IDLE) - Android alarm precision and idle-mode behavior; seeAndroidScheduleMode. The default needs no special access, but Android may deliver the notification some minutes late. Exact modes deliver on time and require exact-alarm access. Ignored on other platforms.
Raises:
- NotificationUnsupportedPlatformException - If called on Linux or the web, which don't support scheduled notifications.
- NotificationInvalidArgumentException - If
whenis not in the future. - NotificationInvalidArgumentException - If
iddoesn't fit a 32-bit signed integer. - NotificationInvalidArgumentException - If a value in
actionsoroptionsis invalid. - NotificationPermissionException - If an exact
schedule_modelacks Android exact-alarm access. - NotificationException - If the bridge reports another failure.
from datetime import datetime
from zoneinfo import ZoneInfo
import flet_notifications as ftn
await notifications.schedule(
id=2,
when=datetime(2027, 1, 1, 9, 0, tzinfo=ZoneInfo("Europe/Paris")),
title="Morning reminder",
match_components=ftn.DateTimeComponents.TIME,
)
showasync
show(
id: int,
title: str | None = None,
body: str | None = None,
payload: str | None = None,
actions: list[NotificationAction] | None = None,
options: NotificationOptions | None = None,
) -> NoneDisplay a local notification immediately.
Reusing an ID normally updates the existing notification, which is useful
for AndroidOptions.progress updates. Android's
AndroidOptions.tag also participates in
identifying immediately displayed notifications. Visible content, action
support, and alerting depend on the current platform and the user's
notification settings. On Web, obtain browser permission with
request_permissions before showing a notification.
Parameters:
- id (int) - Notification identifier. Reuse it to update the same notification; on Android, a tag also participates in identifying immediately shown notifications. Native platforms can impose identifier range limits.
- title (str | None, default:
None) - Notification title.Noneomits the title. - body (str | None, default:
None) - Notification body.Noneomits the body. - payload (str | None, default:
None) - Application-defined string returned with tap and action events. The service does not interpret this value.Noneattaches no payload. - actions (list[NotificationAction] | None, default:
None) - Action buttons; seeNotificationActionfor platform support and background-response behavior. - options (NotificationOptions | None, default:
None) - Additional per-platform details; seeNotificationOptions.
Raises:
- NotificationInvalidArgumentException - If
iddoesn't fit a 32-bit signed integer. - NotificationInvalidArgumentException - If a value in
actionsoroptionsis invalid, such as an empty action title or a progress value above its maximum. - NotificationException - If the bridge reports initialization or operation failure.
start_foreground_serviceasync
start_foreground_service(
id: int,
title: str | None = None,
body: str | None = None,
payload: str | None = None,
actions: list[NotificationAction] | None = None,
options: NotificationOptions | None = None,
start_type: AndroidServiceStartType | None = None,
service_types: list[AndroidForegroundServiceType]
| None = None,
) -> NoneStart an Android foreground service with a visible notification.
Requires a service declaration, appropriate foreground-service permissions,
and types matching the actual work. See
AndroidForegroundServiceType for the shared
setup and each type's pyproject.toml entries and runtime requirements.
This starts the plugin's native foreground service; it does not create a
Python worker or guarantee that Android will keep the process alive
indefinitely. Android's start restrictions and service time limits still
apply. Use stop_foreground_service when the work is finished.
Parameters:
- id (int) - Nonzero identifier for the foreground-service notification.
- title (str | None, default:
None) - Notification title.Noneomits the title. - body (str | None, default:
None) - Notification body.Noneomits the body. - payload (str | None, default:
None) - Application-defined string returned with tap and action events. The service does not interpret this value.Noneattaches no payload. - actions (list[NotificationAction] | None, default:
None) - Action buttons; seeNotificationActionfor platform support and background-response behavior. - options (NotificationOptions | None, default:
None) - Additional per-platform details; seeNotificationOptions. - start_type (AndroidServiceStartType | None, default:
None) - Native service restart policy; seeAndroidServiceStartType. This does not control restarting Python tasks. - service_types (list[AndroidForegroundServiceType] | None, default:
None) - Kinds of work performed by the service; seeAndroidForegroundServiceType. Must match the manifest declarations and permissions.Noneor an empty list uses the manifest's service types.
Raises:
- NotificationUnsupportedPlatformException - If called on a platform other than Android, where foreground services don't exist.
- NotificationInvalidArgumentException - If
idis0. - NotificationInvalidArgumentException - If
iddoesn't fit a 32-bit signed integer. - NotificationInvalidArgumentException - If a value in
actionsoroptionsis invalid. - NotificationException - If the bridge reports another failure.
stop_foreground_serviceasync
stop_foreground_service() -> NoneStop the Android foreground service started by this extension.
Removes the service's foreground notification. It does not terminate Python tasks you started; stop the associated application work yourself. Does nothing on other platforms, where no foreground service can run.
Raises:
- NotificationException - If the bridge reports initialization or operation failure.
update_windows_progressasync
update_windows_progress(
id: int, progress: WindowsProgress
) -> boolUpdate the progress bar of a shown Windows notification in place.
Unlike showing the notification again, the update doesn't pop the toast up
again. The notification must already have been shown with
WindowsOptions.progress; to advance it, change
the values of the same progress object and pass it here.
Parameters:
- id (int) - Identifier of the notification to update.
- progress (WindowsProgress) - The progress to show.
Returns:
- bool - Whether the notification was updated;
Falsewhen it is no longer shown, such as after the user dismissed it.
Raises:
- NotificationUnsupportedPlatformException - If called on a platform other than Windows, including a web app opened on Windows.
- NotificationInvalidArgumentException - If
iddoesn't fit a 32-bit signed integer. - NotificationInvalidArgumentException - If
progressis invalid, such as avalueabove itsmax. - NotificationException - If the bridge reports another failure.
import flet_notifications as ftn
progress = ftn.WindowsProgress(status="Downloading...", label="0/10")
await notifications.show(
id=7,
title="report.pdf",
options=ftn.NotificationOptions(
windows=ftn.WindowsOptions(progress=progress)
),
)
for step in range(1, 11):
progress.value = step * 10
progress.label = f"{step}/10"
await notifications.update_windows_progress(7, progress)