Skip to main content

Native local notifications for Flet apps (Android)

Project description

flet-android-notifications

Native Android notifications for Flet apps. Bridges Python to the flutter_local_notifications plugin through a custom Flet extension.

Flet has no built-in notification support, and Python-side approaches (plyer, Pyjnius) fail because Flet's Python process is sandboxed from Android APIs.

Install

pip install flet-android-notifications

Add to your pyproject.toml:

[project]
dependencies = ["flet>=0.80.5", "flet-android-notifications"]

[tool.flet.android.permission]
"android.permission.POST_NOTIFICATIONS" = true
"android.permission.SCHEDULE_EXACT_ALARM" = true      # for scheduled/periodic
"android.permission.RECEIVE_BOOT_COMPLETED" = true     # survive reboots

[tool.flet.app]
exclude = ["flet_android_notifications"]

[tool.flet.dev_packages]
flet-android-notifications = "flet_android_notifications"

Quick start

from datetime import datetime, timedelta
import flet as ft
from flet_android_notifications import FletAndroidNotifications

def main(page: ft.Page):
    notifications = FletAndroidNotifications()

    async def send(e):
        await notifications.request_permissions()
        await notifications.show_notification(
            notification_id=1, title="Hello", body="It works!",
        )

    page.add(ft.Button(content="Send", on_click=send))

ft.run(main)

Instantiate FletAndroidNotifications once. Don't add it to page.overlay or page.controls — it's a service, not a visual control.

See examples/ for more: simple, action buttons, scheduled, styles, periodic, timeout, query, foreground service.

API overview

Core methods

Method Description
show_notification(id, title, body, ...) show a notification immediately
schedule_notification(id, title, body, scheduled_time, ...) fire at a future time via AlarmManager
periodically_show(id, title, body, repeat_interval, ...) repeat every minute / hour / day / week
periodically_show_with_duration(id, title, body, duration_seconds, ...) repeat at a custom interval
start_foreground_service(id, title, body, ...) start a foreground service with persistent notification
stop_foreground_service() stop the foreground service and remove its notification
cancel(notification_id) cancel one notification
cancel_all() cancel all notifications

Query methods

Method Returns
get_active_notifications() list[dict] — currently displayed (id, title, body, channel_id, payload)
get_pending_notifications() list[dict] — scheduled/periodic (id, title, body, payload)

Permission methods

Method Returns
request_permissions() bool — POST_NOTIFICATIONS (Android 13+)
request_exact_alarm_permission() bool — SCHEDULE_EXACT_ALARM (Android 14+)

Tap callback

import json

def on_tap(e):
    data = json.loads(e.data)  # {"payload": "...", "action_id": "..."}

notifications = FletAndroidNotifications(on_notification_tap=on_tap)

action_id is "" when the body is tapped (not an action button).


Notification parameters

show_notification, schedule_notification, periodically_show, and periodically_show_with_duration all share a common set of parameters. Only the required ones differ per method.

Required parameters

Parameter show schedule periodically_show periodically_show_with_duration
notification_id int int int int
title str str str str
body str str str str
scheduled_time datetime
repeat_interval str
duration_seconds int|float

repeat_interval is one of "every_minute", "hourly", "daily", "weekly".

Common optional parameters

These work on all four methods above.

Basics:

Parameter Type Default Description
payload str "" returned in tap callback
actions list[dict] None buttons: [{"id": "...", "title": "..."}]
importance str "high" none, min, low, default, high, max
timeout_after int|None None auto-dismiss after N milliseconds
category str|None None notification type hint for DND filtering

Channel:

Parameter Type Default
channel_id str "flet_notifications"
channel_name str "Flet Notifications"
channel_description str "Notifications from Flet app"
channel_bypass_dnd bool False

Appearance:

Parameter Type Default Description
icon str|None None drawable resource for small icon
large_icon str|None None thumbnail on right side
large_icon_type str "drawable_resource" or "file_path"
color str|None None hex accent color, e.g. "#FF5722"
colorized bool False color as background (foreground service only)
sub_text str|None None small text below content
visibility str|None None "public", "private", or "secret"

Behavior:

Parameter Type Default Description
play_sound bool True play notification sound
enable_vibration bool True vibrate
sound str|None None raw resource name (e.g. "alert_tone")
vibration_pattern list[int]|None None e.g. [0, 500, 200, 500]
ongoing bool False can't be swiped away
auto_cancel bool True dismiss on tap
silent bool False suppress sound and vibration
only_alert_once bool False alert on first show only

Styles and progress:

Parameter Type Default Description
style BigTextStyle|BigPictureStyle|InboxStyle|None None rich expandable style
show_progress bool False show progress bar
max_progress int 0 max value
progress int 0 current value
indeterminate bool False spinning progress bar

Grouping:

Parameter Type Default Description
group_key str|None None bundle notifications together
set_as_group_summary bool False this is the group summary
group_alert_behavior str "all" "all", "summary", "children"

Schedule-only parameters

These only apply to schedule_notification:

Parameter Type Default Description
schedule_mode str "inexact_allow_while_idle" see table below
match_date_time_components str|None None "time" (daily), "day_of_week_and_time" (weekly), "day_of_month_and_time" (monthly), "date_and_time" (yearly)

Schedule modes:

Mode Exact alarm permission? Fires in Doze?
"inexact" no no
"inexact_allow_while_idle" no yes
"exact" yes no
"exact_allow_while_idle" yes yes
"alarm_clock" yes yes

