I'm working on a Python app using Kivy and want to implement notifications without relying on an online API. My goal is to create local notifications that appear in the system's notification area (e.g., Android notification tray).
What I’ve Tried:
I researched this feature and found that many solutions use third-party APIs like Firebase or OneSignal, which require internet connectivity. However, I want to keep the functionality offline.
I tried using pyjnius for Android notifications but ran into issues understanding how to use the Android NotificationManager class correctly, and the answers that have been posted here don't work anymore because they're out-dated for higher versions of android
After extensive rebuilding and reading, I discovered that the only way to achieve this was through Java. Thankfully, Pyjnius provides a wrapper for Java classes. By carefully going through the Android Developer Notification docs and some GitHub discussions, I realized that the issue stems from Android 13 introducing new notification procedures, causing older implementations to fail.
Prerequisites:
In your buildozer.spec
file, ensure you include the following:
# Add pyjnius so it's packaged with the build
requirements = python3,kivy,pyjnius
# Add permission for notifications
android.permissions = POST_NOTIFICATIONS
# Required API level and dependencies (write exactly as shown, no quotation marks)
android.api = 31
android.gradle_dependencies = androidx.core:core:1.6.0
android.enable_androidx = True
In your main.py
file:
# Request notification permission
from android.permissions import request_permissions, Permission
permissions = [Permission.POST_NOTIFICATIONS]
request_permissions(permissions)
# Import JAVA classes through Pyjnius
from jnius import autoclass
PythonActivity = autoclass('org.kivy.android.PythonActivity')
NotificationManager = autoclass('android.app.NotificationManager')
NotificationCompat = autoclass('androidx.core.app.NotificationCompat')
NotificationChannel = autoclass('android.app.NotificationChannel')
NotificationCompatBuilder = autoclass('androidx.core.app.NotificationCompat$Builder')
BuildVersion = autoclass('android.os.Build$VERSION')
# Get the app's context and notification manager
context = PythonActivity.mActivity
notification_manager = context.getSystemService(context.NOTIFICATION_SERVICE)
# For Android 8.0+ Notification Channel is required
channel_id = "default_channel"
if BuildVersion.SDK_INT >= 26:
channel = NotificationChannel(
channel_id,
"Default Channel",
NotificationManager.IMPORTANCE_HIGH # Shows briefly before moving to the tray
)
notification_manager.createNotificationChannel(channel)
# Build the notification
builder = NotificationCompatBuilder(context, channel_id)
builder.setContentTitle("This is my notification title")
builder.setContentText("This is the notification message")
builder.setSmallIcon(autoclass("android.R$drawable").ic_dialog_info) # Use a valid drawable
builder.setDefaults(NotificationCompat.DEFAULT_ALL)
builder.setPriority(NotificationCompat.PRIORITY_HIGH) # For pre-Android 8 devices
# Show the notification
notification_manager.notify(1, builder.build())
I found the above approach a bit wordly, so I created a package to simplifiy the process. It also includes support for advanced notification styles:
from android_notify.core import send_notification
send_notification("Hello", "This is a basic notification.")