Plyer
Plyer is a platform-independent Python API that provides a unified interface for accessing hardware features and platform-dependent functionalities across various operating systems, including Android, iOS, macOS, Linux, and Windows. It is actively managed by the Kivy Team and, while suitable for Kivy applications, can be used independently. The library wraps existing platform-specific APIs and often leverages external tools like PyJNIus for Android and PyObjus for iOS/macOS to achieve its cross-platform compatibility. The current version is 2.1.0, with ongoing development and maintenance by the Kivy community.
Common errors
-
AttributeError: 'NoneType' object has no attribute 'notify' (or similar for other features)
cause This error typically occurs when Plyer fails to load a backend for the requested API on the current platform, often because the feature is not supported or a necessary underlying system component is missing.fixVerify that the feature you are trying to use is supported on your operating system. For desktop notifications on Linux, ensure a notification daemon (e.g., `dunst`, `notification-daemon`) is running. For mobile, ensure all required permissions and backend libraries (e.g., PyJNIus, PyObjus) are correctly configured in your mobile build environment. -
Notifications do not appear on Windows or have a generic icon.
cause On Windows, the `app_icon` parameter for `notification.notify()` specifically requires a path to an `.ico` file. Using other image formats (e.g., `.png`, `.jpg`) will result in no icon or a default system icon.fixConvert your application icon to the `.ico` format and provide the absolute path to this `.ico` file in the `app_icon` parameter. Ensure the path is accessible to the application. -
GPS/Camera/Vibrator features are not working on Android/iOS.
cause Mobile operating systems require explicit permissions from the user for accessing hardware features like GPS, camera, or vibrator. These permissions must be declared in your application's manifest (Android) or `Info.plist` (iOS).fixFor Android, add relevant permissions (e.g., `android.permission.ACCESS_FINE_LOCATION`, `android.permission.CAMERA`, `android.permission.VIBRATE`) to your `buildozer.spec` file. For iOS, specify privacy-related keys (e.g., `NSLocationWhenInUseUsageDescription`) in your `Info.plist` via `kivy-ios` or directly.
Warnings
- gotcha Not all Plyer APIs are available or fully functional on every platform. For instance, GPS features are primarily for mobile, and some desktop functionalities might be limited.
- breaking When building for mobile platforms like Android or iOS, `plyer` often requires platform-specific backend libraries (e.g., PyJNIus for Android, PyObjus for iOS/macOS). These are not installed automatically with `pip install plyer` and must be managed by your mobile build toolchain (e.g., `python-for-android`, `kivy-ios`).
- gotcha Some features, particularly sensor-related ones like GPS, are asynchronous and require callbacks to retrieve data. Users expecting immediate, synchronous results may encounter issues or incorrect usage patterns.
Install
-
pip install plyer -
pip install plyer[tests]
Imports
- notification
from plyer import notification
- gps
from plyer import gps
- battery
from plyer import battery
- filechooser
from plyer import filechooser
Quickstart
from plyer import notification
import time
if __name__ == '__main__':
print("Sending desktop notification...")
try:
notification.notify(
title='Hello from Plyer!',
message='This is a cross-platform notification example.',
app_name='Plyer Quickstart',
# app_icon='path/to/icon.ico', # On Windows, must be .ico format
timeout=5 # Notification will disappear after 5 seconds
)
print("Notification sent. Check your system tray.")
except Exception as e:
print(f"Failed to send notification: {e}")
print("Ensure your system supports desktop notifications and any backend dependencies are met.")
# Example for a mobile-focused feature (conceptual, won't run on desktop without backend)
# from plyer import battery
# try:
# info = battery.status
# print(f"Battery Status: {info['percent']}% {'(charging)' if info['isCharging'] else ''}")
# except Exception as e:
# print(f"Could not get battery info: {e}")