Foreground service

For persistent background tasks (music, GPS tracking, uploads) that require a visible notification:

await notifications.start_foreground_service(
    notification_id=1,  # must not be 0
    title="Uploading",
    body="3 files remaining...",
    foreground_service_types=["special_use"],
    ongoing=True,
)

# when done:
await notifications.stop_foreground_service()

Parameters specific to foreground service:

Parameter Type Default Description
start_type str "start_sticky" start_sticky, start_not_sticky, start_sticky_compatibility, start_redeliver_intent
foreground_service_types list[str]|None None e.g. ["special_use"], ["location"], ["media_playback"]

All other notification parameters (channel, appearance, behavior, etc.) are the same as show_notification.

Important:

  • notification_id must not be 0 (Android constraint)
  • The notification is not removed by cancel() or cancel_all() — use stop_foreground_service()
  • Requires FOREGROUND_SERVICE permission plus a type-specific permission (e.g. FOREGROUND_SERVICE_SPECIAL_USE)

AndroidManifest.xml — add inside <application>:

<service android:name="com.dexterous.flutterlocalnotifications.ForegroundService"
    android:exported="false"
    android:foregroundServiceType="specialUse" />

Adjust foregroundServiceType to match your use case (e.g. location, mediaPlayback).

pyproject.toml permissions:

[tool.flet.android.permission]
"android.permission.FOREGROUND_SERVICE" = true
"android.permission.FOREGROUND_SERVICE_SPECIAL_USE" = true

Styles

from flet_android_notifications import BigTextStyle, BigPictureStyle, InboxStyle

# expandable long text
style=BigTextStyle("Full text here...", content_title="Expanded title")

# full-width image when expanded
style=BigPictureStyle(drawable_resource="splash")

# list of lines
style=InboxStyle(["Line 1", "Line 2", "Line 3"], summary_text="3 items")

Building the APK

# first build — generates Flutter template, may fail at Gradle
flet build apk -v

# patch desugaring into build/flutter/android/app/build.gradle.kts:
#   android { compileOptions { isCoreLibraryDesugaringEnabled = true } }
#   dependencies { coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4") }

# rebuild
flet build apk -v

The desugaring patch is needed because flutter_local_notifications v19+ uses Java 8 APIs. Apply once per clean build directory.

AndroidManifest.xml for scheduled notifications

Register BroadcastReceivers inside <application> in build/flutter/android/app/src/main/AndroidManifest.xml so scheduled notifications survive reboots:

<receiver android:exported="false"
    android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationReceiver" />
<receiver android:exported="false"
    android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
        <action android:name="android.intent.action.QUICKBOOT_POWERON" />
        <action android:name="com.htc.intent.action.QUICKBOOT_POWERON" />
    </intent-filter>
</receiver>

Installing on device

Always full-uninstall before installing. Flet caches the extracted Python environment:

adb uninstall com.yourapp.package
adb install build/apk/app-release.apk

On Windows, set PYTHONIOENCODING=utf-8 before building to avoid Unicode crashes.

Custom resources

  • Small icons: vector drawable XML in res/drawable/ (24dp, white on transparent)
  • Sounds: audio files in res/raw/, reference by name without extension: sound="alert_tone"

Add res/raw/keep.xml to prevent resource stripping:

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

Sound is permanently bound to a channel at creation. Change the sound by using a different channel_id.

Samsung OneUI notes

  • Color: Samsung's system palette overrides the color parameter. Works on stock Android, ignored on Samsung.
  • Brief mode: Samsung's compact notification view hides expanded content. Swipe down to expand.
  • colorized: only works for foreground service / media-style notifications (all OEMs).

Limitations

  • Android only. iOS support would need DarwinNotificationDetails in the Dart layer.
  • Desktop: the service instantiates without error but notifications won't appear.

How it works

Python app → FletAndroidNotifications (ft.Service)
  → _invoke_method() over Flet protocol
    → NotificationsService (FletService, Dart)
      → flutter_local_notifications plugin → Android NotificationManager

The extension ships as a Python package with a flutter/ directory containing the Dart code. flet build apk discovers it in site-packages and includes it as a Flutter path dependency.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

flet_android_notifications-0.7.6.tar.gz (17.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

flet_android_notifications-0.7.6-py3-none-any.whl (18.5 kB view details)

Uploaded Python 3

File details

Details for the file flet_android_notifications-0.7.6.tar.gz.

File metadata

File hashes

Hashes for flet_android_notifications-0.7.6.tar.gz
Algorithm Hash digest
SHA256 ae7752f7fd34d1c97a640a68a481710c0ba1945aabd06e9a95e497ad5b10c1d1
MD5 661f9b2c4423b7acd42477c44bac6476
BLAKE2b-256 be87bbc55a9ad2d7c663f822b982998e21c6e742342bcf89900ccd9a51f9371c

See more details on using hashes here.

File details

Details for the file flet_android_notifications-0.7.6-py3-none-any.whl.

File metadata

File hashes

Hashes for flet_android_notifications-0.7.6-py3-none-any.whl
Algorithm Hash digest
SHA256 0a2ee1afb2bffa8ab0dfba0049a08dc1b021d51704f7540c66cf2ce0c16a5aa9
MD5 bf3fec9f9676ea404a17e56e94b14044
BLAKE2b-256 70f8d5d77b9c29658dd676ea6bad5ea20ba8708007192f82b4db2f65ee0a9860

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page