android-notify 1.61.2.dev0__tar.gz → 1.61.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/PKG-INFO +59 -138
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/README.md +57 -136
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/config.py +1 -2
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/core.py +4 -3
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/internal/android.py +9 -59
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/internal/channels.py +6 -19
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/internal/facade.py +0 -53
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/internal/helper.py +1 -4
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/internal/java_classes.py +17 -13
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/internal/permissions.py +22 -9
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/sword.py +4 -6
- android_notify-1.61.3/android_notify/tests/test_notification_sound.py +24 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/widgets/images.py +1 -2
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/widgets/texts.py +1 -5
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify.egg-info/PKG-INFO +59 -138
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify.egg-info/SOURCES.txt +0 -2
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify.egg-info/requires.txt +1 -1
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/pyproject.toml +3 -3
- android_notify-1.61.2.dev0/android_notify/tests/flet/basic/src/core.py +0 -221
- android_notify-1.61.2.dev0/android_notify/tests/flet/flet-working/src/core.py +0 -221
- android_notify-1.61.2.dev0/android_notify/tests/test_notification_sound.py +0 -67
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/__init__.py +0 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/__main__.py +0 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/base.py +0 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/fallback-icons/flet-appicon.png +0 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/fallback-icons/pydroid3-appicon.png +0 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/internal/an_types.py +0 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/internal/intents.py +0 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/internal/logger.py +0 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/styles.py +0 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/tests/__init__.py +0 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/tests/android_notify_test.py +0 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/tests/base_test.py +0 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/tests/flet/adv/main.py +0 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/tests/flet/adv/tests/__init__.py +0 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/tests/flet/adv/tests/test_android_notify_full.py +0 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/tests/flet/basic/src/main.py +0 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/tests/flet/flet-working/src/main.py +0 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/tests/main.py +0 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/tests/p4a/hook.py +0 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/tests/serivces/wallpaper.py +0 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/tests/test_basic_notifications.py +0 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/tests/test_notification_actions.py +0 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/tests/test_notification_appearance.py +0 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/tests/test_notification_behavior.py +0 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/tests/test_notification_channels.py +0 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/tests/test_notification_clear.py +0 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/tests/test_notification_permission.py +0 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/tests/test_notification_progress.py +0 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify/tests/test_notification_styles.py +0 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify.egg-info/dependency_links.txt +0 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify.egg-info/entry_points.txt +0 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/android_notify.egg-info/top_level.txt +0 -0
- {android_notify-1.61.2.dev0 → android_notify-1.61.3}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: android-notify
|
|
3
|
-
Version: 1.61.
|
|
3
|
+
Version: 1.61.3
|
|
4
4
|
Summary: A Python package that simplifies creating Android notifications in Kivy and Flet apps.
|
|
5
5
|
Author-email: Fabian <fector101@yahoo.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -18,7 +18,7 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
|
18
18
|
Description-Content-Type: text/markdown
|
|
19
19
|
Requires-Dist: pyjnius
|
|
20
20
|
Provides-Extra: dev
|
|
21
|
-
Requires-Dist: kivy
|
|
21
|
+
Requires-Dist: kivy; extra == "dev"
|
|
22
22
|
|
|
23
23
|
<div align="center">
|
|
24
24
|
<br>
|
|
@@ -53,6 +53,8 @@ The Android Notify package provides a simple yet comprehensive way to create and
|
|
|
53
53
|
- Persistent notifications
|
|
54
54
|
- Click handlers and callbacks
|
|
55
55
|
- Cancel Notifications
|
|
56
|
+
- Use [Custom Sound](https://android-notify.vercel.app/advanced-methods#custom-sound)
|
|
57
|
+
- Vibration [section](https://android-notify.vercel.app/advanced-methods#vibration)
|
|
56
58
|
|
|
57
59
|
## Quick Start
|
|
58
60
|
|
|
@@ -80,25 +82,48 @@ In your **`buildozer.spec`** file, ensure you include the following:
|
|
|
80
82
|
|
|
81
83
|
```ini
|
|
82
84
|
# Add pyjnius so ensure it's packaged with the build
|
|
83
|
-
requirements = python3, kivy, pyjnius, android-notify
|
|
85
|
+
requirements = python3, kivy, pyjnius, android-notify
|
|
84
86
|
# Add permission for notifications
|
|
85
87
|
android.permissions = POST_NOTIFICATIONS
|
|
88
|
+
|
|
89
|
+
# Required dependency (write exactly as shown, no quotation marks)
|
|
90
|
+
android.gradle_dependencies = androidx.core:core-ktx:1.15.0
|
|
91
|
+
android.enable_androidx = True
|
|
92
|
+
android.api = 35
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
</details>
|
|
96
|
+
|
|
97
|
+
<details>
|
|
98
|
+
<summary><b>Desktop</b></summary>
|
|
99
|
+
<br/>
|
|
100
|
+
|
|
101
|
+
For IDE IntelliSense Can be installed via `pip install`:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
pip install android_notify
|
|
105
|
+
android-notify -v
|
|
86
106
|
```
|
|
87
107
|
|
|
88
108
|
</details>
|
|
89
109
|
|
|
110
|
+
------
|
|
111
|
+
## Installing without Androidx
|
|
112
|
+
How to use without `gradle_dependencies`
|
|
113
|
+
Use `android-notify==1.61.3.dev0` to install via `pip`
|
|
114
|
+
|
|
90
115
|
|
|
91
116
|
<details>
|
|
92
117
|
<summary><b>Flet apps:</b></summary>
|
|
93
118
|
<br/>
|
|
94
119
|
|
|
95
|
-
In your `pyproject.toml` file, ensure you include the following:
|
|
120
|
+
In your `pyproject.toml` file, ensure you include the following:
|
|
96
121
|
|
|
97
122
|
|
|
98
123
|
```toml
|
|
99
124
|
[tool.flet.android]
|
|
100
125
|
dependencies = [
|
|
101
|
-
"pyjnius","android-notify==1.61.
|
|
126
|
+
"pyjnius","android-notify==1.61.3.dev0"
|
|
102
127
|
]
|
|
103
128
|
|
|
104
129
|
[tool.flet.android.permission]
|
|
@@ -108,7 +133,16 @@ dependencies = [
|
|
|
108
133
|
|
|
109
134
|
</details>
|
|
110
135
|
|
|
136
|
+
<details>
|
|
137
|
+
<summary><b>In Kivy</b></summary>
|
|
138
|
+
<br/>
|
|
139
|
+
|
|
140
|
+
```ini
|
|
141
|
+
# buildozer.spec
|
|
142
|
+
requirements = python3, kivy, pyjnius, android-notify==1.61.3.dev0
|
|
143
|
+
```
|
|
111
144
|
|
|
145
|
+
</details>
|
|
112
146
|
|
|
113
147
|
<details>
|
|
114
148
|
|
|
@@ -116,10 +150,10 @@ dependencies = [
|
|
|
116
150
|
<br/>
|
|
117
151
|
|
|
118
152
|
On the [pydroid 3](https://play.google.com/store/apps/details?id=ru.iiec.pydroid3) mobile app for running python code you can test some features.
|
|
119
|
-
- In pip section where you're asked to insert `Libary name` paste `android-notify==1.61.
|
|
153
|
+
- In pip section where you're asked to insert `Libary name` paste `android-notify==1.61.3.dev0`
|
|
120
154
|
- Minimal working example
|
|
121
155
|
```py
|
|
122
|
-
# Testing with `android-notify==1.61.
|
|
156
|
+
# Testing with `android-notify==1.61.3.dev0` on pydroid
|
|
123
157
|
from kivy.app import App
|
|
124
158
|
from kivy.uix.boxlayout import BoxLayout
|
|
125
159
|
from kivy.uix.button import Button
|
|
@@ -146,9 +180,7 @@ class AndroidNotifyDemoApp(App):
|
|
|
146
180
|
def send_notification(self, *args):
|
|
147
181
|
Notification(
|
|
148
182
|
title="Hello from Android Notify",
|
|
149
|
-
message="This is a basic notification."
|
|
150
|
-
channel_id="android_notify_demo",
|
|
151
|
-
channel_name="Android Notify Demo"
|
|
183
|
+
message="This is a basic notification."
|
|
152
184
|
).send()
|
|
153
185
|
|
|
154
186
|
|
|
@@ -159,134 +191,13 @@ if __name__ == "__main__":
|
|
|
159
191
|
</details>
|
|
160
192
|
|
|
161
193
|
|
|
162
|
-
<details>
|
|
163
|
-
|
|
164
|
-
<summary><b>Desktop</b></summary>
|
|
165
|
-
<br/>
|
|
166
|
-
|
|
167
|
-
For IDE IntelliSense Can be installed via `pip install`:
|
|
168
|
-
|
|
169
|
-
```bash
|
|
170
|
-
pip install android_notify
|
|
171
|
-
android-notify -v
|
|
172
|
-
```
|
|
173
|
-
</details>
|
|
174
194
|
|
|
175
195
|
## Documentation
|
|
176
|
-
For Dev Version
|
|
177
|
-
```ini
|
|
178
|
-
requirements = python3, kivy, pyjnius, https://github.com/Fector101/android_notify/archive/without-androidx.zip
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
<details>
|
|
182
|
-
<summary> <b> To talk to BroadCast Listener From Buttons </b> </summary>
|
|
183
|
-
|
|
184
|
-
- Make things happen without being in your app
|
|
185
|
-
```python
|
|
186
|
-
from android_notify import Notification
|
|
187
|
-
notification = Notification(title="Receiver Notification")
|
|
188
|
-
notification.addButton(text="Stop", receiver_name="CarouselReceiver", action="ACTION_STOP")
|
|
189
|
-
notification.addButton(text="Skip", receiver_name="CarouselReceiver", action="ACTION_SKIP")
|
|
190
|
-
```
|
|
191
|
-
You can use this [wiki](https://github.com/Fector101/android_notify/wiki/How-to-Use-with-Broadcast-Listener) as a guide create a broadcast listener
|
|
192
|
-
</details>
|
|
193
|
-
|
|
194
|
-
<details>
|
|
195
|
-
<summary> <b> To use colored text in your notifications </b> </summary>
|
|
196
|
-
|
|
197
|
-
- Copy the [res](https://github.com/Fector101/android_notify/tree/main/android_notify/res) folder to your app path.
|
|
198
|
-
- Lastly in your `buildozer.spec` file
|
|
199
|
-
Add `source.include_exts = xml` and `android.add_resources = # path you pasted`
|
|
200
|
-
```python
|
|
201
|
-
# Use Hex Code to be Safe
|
|
202
|
-
n = Notification(title="Title and Message Color", message="Testing",title_color="red")
|
|
203
|
-
n.send()
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
</details>
|
|
207
|
-
|
|
208
|
-
<details>
|
|
209
|
-
<summary> <b>To use Custom Sounds </b> </summary>
|
|
210
|
-
|
|
211
|
-
**Option 1: Audio files bundled in `res/raw`**
|
|
212
|
-
|
|
213
|
-
- Put audio files in `res/raw` folder,
|
|
214
|
-
- Then from `buildozer.spec` point to res folder `android.add_resources = res`
|
|
215
|
-
- and includes it's format `source.include_exts = wav`.
|
|
216
|
-
|
|
217
|
-
Lastly From the code
|
|
218
|
-
```py
|
|
219
|
-
# Create a custom notification channel with a unique sound resource for android 8+
|
|
220
|
-
Notification.createChannel(
|
|
221
|
-
id="weird_sound_tester",
|
|
222
|
-
name="Weird Sound Tester",
|
|
223
|
-
description="A test channel for custom sounds from the res/raw folder.",
|
|
224
|
-
res_sound_name="sneeze" # file name without .wav or .mp3
|
|
225
|
-
)
|
|
226
|
-
|
|
227
|
-
# Send a notification through the created channel
|
|
228
|
-
n=Notification(
|
|
229
|
-
title="Custom Sound Notification",
|
|
230
|
-
message="This tests playback of a custom sound (sneeze.wav) stored in res/raw.",
|
|
231
|
-
channel_id="weird_sound_tester" # important tells notification to use right channel
|
|
232
|
-
)
|
|
233
|
-
n.setSound("sneeze")# for android 7 below
|
|
234
|
-
n.send()
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
**Option 2: Local file path or URI (`sound_path`)**
|
|
238
|
-
|
|
239
|
-
You can use a local audio file, a `content://`, `file://`, or `android.resource://` URI directly:
|
|
240
|
-
|
|
241
|
-
```py
|
|
242
|
-
# Using a local file path
|
|
243
|
-
Notification.createChannel(
|
|
244
|
-
id="local_sound",
|
|
245
|
-
name="Local Sound",
|
|
246
|
-
sound_path="/storage/emulated/0/Download/alert.mp3"
|
|
247
|
-
)
|
|
248
|
-
|
|
249
|
-
# Using a content URI (e.g., from media store)
|
|
250
|
-
Notification.createChannel(
|
|
251
|
-
id="uri_sound",
|
|
252
|
-
name="URI Sound",
|
|
253
|
-
sound_path="content://media/external/audio/media/123"
|
|
254
|
-
)
|
|
255
|
-
|
|
256
|
-
# Send notification with custom sound path
|
|
257
|
-
n = Notification(
|
|
258
|
-
title="Custom Sound",
|
|
259
|
-
message="Playing from local path",
|
|
260
|
-
channel_id="local_sound"
|
|
261
|
-
)
|
|
262
|
-
n.setSound(sound_path="/storage/emulated/0/Download/alert.mp3")
|
|
263
|
-
n.send()
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
Private files (e.g., in app's `data/` directory) are automatically copied to external storage before playing.
|
|
267
|
-
</details>
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
<details>
|
|
271
|
-
<summary> <b> Vibrate feature</b> </summary>
|
|
272
|
-
|
|
196
|
+
For Dev Version usage
|
|
273
197
|
```ini
|
|
274
|
-
|
|
275
|
-
android.permissions = VIBRATE
|
|
276
|
-
```
|
|
277
|
-
|
|
278
|
-
```python
|
|
279
|
-
Notification.createChannel(id='shake', name="Shake Passage", vibrate=True)
|
|
280
|
-
|
|
281
|
-
n=Notification(title='Vibrate',channel_id='shake')
|
|
282
|
-
n.setVibrate() # for less than android 8
|
|
283
|
-
n.fVibrate() # To Force Vibrate (when user turned off in settings)
|
|
284
|
-
n.send()
|
|
198
|
+
requirements = python3, kivy, pyjnius, https://github.com/Fector101/android_notify/archive/main.zip
|
|
285
199
|
```
|
|
286
200
|
|
|
287
|
-
</details>
|
|
288
|
-
|
|
289
|
-
|
|
290
201
|
<details>
|
|
291
202
|
<summary> <b> Add Data to Notification</b> </summary>
|
|
292
203
|
|
|
@@ -318,9 +229,19 @@ from android_notify import Notification, NotificationHandler
|
|
|
318
229
|
|
|
319
230
|
## ☕ Support the Project
|
|
320
231
|
|
|
321
|
-
If you find this project helpful,
|
|
322
|
-
|
|
232
|
+
If you find this project helpful, your support would help me continue working on open-source projects
|
|
233
|
+
[donate](https://www.buymeacoffee.com/fector101)
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
## Bug Reports & Feature Requests
|
|
237
|
+
|
|
238
|
+
Found a bug or have an idea for a new feature?
|
|
239
|
+
Feel free to open an issue [here](https://reference-url-citation.invalid/0)
|
|
240
|
+
|
|
241
|
+
When reporting a bug, try to include:
|
|
242
|
+
- Device name
|
|
243
|
+
- Android version
|
|
244
|
+
- Steps to reproduce the issue
|
|
245
|
+
- Screenshots or logs (if possible)
|
|
323
246
|
|
|
324
|
-
|
|
325
|
-
<img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" height="60">
|
|
326
|
-
</a>
|
|
247
|
+
Feature suggestions are also welcome.
|
|
@@ -31,6 +31,8 @@ The Android Notify package provides a simple yet comprehensive way to create and
|
|
|
31
31
|
- Persistent notifications
|
|
32
32
|
- Click handlers and callbacks
|
|
33
33
|
- Cancel Notifications
|
|
34
|
+
- Use [Custom Sound](https://android-notify.vercel.app/advanced-methods#custom-sound)
|
|
35
|
+
- Vibration [section](https://android-notify.vercel.app/advanced-methods#vibration)
|
|
34
36
|
|
|
35
37
|
## Quick Start
|
|
36
38
|
|
|
@@ -58,25 +60,48 @@ In your **`buildozer.spec`** file, ensure you include the following:
|
|
|
58
60
|
|
|
59
61
|
```ini
|
|
60
62
|
# Add pyjnius so ensure it's packaged with the build
|
|
61
|
-
requirements = python3, kivy, pyjnius, android-notify
|
|
63
|
+
requirements = python3, kivy, pyjnius, android-notify
|
|
62
64
|
# Add permission for notifications
|
|
63
65
|
android.permissions = POST_NOTIFICATIONS
|
|
66
|
+
|
|
67
|
+
# Required dependency (write exactly as shown, no quotation marks)
|
|
68
|
+
android.gradle_dependencies = androidx.core:core-ktx:1.15.0
|
|
69
|
+
android.enable_androidx = True
|
|
70
|
+
android.api = 35
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
</details>
|
|
74
|
+
|
|
75
|
+
<details>
|
|
76
|
+
<summary><b>Desktop</b></summary>
|
|
77
|
+
<br/>
|
|
78
|
+
|
|
79
|
+
For IDE IntelliSense Can be installed via `pip install`:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
pip install android_notify
|
|
83
|
+
android-notify -v
|
|
64
84
|
```
|
|
65
85
|
|
|
66
86
|
</details>
|
|
67
87
|
|
|
88
|
+
------
|
|
89
|
+
## Installing without Androidx
|
|
90
|
+
How to use without `gradle_dependencies`
|
|
91
|
+
Use `android-notify==1.61.3.dev0` to install via `pip`
|
|
92
|
+
|
|
68
93
|
|
|
69
94
|
<details>
|
|
70
95
|
<summary><b>Flet apps:</b></summary>
|
|
71
96
|
<br/>
|
|
72
97
|
|
|
73
|
-
In your `pyproject.toml` file, ensure you include the following:
|
|
98
|
+
In your `pyproject.toml` file, ensure you include the following:
|
|
74
99
|
|
|
75
100
|
|
|
76
101
|
```toml
|
|
77
102
|
[tool.flet.android]
|
|
78
103
|
dependencies = [
|
|
79
|
-
"pyjnius","android-notify==1.61.
|
|
104
|
+
"pyjnius","android-notify==1.61.3.dev0"
|
|
80
105
|
]
|
|
81
106
|
|
|
82
107
|
[tool.flet.android.permission]
|
|
@@ -86,7 +111,16 @@ dependencies = [
|
|
|
86
111
|
|
|
87
112
|
</details>
|
|
88
113
|
|
|
114
|
+
<details>
|
|
115
|
+
<summary><b>In Kivy</b></summary>
|
|
116
|
+
<br/>
|
|
117
|
+
|
|
118
|
+
```ini
|
|
119
|
+
# buildozer.spec
|
|
120
|
+
requirements = python3, kivy, pyjnius, android-notify==1.61.3.dev0
|
|
121
|
+
```
|
|
89
122
|
|
|
123
|
+
</details>
|
|
90
124
|
|
|
91
125
|
<details>
|
|
92
126
|
|
|
@@ -94,10 +128,10 @@ dependencies = [
|
|
|
94
128
|
<br/>
|
|
95
129
|
|
|
96
130
|
On the [pydroid 3](https://play.google.com/store/apps/details?id=ru.iiec.pydroid3) mobile app for running python code you can test some features.
|
|
97
|
-
- In pip section where you're asked to insert `Libary name` paste `android-notify==1.61.
|
|
131
|
+
- In pip section where you're asked to insert `Libary name` paste `android-notify==1.61.3.dev0`
|
|
98
132
|
- Minimal working example
|
|
99
133
|
```py
|
|
100
|
-
# Testing with `android-notify==1.61.
|
|
134
|
+
# Testing with `android-notify==1.61.3.dev0` on pydroid
|
|
101
135
|
from kivy.app import App
|
|
102
136
|
from kivy.uix.boxlayout import BoxLayout
|
|
103
137
|
from kivy.uix.button import Button
|
|
@@ -124,9 +158,7 @@ class AndroidNotifyDemoApp(App):
|
|
|
124
158
|
def send_notification(self, *args):
|
|
125
159
|
Notification(
|
|
126
160
|
title="Hello from Android Notify",
|
|
127
|
-
message="This is a basic notification."
|
|
128
|
-
channel_id="android_notify_demo",
|
|
129
|
-
channel_name="Android Notify Demo"
|
|
161
|
+
message="This is a basic notification."
|
|
130
162
|
).send()
|
|
131
163
|
|
|
132
164
|
|
|
@@ -137,134 +169,13 @@ if __name__ == "__main__":
|
|
|
137
169
|
</details>
|
|
138
170
|
|
|
139
171
|
|
|
140
|
-
<details>
|
|
141
|
-
|
|
142
|
-
<summary><b>Desktop</b></summary>
|
|
143
|
-
<br/>
|
|
144
|
-
|
|
145
|
-
For IDE IntelliSense Can be installed via `pip install`:
|
|
146
|
-
|
|
147
|
-
```bash
|
|
148
|
-
pip install android_notify
|
|
149
|
-
android-notify -v
|
|
150
|
-
```
|
|
151
|
-
</details>
|
|
152
172
|
|
|
153
173
|
## Documentation
|
|
154
|
-
For Dev Version
|
|
155
|
-
```ini
|
|
156
|
-
requirements = python3, kivy, pyjnius, https://github.com/Fector101/android_notify/archive/without-androidx.zip
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
<details>
|
|
160
|
-
<summary> <b> To talk to BroadCast Listener From Buttons </b> </summary>
|
|
161
|
-
|
|
162
|
-
- Make things happen without being in your app
|
|
163
|
-
```python
|
|
164
|
-
from android_notify import Notification
|
|
165
|
-
notification = Notification(title="Receiver Notification")
|
|
166
|
-
notification.addButton(text="Stop", receiver_name="CarouselReceiver", action="ACTION_STOP")
|
|
167
|
-
notification.addButton(text="Skip", receiver_name="CarouselReceiver", action="ACTION_SKIP")
|
|
168
|
-
```
|
|
169
|
-
You can use this [wiki](https://github.com/Fector101/android_notify/wiki/How-to-Use-with-Broadcast-Listener) as a guide create a broadcast listener
|
|
170
|
-
</details>
|
|
171
|
-
|
|
172
|
-
<details>
|
|
173
|
-
<summary> <b> To use colored text in your notifications </b> </summary>
|
|
174
|
-
|
|
175
|
-
- Copy the [res](https://github.com/Fector101/android_notify/tree/main/android_notify/res) folder to your app path.
|
|
176
|
-
- Lastly in your `buildozer.spec` file
|
|
177
|
-
Add `source.include_exts = xml` and `android.add_resources = # path you pasted`
|
|
178
|
-
```python
|
|
179
|
-
# Use Hex Code to be Safe
|
|
180
|
-
n = Notification(title="Title and Message Color", message="Testing",title_color="red")
|
|
181
|
-
n.send()
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
</details>
|
|
185
|
-
|
|
186
|
-
<details>
|
|
187
|
-
<summary> <b>To use Custom Sounds </b> </summary>
|
|
188
|
-
|
|
189
|
-
**Option 1: Audio files bundled in `res/raw`**
|
|
190
|
-
|
|
191
|
-
- Put audio files in `res/raw` folder,
|
|
192
|
-
- Then from `buildozer.spec` point to res folder `android.add_resources = res`
|
|
193
|
-
- and includes it's format `source.include_exts = wav`.
|
|
194
|
-
|
|
195
|
-
Lastly From the code
|
|
196
|
-
```py
|
|
197
|
-
# Create a custom notification channel with a unique sound resource for android 8+
|
|
198
|
-
Notification.createChannel(
|
|
199
|
-
id="weird_sound_tester",
|
|
200
|
-
name="Weird Sound Tester",
|
|
201
|
-
description="A test channel for custom sounds from the res/raw folder.",
|
|
202
|
-
res_sound_name="sneeze" # file name without .wav or .mp3
|
|
203
|
-
)
|
|
204
|
-
|
|
205
|
-
# Send a notification through the created channel
|
|
206
|
-
n=Notification(
|
|
207
|
-
title="Custom Sound Notification",
|
|
208
|
-
message="This tests playback of a custom sound (sneeze.wav) stored in res/raw.",
|
|
209
|
-
channel_id="weird_sound_tester" # important tells notification to use right channel
|
|
210
|
-
)
|
|
211
|
-
n.setSound("sneeze")# for android 7 below
|
|
212
|
-
n.send()
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
**Option 2: Local file path or URI (`sound_path`)**
|
|
216
|
-
|
|
217
|
-
You can use a local audio file, a `content://`, `file://`, or `android.resource://` URI directly:
|
|
218
|
-
|
|
219
|
-
```py
|
|
220
|
-
# Using a local file path
|
|
221
|
-
Notification.createChannel(
|
|
222
|
-
id="local_sound",
|
|
223
|
-
name="Local Sound",
|
|
224
|
-
sound_path="/storage/emulated/0/Download/alert.mp3"
|
|
225
|
-
)
|
|
226
|
-
|
|
227
|
-
# Using a content URI (e.g., from media store)
|
|
228
|
-
Notification.createChannel(
|
|
229
|
-
id="uri_sound",
|
|
230
|
-
name="URI Sound",
|
|
231
|
-
sound_path="content://media/external/audio/media/123"
|
|
232
|
-
)
|
|
233
|
-
|
|
234
|
-
# Send notification with custom sound path
|
|
235
|
-
n = Notification(
|
|
236
|
-
title="Custom Sound",
|
|
237
|
-
message="Playing from local path",
|
|
238
|
-
channel_id="local_sound"
|
|
239
|
-
)
|
|
240
|
-
n.setSound(sound_path="/storage/emulated/0/Download/alert.mp3")
|
|
241
|
-
n.send()
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
Private files (e.g., in app's `data/` directory) are automatically copied to external storage before playing.
|
|
245
|
-
</details>
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
<details>
|
|
249
|
-
<summary> <b> Vibrate feature</b> </summary>
|
|
250
|
-
|
|
174
|
+
For Dev Version usage
|
|
251
175
|
```ini
|
|
252
|
-
|
|
253
|
-
android.permissions = VIBRATE
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
```python
|
|
257
|
-
Notification.createChannel(id='shake', name="Shake Passage", vibrate=True)
|
|
258
|
-
|
|
259
|
-
n=Notification(title='Vibrate',channel_id='shake')
|
|
260
|
-
n.setVibrate() # for less than android 8
|
|
261
|
-
n.fVibrate() # To Force Vibrate (when user turned off in settings)
|
|
262
|
-
n.send()
|
|
176
|
+
requirements = python3, kivy, pyjnius, https://github.com/Fector101/android_notify/archive/main.zip
|
|
263
177
|
```
|
|
264
178
|
|
|
265
|
-
</details>
|
|
266
|
-
|
|
267
|
-
|
|
268
179
|
<details>
|
|
269
180
|
<summary> <b> Add Data to Notification</b> </summary>
|
|
270
181
|
|
|
@@ -296,9 +207,19 @@ from android_notify import Notification, NotificationHandler
|
|
|
296
207
|
|
|
297
208
|
## ☕ Support the Project
|
|
298
209
|
|
|
299
|
-
If you find this project helpful,
|
|
300
|
-
|
|
210
|
+
If you find this project helpful, your support would help me continue working on open-source projects
|
|
211
|
+
[donate](https://www.buymeacoffee.com/fector101)
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
## Bug Reports & Feature Requests
|
|
215
|
+
|
|
216
|
+
Found a bug or have an idea for a new feature?
|
|
217
|
+
Feel free to open an issue [here](https://reference-url-citation.invalid/0)
|
|
218
|
+
|
|
219
|
+
When reporting a bug, try to include:
|
|
220
|
+
- Device name
|
|
221
|
+
- Android version
|
|
222
|
+
- Steps to reproduce the issue
|
|
223
|
+
- Screenshots or logs (if possible)
|
|
301
224
|
|
|
302
|
-
|
|
303
|
-
<img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" height="60">
|
|
304
|
-
</a>
|
|
225
|
+
Feature suggestions are also welcome.
|
|
@@ -6,7 +6,7 @@ from android_notify.internal.logger import logger
|
|
|
6
6
|
from android_notify.config import get_python_activity, on_android_platform, get_python_activity_context
|
|
7
7
|
from android_notify.internal.permissions import has_notification_permission, ask_notification_permission
|
|
8
8
|
from android_notify.internal.java_classes import autoclass, BuildVersion, BitmapFactory, NotificationChannel, NotificationManagerCompat, NotificationCompat, NotificationCompatBuilder, \
|
|
9
|
-
NotificationCompatBigTextStyle, NotificationCompatBigPictureStyle, NotificationCompatInboxStyle
|
|
9
|
+
NotificationCompatBigTextStyle, NotificationCompatBigPictureStyle, NotificationCompatInboxStyle, IconCompat
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
|
|
@@ -60,7 +60,6 @@ def get_image_uri(relative_path):
|
|
|
60
60
|
|
|
61
61
|
def get_icon_object(uri):
|
|
62
62
|
context = get_python_activity_context()
|
|
63
|
-
IconCompat = autoclass('android.graphics.drawable.Icon')
|
|
64
63
|
bitmap = BitmapFactory.decodeStream(context.getContentResolver().openInputStream(uri))
|
|
65
64
|
return IconCompat.createWithBitmap(bitmap)
|
|
66
65
|
|
|
@@ -115,7 +114,9 @@ def send_notification(
|
|
|
115
114
|
return None
|
|
116
115
|
context = get_python_activity_context()
|
|
117
116
|
|
|
118
|
-
|
|
117
|
+
|
|
118
|
+
asks_permission_if_needed()
|
|
119
|
+
|
|
119
120
|
channel_id = channel_name.replace(' ', '_').lower().lower() if not channel_id else channel_id
|
|
120
121
|
# Get notification manager
|
|
121
122
|
notification_manager = context.getSystemService(context.NOTIFICATION_SERVICE)
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Android related logic
|
|
3
3
|
"""
|
|
4
|
-
import time
|
|
4
|
+
import time
|
|
5
5
|
|
|
6
6
|
from .logger import logger
|
|
7
7
|
from ..config import get_notification_manager, on_android_platform, from_service_file, on_flet_app, \
|
|
8
8
|
get_python_activity_context
|
|
9
9
|
from .permissions import has_notification_permission
|
|
10
10
|
from .java_classes import autoclass, BuildVersion, Uri, NotificationCompat, NotificationManagerCompat, \
|
|
11
|
-
NotificationManager, Context
|
|
11
|
+
NotificationManager, Context
|
|
12
12
|
from .an_types import Importance
|
|
13
13
|
|
|
14
14
|
|
|
@@ -98,72 +98,22 @@ def get_sound_uri(res_sound_name):
|
|
|
98
98
|
return Uri.parse(f"android.resource://{package_name}/raw/{res_sound_name}")
|
|
99
99
|
|
|
100
100
|
|
|
101
|
-
def
|
|
102
|
-
if not on_android_platform() or not sound_path:
|
|
103
|
-
return None
|
|
104
|
-
|
|
105
|
-
if sound_path.startswith("content://") or sound_path.startswith("file://") or sound_path.startswith("android.resource://"):
|
|
106
|
-
try:
|
|
107
|
-
return Uri.parse(sound_path)
|
|
108
|
-
except Exception as e:
|
|
109
|
-
logger.exception(f"Error parsing sound URI: {sound_path}")
|
|
110
|
-
return None
|
|
111
|
-
|
|
112
|
-
# Resolve relative paths
|
|
113
|
-
abs_path = os.path.abspath(sound_path)
|
|
114
|
-
if not os.path.exists(abs_path):
|
|
115
|
-
logger.warning(f"Sound file does not exist: {sound_path} (resolved to {abs_path})")
|
|
116
|
-
return None
|
|
117
|
-
|
|
118
|
-
# Check if the file is in private storage (contains /data/)
|
|
119
|
-
if "/data/" in abs_path or not (abs_path.startswith("/storage") or abs_path.startswith("/sdcard")):
|
|
120
|
-
try:
|
|
121
|
-
context = get_python_activity_context()
|
|
122
|
-
ext_files = context.getExternalFilesDir("Notifications")
|
|
123
|
-
if ext_files:
|
|
124
|
-
ext_files_path = ext_files.getAbsolutePath()
|
|
125
|
-
dest_file = os.path.join(ext_files_path, os.path.basename(abs_path))
|
|
126
|
-
|
|
127
|
-
# Copy if destination doesn't exist or is older than the source
|
|
128
|
-
if not os.path.exists(dest_file) or os.path.getmtime(abs_path) > os.path.getmtime(dest_file):
|
|
129
|
-
import shutil
|
|
130
|
-
shutil.copy2(abs_path, dest_file)
|
|
131
|
-
abs_path = dest_file
|
|
132
|
-
except Exception as copy_error:
|
|
133
|
-
logger.exception(f"Failed to copy private sound file {abs_path} to external files: {copy_error}")
|
|
134
|
-
|
|
135
|
-
try:
|
|
136
|
-
java_file = File(abs_path)
|
|
137
|
-
return Uri.fromFile(java_file)
|
|
138
|
-
except Exception as e:
|
|
139
|
-
logger.exception(f"Error generating Uri from file path: {abs_path}")
|
|
140
|
-
return None
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
def set_sound(builder, res_sound_name=None, sound_path=None):
|
|
101
|
+
def set_sound(builder, res_sound_name):
|
|
144
102
|
"""
|
|
145
103
|
Sets sound for devices less than android 8 (For 8+ use createChannel)
|
|
146
104
|
:param builder: builder instance
|
|
147
105
|
:param res_sound_name: audio file name (without .wav or .mp3) locate in res/raw/
|
|
148
|
-
:param sound_path: local file path or uri string
|
|
149
106
|
"""
|
|
150
107
|
|
|
151
108
|
if not on_android_platform():
|
|
152
109
|
return None
|
|
153
110
|
|
|
154
|
-
if BuildVersion.SDK_INT < 26:
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
if sound_uri:
|
|
162
|
-
try:
|
|
163
|
-
builder.setSound(sound_uri)
|
|
164
|
-
return True
|
|
165
|
-
except Exception as failed_adding_sound_for_devices_below_android8:
|
|
166
|
-
logger.exception(failed_adding_sound_for_devices_below_android8)
|
|
111
|
+
if res_sound_name and BuildVersion.SDK_INT < 26:
|
|
112
|
+
try:
|
|
113
|
+
builder.setSound(get_sound_uri(res_sound_name))
|
|
114
|
+
return True
|
|
115
|
+
except Exception as failed_adding_sound_for_devices_below_android8:
|
|
116
|
+
logger.exception(failed_adding_sound_for_devices_below_android8)
|
|
167
117
|
return None
|
|
168
118
|
|
|
169
119
|
|