android-notify 1.60.7.dev0__tar.gz → 1.60.8__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.60.7.dev0 → android_notify-1.60.8}/PKG-INFO +45 -28
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/README.md +44 -27
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/__init__.py +7 -2
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/config.py +1 -2
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/core.py +5 -4
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/internal/facade.py +0 -6
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/internal/helper.py +5 -3
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/internal/java_classes.py +17 -10
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/internal/permissions.py +47 -10
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/tests/main.py +28 -10
- android_notify-1.60.8/android_notify/tests/test_notification_permission.py +36 -0
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/widgets/images.py +1 -4
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/widgets/texts.py +2 -5
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify.egg-info/PKG-INFO +45 -28
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify.egg-info/SOURCES.txt +6 -7
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/pyproject.toml +1 -1
- android_notify-1.60.7.dev0/docs/examples/flet-working/src/core.py +0 -221
- android_notify-1.60.7.dev0/docs/tests/flet/basic/src/core.py +0 -221
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/__main__.py +0 -0
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/base.py +0 -0
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/fallback-icons/flet-appicon.png +0 -0
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/fallback-icons/pydroid3-appicon.png +0 -0
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/internal/an_types.py +0 -0
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/internal/android.py +0 -0
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/internal/channels.py +0 -0
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/internal/intents.py +0 -0
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/internal/logger.py +0 -0
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/styles.py +0 -0
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/sword.py +0 -0
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/tests/__init__.py +0 -0
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/tests/android_notify_test.py +0 -0
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/tests/base_test.py +0 -0
- {android_notify-1.60.7.dev0/docs → android_notify-1.60.8/android_notify}/tests/flet/adv/main.py +0 -0
- {android_notify-1.60.7.dev0/docs → android_notify-1.60.8/android_notify}/tests/flet/adv/tests/__init__.py +0 -0
- {android_notify-1.60.7.dev0/docs → android_notify-1.60.8/android_notify}/tests/flet/adv/tests/test_android_notify_full.py +0 -0
- {android_notify-1.60.7.dev0/docs → android_notify-1.60.8/android_notify}/tests/flet/basic/src/main.py +0 -0
- {android_notify-1.60.7.dev0/docs/examples → android_notify-1.60.8/android_notify/tests/flet}/flet-working/src/main.py +0 -0
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/tests/p4a/hook.py +0 -0
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/tests/serivces/wallpaper.py +0 -0
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/tests/test_basic_notifications.py +0 -0
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/tests/test_notification_actions.py +0 -0
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/tests/test_notification_appearance.py +0 -0
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/tests/test_notification_behavior.py +0 -0
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/tests/test_notification_channels.py +0 -0
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/tests/test_notification_clear.py +0 -0
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/tests/test_notification_progress.py +0 -0
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/tests/test_notification_sound.py +0 -0
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/tests/test_notification_styles.py +0 -0
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify.egg-info/dependency_links.txt +0 -0
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify.egg-info/entry_points.txt +0 -0
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify.egg-info/requires.txt +0 -0
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify.egg-info/top_level.txt +0 -0
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/docs/website/src/pages/data/laner_Sent.py +0 -0
- {android_notify-1.60.7.dev0 → android_notify-1.60.8}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: android-notify
|
|
3
|
-
Version: 1.60.
|
|
3
|
+
Version: 1.60.8
|
|
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
|
|
@@ -81,9 +81,14 @@ In your **`buildozer.spec`** file, ensure you include the following:
|
|
|
81
81
|
|
|
82
82
|
```ini
|
|
83
83
|
# Add pyjnius so ensure it's packaged with the build
|
|
84
|
-
requirements = python3, kivy, pyjnius, android-notify
|
|
84
|
+
requirements = python3, kivy, pyjnius, android-notify
|
|
85
85
|
# Add permission for notifications
|
|
86
86
|
android.permissions = POST_NOTIFICATIONS
|
|
87
|
+
|
|
88
|
+
# Required dependencies (write exactly as shown, no quotation marks)
|
|
89
|
+
android.gradle_dependencies = androidx.core:core:1.6.0, androidx.core:core-ktx:1.15.0
|
|
90
|
+
android.enable_androidx = True
|
|
91
|
+
android.api = 35
|
|
87
92
|
```
|
|
88
93
|
|
|
89
94
|
</details>
|
|
@@ -93,13 +98,13 @@ android.permissions = POST_NOTIFICATIONS
|
|
|
93
98
|
<summary><b>Flet apps:</b></summary>
|
|
94
99
|
<br/>
|
|
95
100
|
|
|
96
|
-
In your `pyproject.toml` file, ensure you include the following:
|
|
101
|
+
In your `pyproject.toml` file, ensure you include the following:
|
|
97
102
|
|
|
98
103
|
|
|
99
104
|
```toml
|
|
100
105
|
[tool.flet.android]
|
|
101
106
|
dependencies = [
|
|
102
|
-
"pyjnius","android-notify==1.60.
|
|
107
|
+
"pyjnius","android-notify==1.60.8.dev0"
|
|
103
108
|
]
|
|
104
109
|
|
|
105
110
|
[tool.flet.android.permission]
|
|
@@ -109,7 +114,35 @@ dependencies = [
|
|
|
109
114
|
|
|
110
115
|
</details>
|
|
111
116
|
|
|
117
|
+
<details>
|
|
118
|
+
|
|
119
|
+
<summary><b>Desktop</b></summary>
|
|
120
|
+
<br/>
|
|
121
|
+
|
|
122
|
+
For IDE IntelliSense Can be installed via `pip install`:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
pip install android_notify
|
|
126
|
+
android-notify -v
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
</details>
|
|
130
|
+
|
|
131
|
+
------
|
|
132
|
+
## Installing without Androidx
|
|
133
|
+
How to use without `gradle_dependencies`
|
|
134
|
+
Use `android-notify==1.60.8.dev0` to install via `pip`
|
|
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.60.8.dev0
|
|
143
|
+
```
|
|
112
144
|
|
|
145
|
+
</details>
|
|
113
146
|
|
|
114
147
|
<details>
|
|
115
148
|
|
|
@@ -117,10 +150,10 @@ dependencies = [
|
|
|
117
150
|
<br/>
|
|
118
151
|
|
|
119
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.
|
|
120
|
-
- In pip section where you're asked to insert `Libary name` paste `android-notify==1.60.
|
|
153
|
+
- In pip section where you're asked to insert `Libary name` paste `android-notify==1.60.8.dev0`
|
|
121
154
|
- Minimal working example
|
|
122
155
|
```py
|
|
123
|
-
# Testing with `android-notify==1.60.
|
|
156
|
+
# Testing with `android-notify==1.60.8.dev0` on pydroid
|
|
124
157
|
from kivy.app import App
|
|
125
158
|
from kivy.uix.boxlayout import BoxLayout
|
|
126
159
|
from kivy.uix.button import Button
|
|
@@ -160,23 +193,11 @@ if __name__ == "__main__":
|
|
|
160
193
|
</details>
|
|
161
194
|
|
|
162
195
|
|
|
163
|
-
<details>
|
|
164
|
-
|
|
165
|
-
<summary><b>Desktop</b></summary>
|
|
166
|
-
<br/>
|
|
167
|
-
|
|
168
|
-
For IDE IntelliSense Can be installed via `pip install`:
|
|
169
|
-
|
|
170
|
-
```bash
|
|
171
|
-
pip install android_notify
|
|
172
|
-
android-notify -v
|
|
173
|
-
```
|
|
174
|
-
</details>
|
|
175
196
|
|
|
176
197
|
## Documentation
|
|
177
|
-
For Dev Version
|
|
198
|
+
For Dev Version usage
|
|
178
199
|
```ini
|
|
179
|
-
requirements = python3, kivy, pyjnius, https://github.com/Fector101/android_notify/archive/
|
|
200
|
+
requirements = python3, kivy, pyjnius, https://github.com/Fector101/android_notify/archive/main.zip
|
|
180
201
|
```
|
|
181
202
|
|
|
182
203
|
<details>
|
|
@@ -185,7 +206,7 @@ requirements = python3, kivy, pyjnius, https://github.com/Fector101/android_noti
|
|
|
185
206
|
- Make things happen without being in your app
|
|
186
207
|
```python
|
|
187
208
|
from android_notify import Notification
|
|
188
|
-
notification = Notification(title="
|
|
209
|
+
notification = Notification(title="Reciver Notification")
|
|
189
210
|
notification.addButton(text="Stop", receiver_name="CarouselReceiver", action="ACTION_STOP")
|
|
190
211
|
notification.addButton(text="Skip", receiver_name="CarouselReceiver", action="ACTION_SKIP")
|
|
191
212
|
```
|
|
@@ -248,7 +269,7 @@ Notification.createChannel(id='shake', name="Shake Passage", vibrate=True)
|
|
|
248
269
|
|
|
249
270
|
n=Notification(title='Vibrate',channel_id='shake')
|
|
250
271
|
n.setVibrate() # for less than android 8
|
|
251
|
-
n.fVibrate() # To Force Vibrate
|
|
272
|
+
n.fVibrate() # To Force Vibrate
|
|
252
273
|
n.send()
|
|
253
274
|
```
|
|
254
275
|
|
|
@@ -286,9 +307,5 @@ from android_notify import Notification, NotificationHandler
|
|
|
286
307
|
|
|
287
308
|
## ☕ Support the Project
|
|
288
309
|
|
|
289
|
-
If you find this project helpful,
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
<a href="https://www.buymeacoffee.com/fector101" target="_blank">
|
|
293
|
-
<img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" height="60">
|
|
294
|
-
</a>
|
|
310
|
+
If you find this project helpful, your support would help me continue working on open-source projects
|
|
311
|
+
[donate](https://www.buymeacoffee.com/fector101)
|
|
@@ -58,9 +58,14 @@ In your **`buildozer.spec`** file, ensure you include the following:
|
|
|
58
58
|
|
|
59
59
|
```ini
|
|
60
60
|
# Add pyjnius so ensure it's packaged with the build
|
|
61
|
-
requirements = python3, kivy, pyjnius, android-notify
|
|
61
|
+
requirements = python3, kivy, pyjnius, android-notify
|
|
62
62
|
# Add permission for notifications
|
|
63
63
|
android.permissions = POST_NOTIFICATIONS
|
|
64
|
+
|
|
65
|
+
# Required dependencies (write exactly as shown, no quotation marks)
|
|
66
|
+
android.gradle_dependencies = androidx.core:core:1.6.0, androidx.core:core-ktx:1.15.0
|
|
67
|
+
android.enable_androidx = True
|
|
68
|
+
android.api = 35
|
|
64
69
|
```
|
|
65
70
|
|
|
66
71
|
</details>
|
|
@@ -70,13 +75,13 @@ android.permissions = POST_NOTIFICATIONS
|
|
|
70
75
|
<summary><b>Flet apps:</b></summary>
|
|
71
76
|
<br/>
|
|
72
77
|
|
|
73
|
-
In your `pyproject.toml` file, ensure you include the following:
|
|
78
|
+
In your `pyproject.toml` file, ensure you include the following:
|
|
74
79
|
|
|
75
80
|
|
|
76
81
|
```toml
|
|
77
82
|
[tool.flet.android]
|
|
78
83
|
dependencies = [
|
|
79
|
-
"pyjnius","android-notify==1.60.
|
|
84
|
+
"pyjnius","android-notify==1.60.8.dev0"
|
|
80
85
|
]
|
|
81
86
|
|
|
82
87
|
[tool.flet.android.permission]
|
|
@@ -86,7 +91,35 @@ dependencies = [
|
|
|
86
91
|
|
|
87
92
|
</details>
|
|
88
93
|
|
|
94
|
+
<details>
|
|
95
|
+
|
|
96
|
+
<summary><b>Desktop</b></summary>
|
|
97
|
+
<br/>
|
|
98
|
+
|
|
99
|
+
For IDE IntelliSense Can be installed via `pip install`:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
pip install android_notify
|
|
103
|
+
android-notify -v
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
</details>
|
|
107
|
+
|
|
108
|
+
------
|
|
109
|
+
## Installing without Androidx
|
|
110
|
+
How to use without `gradle_dependencies`
|
|
111
|
+
Use `android-notify==1.60.8.dev0` to install via `pip`
|
|
112
|
+
|
|
113
|
+
<details>
|
|
114
|
+
<summary><b>In Kivy</b></summary>
|
|
115
|
+
<br/>
|
|
116
|
+
|
|
117
|
+
```ini
|
|
118
|
+
# buildozer.spec
|
|
119
|
+
requirements = python3, kivy, pyjnius, android-notify==1.60.8.dev0
|
|
120
|
+
```
|
|
89
121
|
|
|
122
|
+
</details>
|
|
90
123
|
|
|
91
124
|
<details>
|
|
92
125
|
|
|
@@ -94,10 +127,10 @@ dependencies = [
|
|
|
94
127
|
<br/>
|
|
95
128
|
|
|
96
129
|
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.60.
|
|
130
|
+
- In pip section where you're asked to insert `Libary name` paste `android-notify==1.60.8.dev0`
|
|
98
131
|
- Minimal working example
|
|
99
132
|
```py
|
|
100
|
-
# Testing with `android-notify==1.60.
|
|
133
|
+
# Testing with `android-notify==1.60.8.dev0` on pydroid
|
|
101
134
|
from kivy.app import App
|
|
102
135
|
from kivy.uix.boxlayout import BoxLayout
|
|
103
136
|
from kivy.uix.button import Button
|
|
@@ -137,23 +170,11 @@ if __name__ == "__main__":
|
|
|
137
170
|
</details>
|
|
138
171
|
|
|
139
172
|
|
|
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
173
|
|
|
153
174
|
## Documentation
|
|
154
|
-
For Dev Version
|
|
175
|
+
For Dev Version usage
|
|
155
176
|
```ini
|
|
156
|
-
requirements = python3, kivy, pyjnius, https://github.com/Fector101/android_notify/archive/
|
|
177
|
+
requirements = python3, kivy, pyjnius, https://github.com/Fector101/android_notify/archive/main.zip
|
|
157
178
|
```
|
|
158
179
|
|
|
159
180
|
<details>
|
|
@@ -162,7 +183,7 @@ requirements = python3, kivy, pyjnius, https://github.com/Fector101/android_noti
|
|
|
162
183
|
- Make things happen without being in your app
|
|
163
184
|
```python
|
|
164
185
|
from android_notify import Notification
|
|
165
|
-
notification = Notification(title="
|
|
186
|
+
notification = Notification(title="Reciver Notification")
|
|
166
187
|
notification.addButton(text="Stop", receiver_name="CarouselReceiver", action="ACTION_STOP")
|
|
167
188
|
notification.addButton(text="Skip", receiver_name="CarouselReceiver", action="ACTION_SKIP")
|
|
168
189
|
```
|
|
@@ -225,7 +246,7 @@ Notification.createChannel(id='shake', name="Shake Passage", vibrate=True)
|
|
|
225
246
|
|
|
226
247
|
n=Notification(title='Vibrate',channel_id='shake')
|
|
227
248
|
n.setVibrate() # for less than android 8
|
|
228
|
-
n.fVibrate() # To Force Vibrate
|
|
249
|
+
n.fVibrate() # To Force Vibrate
|
|
229
250
|
n.send()
|
|
230
251
|
```
|
|
231
252
|
|
|
@@ -263,9 +284,5 @@ from android_notify import Notification, NotificationHandler
|
|
|
263
284
|
|
|
264
285
|
## ☕ Support the Project
|
|
265
286
|
|
|
266
|
-
If you find this project helpful,
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
<a href="https://www.buymeacoffee.com/fector101" target="_blank">
|
|
270
|
-
<img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" height="60">
|
|
271
|
-
</a>
|
|
287
|
+
If you find this project helpful, your support would help me continue working on open-source projects
|
|
288
|
+
[donate](https://www.buymeacoffee.com/fector101)
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
-
"""
|
|
2
|
-
|
|
1
|
+
"""
|
|
2
|
+
Android-Notify
|
|
3
|
+
=================
|
|
4
|
+
|
|
5
|
+
For Creating Android Notifications In Python Apps.
|
|
6
|
+
|
|
7
|
+
All the documentation is available at: https://android-notify.vercel.app/
|
|
3
8
|
"""
|
|
4
9
|
from .core import send_notification
|
|
5
10
|
from .styles import NotificationStyles
|
|
@@ -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
|
|
|
@@ -49,7 +49,7 @@ def get_image_uri(relative_path):
|
|
|
49
49
|
"""
|
|
50
50
|
app_root_path = get_app_root_path()
|
|
51
51
|
output_path = os.path.join(app_root_path, relative_path)
|
|
52
|
-
#
|
|
52
|
+
# rint(output_path,'output_path') # /data/user/0/org.laner.lan_ft/files/app/assets/imgs/icon.png
|
|
53
53
|
|
|
54
54
|
if not os.path.exists(output_path):
|
|
55
55
|
raise FileNotFoundError(f"\nImage not found at path: {output_path}\n")
|
|
@@ -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)
|
|
@@ -175,12 +175,6 @@ class NotificationManagerCompat:
|
|
|
175
175
|
IMPORTANCE_MIN = ''
|
|
176
176
|
IMPORTANCE_NONE = ''
|
|
177
177
|
|
|
178
|
-
class AndroidNotification:
|
|
179
|
-
DEFAULT_ALL = 3
|
|
180
|
-
PRIORITY_HIGH = 4
|
|
181
|
-
PRIORITY_DEFAULT = ''
|
|
182
|
-
PRIORITY_LOW = ''
|
|
183
|
-
PRIORITY_MIN = ''
|
|
184
178
|
|
|
185
179
|
class NotificationCompat:
|
|
186
180
|
DEFAULT_ALL = 3
|
|
@@ -40,14 +40,16 @@ def get_package_path():
|
|
|
40
40
|
return os.path.dirname(os.path.abspath(__file__))
|
|
41
41
|
|
|
42
42
|
|
|
43
|
-
def execute_callback(callback,arg):
|
|
43
|
+
def execute_callback(callback,arg, from_who="user"):
|
|
44
44
|
"""
|
|
45
45
|
Executing Callbacks Safely
|
|
46
46
|
"""
|
|
47
|
-
if callback:
|
|
47
|
+
if not callback:
|
|
48
48
|
return None
|
|
49
|
+
if from_who == "user":
|
|
50
|
+
logger.info(f"Executing On Permission Result Callback...")
|
|
49
51
|
try:
|
|
50
|
-
if can_accept_arguments(callback,
|
|
52
|
+
if can_accept_arguments(callback, arg):
|
|
51
53
|
callback(arg)
|
|
52
54
|
else:
|
|
53
55
|
callback()
|
{android_notify-1.60.7.dev0 → android_notify-1.60.8}/android_notify/internal/java_classes.py
RENAMED
|
@@ -39,24 +39,31 @@ if on_android_platform():
|
|
|
39
39
|
Manifest = autoclass('android.Manifest$permission')
|
|
40
40
|
Color = autoclass('android.graphics.Color')
|
|
41
41
|
Context = autoclass('android.content.Context')
|
|
42
|
-
PackageManager = autoclass("android.content.pm.PackageManager")
|
|
43
42
|
except Exception as e:
|
|
44
43
|
from .facade import *
|
|
45
44
|
logger.exception("Didn't get Basic Java Classes")
|
|
46
45
|
|
|
47
46
|
# noinspection PyBroadException
|
|
48
47
|
try:
|
|
49
|
-
NotificationManagerCompat =
|
|
50
|
-
NotificationCompat = autoclass(
|
|
51
|
-
NotificationCompatBuilder = autoclass('
|
|
52
|
-
|
|
53
|
-
NotificationCompatBigPictureStyle = autoclass('android.app.Notification$BigPictureStyle')
|
|
54
|
-
NotificationCompatInboxStyle = autoclass('android.app.Notification$InboxStyle')
|
|
48
|
+
NotificationManagerCompat = autoclass('androidx.core.app.NotificationManagerCompat')
|
|
49
|
+
NotificationCompat = autoclass('androidx.core.app.NotificationCompat')
|
|
50
|
+
NotificationCompatBuilder = autoclass('androidx.core.app.NotificationCompat$Builder')
|
|
51
|
+
IconCompat = autoclass('androidx.core.graphics.drawable.IconCompat')
|
|
55
52
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
53
|
+
# Notification Design
|
|
54
|
+
NotificationCompatBigTextStyle = autoclass('androidx.core.app.NotificationCompat$BigTextStyle')
|
|
55
|
+
NotificationCompatBigPictureStyle = autoclass('androidx.core.app.NotificationCompat$BigPictureStyle')
|
|
56
|
+
NotificationCompatInboxStyle = autoclass('androidx.core.app.NotificationCompat$InboxStyle')
|
|
57
|
+
NotificationCompatDecoratedCustomViewStyle = autoclass('androidx.core.app.NotificationCompat$DecoratedCustomViewStyle')
|
|
58
|
+
|
|
59
|
+
except Exception as dependencies_import_error:
|
|
60
|
+
logger.exception("""
|
|
61
|
+
Dependency Error: Add the following in buildozer.spec:
|
|
62
|
+
* android.gradle_dependencies = androidx.core:core-ktx:1.15.0, androidx.core:core:1.6.0
|
|
63
|
+
* android.enable_androidx = True
|
|
64
|
+
""")
|
|
59
65
|
|
|
66
|
+
from .facade import *
|
|
60
67
|
else:
|
|
61
68
|
cast = lambda x, y: x
|
|
62
69
|
autoclass = lambda x: None
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
"""
|
|
2
2
|
For Permission Related Blocks
|
|
3
3
|
"""
|
|
4
|
+
import os.path
|
|
4
5
|
|
|
5
6
|
from .logger import logger
|
|
6
7
|
from android_notify.config import on_android_platform, on_flet_app, get_python_activity_context
|
|
7
|
-
from android_notify.internal.java_classes import autoclass, BuildVersion, Manifest, Intent, String, Settings, Uri
|
|
8
|
+
from android_notify.internal.java_classes import autoclass, BuildVersion, Manifest, Intent, String, Settings, Uri
|
|
8
9
|
from android_notify.internal.helper import execute_callback
|
|
9
10
|
|
|
10
11
|
|
|
@@ -22,8 +23,10 @@ def has_notification_permission():
|
|
|
22
23
|
if on_flet_app():
|
|
23
24
|
context = get_python_activity_context()
|
|
24
25
|
permission = Manifest.POST_NOTIFICATIONS
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
ContextCompat = autoclass('androidx.core.content.ContextCompat')
|
|
27
|
+
# if you get error `Failed to find class: androidx/core/app/ActivityCompat`
|
|
28
|
+
# in proguard-rules.pro add `-keep class androidx.core.app.ActivityCompat { *; }`
|
|
29
|
+
return ContextCompat.checkSelfPermission(context, permission)
|
|
27
30
|
else:
|
|
28
31
|
from android.permissions import Permission, check_permission # type: ignore
|
|
29
32
|
return check_permission(Permission.POST_NOTIFICATIONS)
|
|
@@ -45,10 +48,16 @@ def ask_notification_permission(callback=None, set_requesting_state=None, legacy
|
|
|
45
48
|
logger.warning("Already have permission to send notifications")
|
|
46
49
|
return None
|
|
47
50
|
|
|
48
|
-
if not can_show_permission_request_popup():
|
|
51
|
+
if not is_first_permission_ask() and not can_show_permission_request_popup():
|
|
49
52
|
logger.warning("""Permission to send notifications has been denied permanently.
|
|
50
|
-
This
|
|
51
|
-
|
|
53
|
+
This can happen when the user denies permission twice from the popup.
|
|
54
|
+
|
|
55
|
+
Opening notification settings...
|
|
56
|
+
|
|
57
|
+
Add in MDApp().on_resume():
|
|
58
|
+
>> if NotificationHandler.has_permission() and self.screen_manager:
|
|
59
|
+
>> self.screen_manager.current = "home_screen"
|
|
60
|
+
""")
|
|
52
61
|
open_notification_settings_screen()
|
|
53
62
|
return None
|
|
54
63
|
|
|
@@ -57,21 +66,38 @@ def ask_notification_permission(callback=None, set_requesting_state=None, legacy
|
|
|
57
66
|
def on_permissions_result(_, grants):
|
|
58
67
|
# _ is permissions
|
|
59
68
|
execute_callback(callback, grants[0])
|
|
60
|
-
execute_callback(set_requesting_state, False)
|
|
69
|
+
execute_callback(set_requesting_state, False,from_who="package")
|
|
61
70
|
|
|
62
|
-
if legacy
|
|
71
|
+
if legacy:
|
|
63
72
|
# TODO Handle activity with request code
|
|
73
|
+
PackageManager = autoclass("android.content.pm.PackageManager")
|
|
64
74
|
permission = Manifest.POST_NOTIFICATIONS
|
|
65
|
-
|
|
75
|
+
|
|
76
|
+
granted = context.checkSelfPermission(permission)
|
|
77
|
+
if granted != PackageManager.PERMISSION_GRANTED:
|
|
78
|
+
context.requestPermissions([permission], 101)
|
|
79
|
+
return None
|
|
80
|
+
elif on_flet_app():
|
|
81
|
+
# TODO Callback when user answers request question
|
|
82
|
+
# Can't bind activity result method is from p4a which is only on kivy
|
|
83
|
+
ActivityCompat = autoclass('androidx.core.app.ActivityCompat')
|
|
84
|
+
permission = Manifest.POST_NOTIFICATIONS
|
|
85
|
+
ActivityCompat.requestPermissions(context, [permission], 101)
|
|
66
86
|
return None
|
|
67
87
|
else:
|
|
68
88
|
from android.permissions import request_permissions, Permission # type: ignore
|
|
69
|
-
execute_callback(set_requesting_state, True)
|
|
89
|
+
execute_callback(set_requesting_state, True,from_who="package")
|
|
70
90
|
request_permissions([Permission.POST_NOTIFICATIONS], on_permissions_result)
|
|
71
91
|
return None
|
|
72
92
|
|
|
73
93
|
|
|
74
94
|
def open_notification_settings_screen():
|
|
95
|
+
"""In MDApp().on_resume()
|
|
96
|
+
|
|
97
|
+
Example:
|
|
98
|
+
>>> if NotificationHandler.has_permission() and self.screen_manager:
|
|
99
|
+
>>> self.screen_manager.current = "home_screen"
|
|
100
|
+
"""
|
|
75
101
|
context = get_python_activity_context()
|
|
76
102
|
|
|
77
103
|
if not context:
|
|
@@ -114,3 +140,14 @@ def can_show_permission_request_popup():
|
|
|
114
140
|
return False
|
|
115
141
|
|
|
116
142
|
return context.shouldShowRequestPermissionRationale(Manifest.POST_NOTIFICATIONS)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def is_first_permission_ask():
|
|
146
|
+
from importlib.resources import files
|
|
147
|
+
buffer_file_name = "ASKED_PERMISSION.txt"
|
|
148
|
+
absolute_buffer_file_path = str(files("android_notify") / buffer_file_name) # Making sure one path is always used
|
|
149
|
+
|
|
150
|
+
if os.path.exists(absolute_buffer_file_path):
|
|
151
|
+
return False
|
|
152
|
+
open(absolute_buffer_file_path,'w').close()
|
|
153
|
+
return True
|
|
@@ -29,6 +29,7 @@ from android_notify.tests.test_notification_behavior import TestNotificationBeha
|
|
|
29
29
|
from android_notify.tests.test_notification_progress import TestNotificationProgress
|
|
30
30
|
from android_notify.tests.test_notification_sound import TestNotificationSound
|
|
31
31
|
from android_notify.tests.test_notification_clear import TestClearNotifications
|
|
32
|
+
from android_notify.tests.test_notification_permission import NOTIFICATION_PERMISSION_TESTS
|
|
32
33
|
from kivy.clock import Clock
|
|
33
34
|
|
|
34
35
|
# -----------------------------
|
|
@@ -82,6 +83,7 @@ class TripleClickButton(Button):
|
|
|
82
83
|
class AndroidNotifyDemoApp(MDApp):
|
|
83
84
|
|
|
84
85
|
def on_start(self):
|
|
86
|
+
print('starting app...')
|
|
85
87
|
try:
|
|
86
88
|
from kivymd.toast import toast
|
|
87
89
|
name = NotificationHandler.get_name(on_start=True)
|
|
@@ -89,6 +91,7 @@ class AndroidNotifyDemoApp(MDApp):
|
|
|
89
91
|
except Exception as e:
|
|
90
92
|
print("Error getting notify name:", e)
|
|
91
93
|
|
|
94
|
+
print('on_start','-'*33)
|
|
92
95
|
|
|
93
96
|
def android_service():
|
|
94
97
|
|
|
@@ -154,11 +157,28 @@ class AndroidNotifyDemoApp(MDApp):
|
|
|
154
157
|
self.test_buttons.append(btn)
|
|
155
158
|
main.add_widget(btn)
|
|
156
159
|
|
|
160
|
+
# Permission request needs human inputs for tests
|
|
161
|
+
for label, action in NOTIFICATION_PERMISSION_TESTS.items():
|
|
162
|
+
btn = self._btn(
|
|
163
|
+
f"Run: {label}",
|
|
164
|
+
lambda _, fn=action: self.run_action(fn, _)
|
|
165
|
+
)
|
|
166
|
+
main.add_widget(btn)
|
|
157
167
|
return root
|
|
158
168
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
169
|
+
def run_action(self, action_fn, btn_instance):
|
|
170
|
+
btn_instance.disabled = True
|
|
171
|
+
print(f"\n▶ Running action: {action_fn.__name__}")
|
|
172
|
+
|
|
173
|
+
try:
|
|
174
|
+
action_fn()
|
|
175
|
+
except Exception as error_running_action:
|
|
176
|
+
print("error_running_action:", error_running_action)
|
|
177
|
+
traceback.print_exc()
|
|
178
|
+
finally:
|
|
179
|
+
# Re-enable AFTER user interaction finishes
|
|
180
|
+
btn_instance.disabled = False
|
|
181
|
+
|
|
162
182
|
def _btn(self, text, callback, height=80):
|
|
163
183
|
return TripleClickButton(
|
|
164
184
|
text=text,
|
|
@@ -185,9 +205,6 @@ class AndroidNotifyDemoApp(MDApp):
|
|
|
185
205
|
for btn in self.test_buttons:
|
|
186
206
|
btn.disabled = False
|
|
187
207
|
|
|
188
|
-
# -----------------------------
|
|
189
|
-
# Actions
|
|
190
|
-
# -----------------------------
|
|
191
208
|
def request_permission(self, btn_instance):
|
|
192
209
|
asks_permission_if_needed()
|
|
193
210
|
btn_instance.disabled = False
|
|
@@ -204,16 +221,17 @@ class AndroidNotifyDemoApp(MDApp):
|
|
|
204
221
|
btn_instance.disabled = False
|
|
205
222
|
|
|
206
223
|
def on_resume(self):
|
|
224
|
+
print('resuming app..')
|
|
207
225
|
try:
|
|
208
226
|
from kivymd.toast import toast
|
|
209
227
|
name = NotificationHandler.get_name()
|
|
210
|
-
|
|
228
|
+
|
|
229
|
+
toast(text=f"name: {name}, Permission:{NotificationHandler.has_permission()}", length_long=True)
|
|
211
230
|
except Exception as e:
|
|
212
231
|
print("Error getting notify name:", e)
|
|
232
|
+
print('on_resume','-'*33)
|
|
233
|
+
|
|
213
234
|
|
|
214
235
|
|
|
215
|
-
# -----------------------------
|
|
216
|
-
# Entry
|
|
217
|
-
# -----------------------------
|
|
218
236
|
if __name__ == "__main__":
|
|
219
237
|
AndroidNotifyDemoApp().run()
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from android_notify import NotificationHandler
|
|
2
|
+
from android_notify.internal.permissions import ask_notification_permission
|
|
3
|
+
from android_notify.core import asks_permission_if_needed
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def ask_permission_no_callback():
|
|
7
|
+
NotificationHandler.asks_permission()
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def ask_permission_with_callback():
|
|
11
|
+
def some_callback(answer):
|
|
12
|
+
print(f"Hey Dude, Notification Request result {answer}.")
|
|
13
|
+
NotificationHandler.asks_permission(some_callback)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def ask_permission_simple_regular():
|
|
17
|
+
asks_permission_if_needed()
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def ask_permission_simple_legacy():
|
|
21
|
+
asks_permission_if_needed(legacy=True)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def ask_permission_from_source():
|
|
25
|
+
def some_callback(answer):
|
|
26
|
+
print(f"Hey, Notification Request Request1: {answer}")
|
|
27
|
+
ask_notification_permission(callback=some_callback)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
NOTIFICATION_PERMISSION_TESTS = {
|
|
31
|
+
"permission (no callback)": ask_permission_no_callback,
|
|
32
|
+
"permission (with callback)": ask_permission_with_callback,
|
|
33
|
+
"permission (simple)": ask_permission_simple_regular,
|
|
34
|
+
"permission (legacy)": ask_permission_simple_legacy,
|
|
35
|
+
"permission (from source)": ask_permission_from_source,
|
|
36
|
+
}
|
|
@@ -4,7 +4,7 @@ For image related things
|
|
|
4
4
|
import os
|
|
5
5
|
|
|
6
6
|
from android_notify.config import app_storage_path, on_flet_app, on_android_platform, get_python_activity_context
|
|
7
|
-
from android_notify.internal.java_classes import autoclass, BitmapFactory, Uri, BuildVersion, Color
|
|
7
|
+
from android_notify.internal.java_classes import autoclass, BitmapFactory, Uri, BuildVersion, Color, IconCompat
|
|
8
8
|
from android_notify.internal.helper import get_package_path
|
|
9
9
|
from android_notify.internal.logger import logger
|
|
10
10
|
|
|
@@ -75,8 +75,6 @@ def icon_finder(icon_name):
|
|
|
75
75
|
# noinspection PyPackageRequirements
|
|
76
76
|
from importlib.resources import files
|
|
77
77
|
return str(files("android_notify")/"fallback-icons"/icon_name)
|
|
78
|
-
# import pkg_resources
|
|
79
|
-
# return pkg_resources.resource_filename(__name__, f"fallback-icons/{icon_name}")
|
|
80
78
|
except Exception:
|
|
81
79
|
# Fallback if pkg_resources not available
|
|
82
80
|
package_dir = get_package_path()
|
|
@@ -130,7 +128,6 @@ def set_small_icon_with_bitmap(bitmap, builder):
|
|
|
130
128
|
logger.warning("Bitmap Insert as Icon Not available below Android 6")
|
|
131
129
|
return False
|
|
132
130
|
try:
|
|
133
|
-
IconCompat = autoclass('android.graphics.drawable.Icon')
|
|
134
131
|
icon = IconCompat.createWithBitmap(bitmap)
|
|
135
132
|
builder.setSmallIcon(icon)
|
|
136
133
|
return True
|