android-notify 1.0__tar.gz → 1.2__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.
Potentially problematic release.
This version of android-notify might be problematic. Click here for more details.
- {android_notify-1.0 → android_notify-1.2}/PKG-INFO +92 -21
- {android_notify-1.0 → android_notify-1.2}/README.md +90 -20
- android_notify-1.2/android_notify/core.py +135 -0
- {android_notify-1.0 → android_notify-1.2}/android_notify.egg-info/PKG-INFO +93 -22
- {android_notify-1.0 → android_notify-1.2}/setup.py +1 -1
- android_notify-1.0/android_notify/core.py +0 -168
- {android_notify-1.0 → android_notify-1.2}/android_notify/__init__.py +0 -0
- {android_notify-1.0 → android_notify-1.2}/android_notify/__main__.py +0 -0
- {android_notify-1.0 → android_notify-1.2}/android_notify/styles.py +0 -0
- {android_notify-1.0 → android_notify-1.2}/android_notify.egg-info/SOURCES.txt +0 -0
- {android_notify-1.0 → android_notify-1.2}/android_notify.egg-info/dependency_links.txt +0 -0
- {android_notify-1.0 → android_notify-1.2}/android_notify.egg-info/requires.txt +0 -0
- {android_notify-1.0 → android_notify-1.2}/android_notify.egg-info/top_level.txt +0 -0
- {android_notify-1.0 → android_notify-1.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: android_notify
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.2
|
|
4
4
|
Summary: A Python package for sending Android notifications.
|
|
5
5
|
Home-page: https://github.com/Fector101/android_notify/
|
|
6
6
|
Author: Fabian
|
|
@@ -9,6 +9,7 @@ Project-URL: Funding, https://buymeacoffee.com/fector101
|
|
|
9
9
|
Project-URL: Source, https://github.com/Fector101/android_notify/
|
|
10
10
|
Requires-Python: >=3.6
|
|
11
11
|
Description-Content-Type: text/markdown
|
|
12
|
+
Requires-Dist: pyjnius
|
|
12
13
|
|
|
13
14
|
# Android Notify
|
|
14
15
|
|
|
@@ -20,21 +21,21 @@ Description-Content-Type: text/markdown
|
|
|
20
21
|
- Support for multiple notification styles:
|
|
21
22
|
- Big Text
|
|
22
23
|
- Big Picture
|
|
24
|
+
- Large Icon
|
|
23
25
|
- Inbox
|
|
24
|
-
-
|
|
26
|
+
- Supports including images in notifications.
|
|
25
27
|
- Compatible with Android 8.0+ (Notification Channels).
|
|
26
28
|
- Customizable notification channels.
|
|
27
|
-
- Support for large icons in notifications.
|
|
28
29
|
|
|
29
30
|
## Installation
|
|
30
31
|
|
|
31
|
-
|
|
32
|
+
This package is available on PyPI and can be installed via pip:
|
|
32
33
|
|
|
33
34
|
```bash
|
|
34
35
|
pip install android-notify
|
|
35
36
|
```
|
|
36
37
|
|
|
37
|
-
##
|
|
38
|
+
## **Dependencies**
|
|
38
39
|
|
|
39
40
|
**Prerequisites:**
|
|
40
41
|
|
|
@@ -51,10 +52,12 @@ requirements = python3,kivy,pyjnius
|
|
|
51
52
|
android.permissions = POST_NOTIFICATIONS
|
|
52
53
|
|
|
53
54
|
# Required dependencies (write exactly as shown, no quotation marks)
|
|
54
|
-
android.gradle_dependencies = androidx.core:core:1.6.0
|
|
55
|
+
android.gradle_dependencies = androidx.core:core:1.6.0, androidx.core:core-ktx:1.15.0
|
|
55
56
|
android.enable_androidx = True
|
|
56
57
|
```
|
|
57
58
|
|
|
59
|
+
---
|
|
60
|
+
|
|
58
61
|
### Example Notification
|
|
59
62
|
|
|
60
63
|
```python
|
|
@@ -86,20 +89,75 @@ send_notification(
|
|
|
86
89
|
)
|
|
87
90
|
```
|
|
88
91
|
|
|
89
|
-
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
### **Assist** -- How to Copy image to app folder
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
import shutil # This module comes packaged with python
|
|
98
|
+
from android.storage import app_storage_path # type: ignore -- This works only on android
|
|
99
|
+
|
|
100
|
+
app_path = os.path.join(app_storage_path(),'app')
|
|
101
|
+
image_path= "/storage/emulated/0/Download/profile.png"
|
|
102
|
+
|
|
103
|
+
shutil.copy(image_path, os.path.join(app_path, "profile.png"))
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
### **Functions Reference**
|
|
90
109
|
|
|
91
|
-
|
|
110
|
+
### 1. `asks_permission_if_needed()`
|
|
92
111
|
|
|
93
|
-
|
|
94
|
-
- **message** (*str*): Notification message body.
|
|
95
|
-
- **style** (*str*): Notification style (`big_text`, `big_picture`, `inbox`, `large_icon`).
|
|
96
|
-
- **img_path** (*str*): Path to the image (for `big_picture` or `large_icon` styles).
|
|
97
|
-
- **channel_id** (*str*): Notification channel ID.
|
|
112
|
+
**Description:**
|
|
98
113
|
|
|
99
|
-
|
|
114
|
+
- Checks if notification permissions are granted and requests them if missing.
|
|
100
115
|
|
|
101
|
-
|
|
102
|
-
|
|
116
|
+
**Usage:**
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
asks_permission_if_needed()
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
### 2. `get_image_uri(relative_path)`
|
|
125
|
+
|
|
126
|
+
**Description:**
|
|
127
|
+
|
|
128
|
+
- Resolves the absolute URI for an image in the app's storage.
|
|
129
|
+
|
|
130
|
+
**Parameters:**
|
|
131
|
+
|
|
132
|
+
- `relative_path` *(str)*: Path to the image (e.g., `assets/imgs/icon.png`).
|
|
133
|
+
|
|
134
|
+
**Returns:**
|
|
135
|
+
|
|
136
|
+
- `Uri`: Android URI object for the image.
|
|
137
|
+
|
|
138
|
+
**Usage:**
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
uri = get_image_uri('assets/imgs/icon.png')
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
### 3. `send_notification(title, message, style=None, img_path=None, channel_id='default_channel')`
|
|
147
|
+
|
|
148
|
+
**Description:**
|
|
149
|
+
|
|
150
|
+
- Sends an Android notification with optional styles and images.
|
|
151
|
+
|
|
152
|
+
**Parameters:**
|
|
153
|
+
|
|
154
|
+
- `title` *(str)*: Notification title.
|
|
155
|
+
- `message` *(str)*: Notification message.
|
|
156
|
+
- `style` *(str, optional)*: Notification style (`big_text`, `big_picture`, `inbox`, `large_icon`).
|
|
157
|
+
- `img_path` *(str, optional)*: Path to the image resource.(for `big_picture` or `large_icon` styles).
|
|
158
|
+
- `channel_id` *(str, optional)*: Notification channel ID.
|
|
159
|
+
|
|
160
|
+
Returns - notification id
|
|
103
161
|
|
|
104
162
|
### Advanced Usage
|
|
105
163
|
|
|
@@ -121,19 +179,32 @@ Feel free to open issues or submit pull requests for improvements!
|
|
|
121
179
|
|
|
122
180
|
Found a bug? Please open an issue on our [GitHub Issues](https://github.com/Fector101/android_notify/issues) page.
|
|
123
181
|
|
|
182
|
+
## Author
|
|
183
|
+
|
|
184
|
+
- Fabian - <fector101@yahoo.com>
|
|
185
|
+
- GitHub: <https://github.com/Fector101/android_notify>
|
|
186
|
+
|
|
187
|
+
For feedback or contributions, feel free to reach out!
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
124
191
|
## ☕ Support the Project
|
|
125
192
|
|
|
126
|
-
If you find
|
|
193
|
+
If you find this project helpful, consider buying me a coffee! Your support helps maintain and improve the project.
|
|
127
194
|
|
|
128
195
|
<a href="https://www.buymeacoffee.com/fector101" target="_blank">
|
|
129
196
|
<img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" height="60">
|
|
130
197
|
</a>
|
|
131
198
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
- Fabian - <fector101@yahoo.com>
|
|
135
|
-
- GitHub: <https://github.com/Fector101/android_notify>
|
|
199
|
+
---
|
|
136
200
|
|
|
137
201
|
## Acknowledgments
|
|
138
202
|
|
|
139
203
|
- Thanks to the Kivy and Pyjnius communities for their support.
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## 🌐 **Links**
|
|
208
|
+
|
|
209
|
+
- **PyPI:** [android-notify on PyPI](https://pypi.org/project/android-notify/)
|
|
210
|
+
- **GitHub:** [Source Code Repository](hhttps://github.com/Fector101/android_notify/)
|
|
@@ -8,21 +8,21 @@
|
|
|
8
8
|
- Support for multiple notification styles:
|
|
9
9
|
- Big Text
|
|
10
10
|
- Big Picture
|
|
11
|
+
- Large Icon
|
|
11
12
|
- Inbox
|
|
12
|
-
-
|
|
13
|
+
- Supports including images in notifications.
|
|
13
14
|
- Compatible with Android 8.0+ (Notification Channels).
|
|
14
15
|
- Customizable notification channels.
|
|
15
|
-
- Support for large icons in notifications.
|
|
16
16
|
|
|
17
17
|
## Installation
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
This package is available on PyPI and can be installed via pip:
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
22
|
pip install android-notify
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
##
|
|
25
|
+
## **Dependencies**
|
|
26
26
|
|
|
27
27
|
**Prerequisites:**
|
|
28
28
|
|
|
@@ -39,10 +39,12 @@ requirements = python3,kivy,pyjnius
|
|
|
39
39
|
android.permissions = POST_NOTIFICATIONS
|
|
40
40
|
|
|
41
41
|
# Required dependencies (write exactly as shown, no quotation marks)
|
|
42
|
-
android.gradle_dependencies = androidx.core:core:1.6.0
|
|
42
|
+
android.gradle_dependencies = androidx.core:core:1.6.0, androidx.core:core-ktx:1.15.0
|
|
43
43
|
android.enable_androidx = True
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
+
---
|
|
47
|
+
|
|
46
48
|
### Example Notification
|
|
47
49
|
|
|
48
50
|
```python
|
|
@@ -74,20 +76,75 @@ send_notification(
|
|
|
74
76
|
)
|
|
75
77
|
```
|
|
76
78
|
|
|
77
|
-
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
### **Assist** -- How to Copy image to app folder
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
import shutil # This module comes packaged with python
|
|
85
|
+
from android.storage import app_storage_path # type: ignore -- This works only on android
|
|
86
|
+
|
|
87
|
+
app_path = os.path.join(app_storage_path(),'app')
|
|
88
|
+
image_path= "/storage/emulated/0/Download/profile.png"
|
|
89
|
+
|
|
90
|
+
shutil.copy(image_path, os.path.join(app_path, "profile.png"))
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
### **Functions Reference**
|
|
78
96
|
|
|
79
|
-
|
|
97
|
+
### 1. `asks_permission_if_needed()`
|
|
80
98
|
|
|
81
|
-
|
|
82
|
-
- **message** (*str*): Notification message body.
|
|
83
|
-
- **style** (*str*): Notification style (`big_text`, `big_picture`, `inbox`, `large_icon`).
|
|
84
|
-
- **img_path** (*str*): Path to the image (for `big_picture` or `large_icon` styles).
|
|
85
|
-
- **channel_id** (*str*): Notification channel ID.
|
|
99
|
+
**Description:**
|
|
86
100
|
|
|
87
|
-
|
|
101
|
+
- Checks if notification permissions are granted and requests them if missing.
|
|
88
102
|
|
|
89
|
-
|
|
90
|
-
|
|
103
|
+
**Usage:**
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
asks_permission_if_needed()
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
### 2. `get_image_uri(relative_path)`
|
|
112
|
+
|
|
113
|
+
**Description:**
|
|
114
|
+
|
|
115
|
+
- Resolves the absolute URI for an image in the app's storage.
|
|
116
|
+
|
|
117
|
+
**Parameters:**
|
|
118
|
+
|
|
119
|
+
- `relative_path` *(str)*: Path to the image (e.g., `assets/imgs/icon.png`).
|
|
120
|
+
|
|
121
|
+
**Returns:**
|
|
122
|
+
|
|
123
|
+
- `Uri`: Android URI object for the image.
|
|
124
|
+
|
|
125
|
+
**Usage:**
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
uri = get_image_uri('assets/imgs/icon.png')
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
### 3. `send_notification(title, message, style=None, img_path=None, channel_id='default_channel')`
|
|
134
|
+
|
|
135
|
+
**Description:**
|
|
136
|
+
|
|
137
|
+
- Sends an Android notification with optional styles and images.
|
|
138
|
+
|
|
139
|
+
**Parameters:**
|
|
140
|
+
|
|
141
|
+
- `title` *(str)*: Notification title.
|
|
142
|
+
- `message` *(str)*: Notification message.
|
|
143
|
+
- `style` *(str, optional)*: Notification style (`big_text`, `big_picture`, `inbox`, `large_icon`).
|
|
144
|
+
- `img_path` *(str, optional)*: Path to the image resource.(for `big_picture` or `large_icon` styles).
|
|
145
|
+
- `channel_id` *(str, optional)*: Notification channel ID.
|
|
146
|
+
|
|
147
|
+
Returns - notification id
|
|
91
148
|
|
|
92
149
|
### Advanced Usage
|
|
93
150
|
|
|
@@ -109,19 +166,32 @@ Feel free to open issues or submit pull requests for improvements!
|
|
|
109
166
|
|
|
110
167
|
Found a bug? Please open an issue on our [GitHub Issues](https://github.com/Fector101/android_notify/issues) page.
|
|
111
168
|
|
|
169
|
+
## Author
|
|
170
|
+
|
|
171
|
+
- Fabian - <fector101@yahoo.com>
|
|
172
|
+
- GitHub: <https://github.com/Fector101/android_notify>
|
|
173
|
+
|
|
174
|
+
For feedback or contributions, feel free to reach out!
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
112
178
|
## ☕ Support the Project
|
|
113
179
|
|
|
114
|
-
If you find
|
|
180
|
+
If you find this project helpful, consider buying me a coffee! Your support helps maintain and improve the project.
|
|
115
181
|
|
|
116
182
|
<a href="https://www.buymeacoffee.com/fector101" target="_blank">
|
|
117
183
|
<img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" height="60">
|
|
118
184
|
</a>
|
|
119
185
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
- Fabian - <fector101@yahoo.com>
|
|
123
|
-
- GitHub: <https://github.com/Fector101/android_notify>
|
|
186
|
+
---
|
|
124
187
|
|
|
125
188
|
## Acknowledgments
|
|
126
189
|
|
|
127
190
|
- Thanks to the Kivy and Pyjnius communities for their support.
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## 🌐 **Links**
|
|
195
|
+
|
|
196
|
+
- **PyPI:** [android-notify on PyPI](https://pypi.org/project/android-notify/)
|
|
197
|
+
- **GitHub:** [Source Code Repository](hhttps://github.com/Fector101/android_notify/)
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
|
|
2
|
+
from jnius import autoclass,cast
|
|
3
|
+
import random
|
|
4
|
+
import os
|
|
5
|
+
|
|
6
|
+
ON_ANDROID = False
|
|
7
|
+
try:
|
|
8
|
+
# Get the required Java classes
|
|
9
|
+
PythonActivity = autoclass('org.kivy.android.PythonActivity')
|
|
10
|
+
NotificationChannel = autoclass('android.app.NotificationChannel')
|
|
11
|
+
String = autoclass('java.lang.String')
|
|
12
|
+
Intent = autoclass('android.content.Intent')
|
|
13
|
+
PendingIntent = autoclass('android.app.PendingIntent')
|
|
14
|
+
context = PythonActivity.mActivity # Get the app's context
|
|
15
|
+
BitmapFactory = autoclass('android.graphics.BitmapFactory')
|
|
16
|
+
BuildVersion = autoclass('android.os.Build$VERSION')
|
|
17
|
+
ON_ANDROID=True
|
|
18
|
+
except Exception as e:
|
|
19
|
+
print('This Package Only Runs on Android !!! ---> Check "https://github.com/Fector101/android_notify/" to see design patterns and more info.')
|
|
20
|
+
|
|
21
|
+
if ON_ANDROID:
|
|
22
|
+
try:
|
|
23
|
+
# NotificationManagerCompat = autoclass('androidx.core.app.NotificationManagerCompat')
|
|
24
|
+
NotificationCompat = autoclass('androidx.core.app.NotificationCompat')
|
|
25
|
+
|
|
26
|
+
# Notification Design
|
|
27
|
+
NotificationCompatBuilder = autoclass('androidx.core.app.NotificationCompat$Builder')
|
|
28
|
+
NotificationCompatBigTextStyle = autoclass('androidx.core.app.NotificationCompat$BigTextStyle')
|
|
29
|
+
# NotificationCompatBigTextStyle = autoclass('android.app.Notification$BigTextStyle')
|
|
30
|
+
NotificationCompatBigPictureStyle = autoclass('androidx.core.app.NotificationCompat$BigPictureStyle')
|
|
31
|
+
NotificationCompatInboxStyle = autoclass('androidx.core.app.NotificationCompat$InboxStyle')
|
|
32
|
+
except Exception as e:
|
|
33
|
+
print("""
|
|
34
|
+
Dependency Error: Add the following in buildozer.spec:
|
|
35
|
+
* android.gradle_dependencies = androidx.core:core-ktx:1.15.0, androidx.core:core:1.6.0
|
|
36
|
+
* android.enable_androidx = True
|
|
37
|
+
* android.permissions = POST_NOTIFICATIONS
|
|
38
|
+
""")
|
|
39
|
+
|
|
40
|
+
def asks_permission_if_needed():
|
|
41
|
+
"""
|
|
42
|
+
Ask for permission to send notifications if needed.
|
|
43
|
+
"""
|
|
44
|
+
from android.permissions import request_permissions, Permission,check_permission # type: ignore
|
|
45
|
+
|
|
46
|
+
permissions=[Permission.POST_NOTIFICATIONS]
|
|
47
|
+
if not all(check_permission(p) for p in permissions):
|
|
48
|
+
request_permissions(permissions)
|
|
49
|
+
|
|
50
|
+
def get_image_uri(relative_path):
|
|
51
|
+
"""
|
|
52
|
+
Get the absolute URI for an image in the assets folder.
|
|
53
|
+
:param relative_path: The relative path to the image (e.g., 'assets/imgs/icon.png').
|
|
54
|
+
:return: Absolute URI java Object (e.g., 'file:///path/to/file.png').
|
|
55
|
+
"""
|
|
56
|
+
from android.storage import app_storage_path # type: ignore
|
|
57
|
+
|
|
58
|
+
output_path = os.path.join(app_storage_path(),'app', relative_path)
|
|
59
|
+
# print(output_path,'output_path') # /data/user/0/org.laner.lan_ft/files/app/assets/imgs/icon.png
|
|
60
|
+
|
|
61
|
+
if not os.path.exists(output_path):
|
|
62
|
+
raise FileNotFoundError(f"Image not found at path: {output_path}")
|
|
63
|
+
|
|
64
|
+
Uri = autoclass('android.net.Uri')
|
|
65
|
+
return Uri.parse(f"file://{output_path}")
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def send_notification(title:str, message:str, style=None, img_path=None, channel_id:str="default_channel"):
|
|
69
|
+
"""
|
|
70
|
+
Send a notification on Android.
|
|
71
|
+
|
|
72
|
+
:param title: Title of the notification.
|
|
73
|
+
:param message: Message body.
|
|
74
|
+
:param style: Style of the notification ('big_text', 'big_picture', 'inbox', 'large_icon').
|
|
75
|
+
:param img_path: Path to the image resource.
|
|
76
|
+
:param channel_id: Notification channel ID.
|
|
77
|
+
"""
|
|
78
|
+
if not ON_ANDROID:
|
|
79
|
+
print('This Package Only Runs on Android !!! ---> Check "https://github.com/Fector101/android_notify/" for Documentation.')
|
|
80
|
+
return
|
|
81
|
+
|
|
82
|
+
# Get notification manager
|
|
83
|
+
notification_manager = context.getSystemService(context.NOTIFICATION_SERVICE)
|
|
84
|
+
|
|
85
|
+
importance= autoclass('android.app.NotificationManager').IMPORTANCE_HIGH # also works #NotificationManager.IMPORTANCE_DEFAULT
|
|
86
|
+
# importance= NotificationManagerCompat.IMPORTANCE_HIGH #autoclass('android.app.NotificationManager').IMPORTANCE_HIGH also works #NotificationManager.IMPORTANCE_DEFAULT
|
|
87
|
+
|
|
88
|
+
# Notification Channel (Required for Android 8.0+)
|
|
89
|
+
if BuildVersion.SDK_INT >= 26:
|
|
90
|
+
channel = NotificationChannel(channel_id, "Default Channel",importance)
|
|
91
|
+
notification_manager.createNotificationChannel(channel)
|
|
92
|
+
|
|
93
|
+
# Build the notification
|
|
94
|
+
builder = NotificationCompatBuilder(context, channel_id)
|
|
95
|
+
builder.setContentTitle(title)
|
|
96
|
+
builder.setContentText(message)
|
|
97
|
+
builder.setSmallIcon(context.getApplicationInfo().icon)
|
|
98
|
+
builder.setDefaults(NotificationCompat.DEFAULT_ALL)
|
|
99
|
+
builder.setPriority(NotificationCompat.PRIORITY_HIGH)
|
|
100
|
+
|
|
101
|
+
# Get Image
|
|
102
|
+
img=None
|
|
103
|
+
if img_path:
|
|
104
|
+
try:
|
|
105
|
+
img = get_image_uri(img_path)
|
|
106
|
+
except FileNotFoundError as e:
|
|
107
|
+
print('Failed Adding Bitmap: ',e)
|
|
108
|
+
|
|
109
|
+
# Apply notification styles
|
|
110
|
+
try:
|
|
111
|
+
if style == "big_text":
|
|
112
|
+
big_text_style = NotificationCompatBigTextStyle()
|
|
113
|
+
big_text_style.bigText(message)
|
|
114
|
+
builder.setStyle(big_text_style)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
elif style == "big_picture" and img_path:
|
|
118
|
+
bitmap = BitmapFactory.decodeStream(context.getContentResolver().openInputStream(img))
|
|
119
|
+
builder.setLargeIcon(bitmap)
|
|
120
|
+
big_picture_style = NotificationCompatBigPictureStyle().bigPicture(bitmap)
|
|
121
|
+
builder.setStyle(big_picture_style)
|
|
122
|
+
elif style == "inbox":
|
|
123
|
+
inbox_style = NotificationCompatInboxStyle()
|
|
124
|
+
for line in message.split("\n"):
|
|
125
|
+
inbox_style.addLine(line)
|
|
126
|
+
builder.setStyle(inbox_style)
|
|
127
|
+
elif style == "large_icon" and img_path:
|
|
128
|
+
bitmap = BitmapFactory.decodeStream(context.getContentResolver().openInputStream(img))
|
|
129
|
+
builder.setLargeIcon(bitmap)
|
|
130
|
+
except Exception as e:
|
|
131
|
+
print('Failed Adding Style: ',e)
|
|
132
|
+
# Display the notification
|
|
133
|
+
notification_id = random.randint(0, 100)
|
|
134
|
+
notification_manager.notify(notification_id, builder.build())
|
|
135
|
+
return notification_id
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
|
-
Name:
|
|
3
|
-
Version: 1.
|
|
2
|
+
Name: android_notify
|
|
3
|
+
Version: 1.2
|
|
4
4
|
Summary: A Python package for sending Android notifications.
|
|
5
5
|
Home-page: https://github.com/Fector101/android_notify/
|
|
6
6
|
Author: Fabian
|
|
@@ -9,6 +9,7 @@ Project-URL: Funding, https://buymeacoffee.com/fector101
|
|
|
9
9
|
Project-URL: Source, https://github.com/Fector101/android_notify/
|
|
10
10
|
Requires-Python: >=3.6
|
|
11
11
|
Description-Content-Type: text/markdown
|
|
12
|
+
Requires-Dist: pyjnius
|
|
12
13
|
|
|
13
14
|
# Android Notify
|
|
14
15
|
|
|
@@ -20,21 +21,21 @@ Description-Content-Type: text/markdown
|
|
|
20
21
|
- Support for multiple notification styles:
|
|
21
22
|
- Big Text
|
|
22
23
|
- Big Picture
|
|
24
|
+
- Large Icon
|
|
23
25
|
- Inbox
|
|
24
|
-
-
|
|
26
|
+
- Supports including images in notifications.
|
|
25
27
|
- Compatible with Android 8.0+ (Notification Channels).
|
|
26
28
|
- Customizable notification channels.
|
|
27
|
-
- Support for large icons in notifications.
|
|
28
29
|
|
|
29
30
|
## Installation
|
|
30
31
|
|
|
31
|
-
|
|
32
|
+
This package is available on PyPI and can be installed via pip:
|
|
32
33
|
|
|
33
34
|
```bash
|
|
34
35
|
pip install android-notify
|
|
35
36
|
```
|
|
36
37
|
|
|
37
|
-
##
|
|
38
|
+
## **Dependencies**
|
|
38
39
|
|
|
39
40
|
**Prerequisites:**
|
|
40
41
|
|
|
@@ -51,10 +52,12 @@ requirements = python3,kivy,pyjnius
|
|
|
51
52
|
android.permissions = POST_NOTIFICATIONS
|
|
52
53
|
|
|
53
54
|
# Required dependencies (write exactly as shown, no quotation marks)
|
|
54
|
-
android.gradle_dependencies = androidx.core:core:1.6.0
|
|
55
|
+
android.gradle_dependencies = androidx.core:core:1.6.0, androidx.core:core-ktx:1.15.0
|
|
55
56
|
android.enable_androidx = True
|
|
56
57
|
```
|
|
57
58
|
|
|
59
|
+
---
|
|
60
|
+
|
|
58
61
|
### Example Notification
|
|
59
62
|
|
|
60
63
|
```python
|
|
@@ -86,20 +89,75 @@ send_notification(
|
|
|
86
89
|
)
|
|
87
90
|
```
|
|
88
91
|
|
|
89
|
-
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
### **Assist** -- How to Copy image to app folder
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
import shutil # This module comes packaged with python
|
|
98
|
+
from android.storage import app_storage_path # type: ignore -- This works only on android
|
|
99
|
+
|
|
100
|
+
app_path = os.path.join(app_storage_path(),'app')
|
|
101
|
+
image_path= "/storage/emulated/0/Download/profile.png"
|
|
102
|
+
|
|
103
|
+
shutil.copy(image_path, os.path.join(app_path, "profile.png"))
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
### **Functions Reference**
|
|
90
109
|
|
|
91
|
-
|
|
110
|
+
### 1. `asks_permission_if_needed()`
|
|
92
111
|
|
|
93
|
-
|
|
94
|
-
- **message** (*str*): Notification message body.
|
|
95
|
-
- **style** (*str*): Notification style (`big_text`, `big_picture`, `inbox`, `large_icon`).
|
|
96
|
-
- **img_path** (*str*): Path to the image (for `big_picture` or `large_icon` styles).
|
|
97
|
-
- **channel_id** (*str*): Notification channel ID.
|
|
112
|
+
**Description:**
|
|
98
113
|
|
|
99
|
-
|
|
114
|
+
- Checks if notification permissions are granted and requests them if missing.
|
|
100
115
|
|
|
101
|
-
|
|
102
|
-
|
|
116
|
+
**Usage:**
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
asks_permission_if_needed()
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
### 2. `get_image_uri(relative_path)`
|
|
125
|
+
|
|
126
|
+
**Description:**
|
|
127
|
+
|
|
128
|
+
- Resolves the absolute URI for an image in the app's storage.
|
|
129
|
+
|
|
130
|
+
**Parameters:**
|
|
131
|
+
|
|
132
|
+
- `relative_path` *(str)*: Path to the image (e.g., `assets/imgs/icon.png`).
|
|
133
|
+
|
|
134
|
+
**Returns:**
|
|
135
|
+
|
|
136
|
+
- `Uri`: Android URI object for the image.
|
|
137
|
+
|
|
138
|
+
**Usage:**
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
uri = get_image_uri('assets/imgs/icon.png')
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
### 3. `send_notification(title, message, style=None, img_path=None, channel_id='default_channel')`
|
|
147
|
+
|
|
148
|
+
**Description:**
|
|
149
|
+
|
|
150
|
+
- Sends an Android notification with optional styles and images.
|
|
151
|
+
|
|
152
|
+
**Parameters:**
|
|
153
|
+
|
|
154
|
+
- `title` *(str)*: Notification title.
|
|
155
|
+
- `message` *(str)*: Notification message.
|
|
156
|
+
- `style` *(str, optional)*: Notification style (`big_text`, `big_picture`, `inbox`, `large_icon`).
|
|
157
|
+
- `img_path` *(str, optional)*: Path to the image resource.(for `big_picture` or `large_icon` styles).
|
|
158
|
+
- `channel_id` *(str, optional)*: Notification channel ID.
|
|
159
|
+
|
|
160
|
+
Returns - notification id
|
|
103
161
|
|
|
104
162
|
### Advanced Usage
|
|
105
163
|
|
|
@@ -121,19 +179,32 @@ Feel free to open issues or submit pull requests for improvements!
|
|
|
121
179
|
|
|
122
180
|
Found a bug? Please open an issue on our [GitHub Issues](https://github.com/Fector101/android_notify/issues) page.
|
|
123
181
|
|
|
182
|
+
## Author
|
|
183
|
+
|
|
184
|
+
- Fabian - <fector101@yahoo.com>
|
|
185
|
+
- GitHub: <https://github.com/Fector101/android_notify>
|
|
186
|
+
|
|
187
|
+
For feedback or contributions, feel free to reach out!
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
124
191
|
## ☕ Support the Project
|
|
125
192
|
|
|
126
|
-
If you find
|
|
193
|
+
If you find this project helpful, consider buying me a coffee! Your support helps maintain and improve the project.
|
|
127
194
|
|
|
128
195
|
<a href="https://www.buymeacoffee.com/fector101" target="_blank">
|
|
129
196
|
<img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" height="60">
|
|
130
197
|
</a>
|
|
131
198
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
- Fabian - <fector101@yahoo.com>
|
|
135
|
-
- GitHub: <https://github.com/Fector101/android_notify>
|
|
199
|
+
---
|
|
136
200
|
|
|
137
201
|
## Acknowledgments
|
|
138
202
|
|
|
139
203
|
- Thanks to the Kivy and Pyjnius communities for their support.
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## 🌐 **Links**
|
|
208
|
+
|
|
209
|
+
- **PyPI:** [android-notify on PyPI](https://pypi.org/project/android-notify/)
|
|
210
|
+
- **GitHub:** [Source Code Repository](hhttps://github.com/Fector101/android_notify/)
|
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
from jnius import autoclass,cast
|
|
3
|
-
import random
|
|
4
|
-
import os
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def asks_permission_if_needed():
|
|
8
|
-
"""
|
|
9
|
-
Ask for permission to send notifications if needed.
|
|
10
|
-
"""
|
|
11
|
-
# Get the required Java classes
|
|
12
|
-
from android.permissions import request_permissions, Permission,check_permission # type: ignore
|
|
13
|
-
|
|
14
|
-
def check_permissions(permissions):
|
|
15
|
-
for permission in permissions:
|
|
16
|
-
if check_permission(permission) != True:
|
|
17
|
-
return False
|
|
18
|
-
return True
|
|
19
|
-
|
|
20
|
-
permissions=[Permission.POST_NOTIFICATIONS]
|
|
21
|
-
if check_permissions(permissions):
|
|
22
|
-
request_permissions(permissions)
|
|
23
|
-
|
|
24
|
-
def get_image_uri(relative_path):
|
|
25
|
-
"""
|
|
26
|
-
Get the absolute URI for an image in the assets folder.
|
|
27
|
-
:param relative_path: The relative path to the image (e.g., 'assets/imgs/icon.png').
|
|
28
|
-
:return: Absolute URI java Object (e.g., 'file:///path/to/file.png').
|
|
29
|
-
"""
|
|
30
|
-
from android.storage import app_storage_path # type: ignore
|
|
31
|
-
# print("app_storage_path()",app_storage_path())
|
|
32
|
-
|
|
33
|
-
output_path = os.path.join(app_storage_path(),'app', relative_path)
|
|
34
|
-
# print(output_path,'output_path') # /data/user/0/org.laner.lan_ft/files/app/assets/imgs/icon.png
|
|
35
|
-
|
|
36
|
-
Uri = autoclass('android.net.Uri')
|
|
37
|
-
return Uri.parse(f"file://{output_path}")
|
|
38
|
-
|
|
39
|
-
def send_notification(title, message, style=None, img_path=None, channel_id="default_channel"):
|
|
40
|
-
"""
|
|
41
|
-
Send a notification on Android.
|
|
42
|
-
|
|
43
|
-
:param title: Title of the notification.
|
|
44
|
-
:param message: Message body.
|
|
45
|
-
:param style: Style of the notification ('big_text', 'big_picture', 'inbox').
|
|
46
|
-
:param image: Image URL or drawable for 'big_picture' style.
|
|
47
|
-
:param channel_id: Notification channel ID.
|
|
48
|
-
"""
|
|
49
|
-
# TODO check if running on android short circuit and return message if not
|
|
50
|
-
|
|
51
|
-
# Get the required Java classes
|
|
52
|
-
# Notification Base
|
|
53
|
-
PythonActivity = autoclass('org.kivy.android.PythonActivity')
|
|
54
|
-
NotificationChannel = autoclass('android.app.NotificationChannel')
|
|
55
|
-
String = autoclass('java.lang.String')
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
NotificationManagerCompat = autoclass('androidx.core.app.NotificationManagerCompat')
|
|
59
|
-
NotificationCompat = autoclass('androidx.core.app.NotificationCompat')
|
|
60
|
-
|
|
61
|
-
# Notification Design
|
|
62
|
-
NotificationCompatBuilder = autoclass('androidx.core.app.NotificationCompat$Builder')
|
|
63
|
-
NotificationCompatBigTextStyle = autoclass('androidx.core.app.NotificationCompat$BigTextStyle')
|
|
64
|
-
# NotificationCompatBigTextStyle = autoclass('android.app.Notification$BigTextStyle')
|
|
65
|
-
|
|
66
|
-
NotificationCompatBigPictureStyle = autoclass('androidx.core.app.NotificationCompat$BigPictureStyle')
|
|
67
|
-
NotificationCompatInboxStyle = autoclass('androidx.core.app.NotificationCompat$InboxStyle')
|
|
68
|
-
BitmapFactory = autoclass('android.graphics.BitmapFactory')
|
|
69
|
-
BuildVersion = autoclass('android.os.Build$VERSION')
|
|
70
|
-
PendingIntent = autoclass('android.app.PendingIntent')
|
|
71
|
-
Intent = autoclass('android.content.Intent')
|
|
72
|
-
|
|
73
|
-
# Get the app's context and notification manager
|
|
74
|
-
context = PythonActivity.mActivity
|
|
75
|
-
notification_manager = context.getSystemService(context.NOTIFICATION_SERVICE)
|
|
76
|
-
|
|
77
|
-
importance= NotificationManagerCompat.IMPORTANCE_HIGH #autoclass('android.app.NotificationManager').IMPORTANCE_HIGH also works #NotificationManager.IMPORTANCE_DEFAULT
|
|
78
|
-
|
|
79
|
-
# Notification Channel (Required for Android 8.0+)
|
|
80
|
-
if BuildVersion.SDK_INT >= 26:
|
|
81
|
-
print('entered....')
|
|
82
|
-
channel = NotificationChannel(
|
|
83
|
-
channel_id,
|
|
84
|
-
"Default Channel",
|
|
85
|
-
importance
|
|
86
|
-
)
|
|
87
|
-
notification_manager.createNotificationChannel(channel)
|
|
88
|
-
|
|
89
|
-
# Build the notification
|
|
90
|
-
builder = NotificationCompatBuilder(context, channel_id)
|
|
91
|
-
builder.setContentTitle(title)
|
|
92
|
-
builder.setContentText(message)
|
|
93
|
-
builder.setSmallIcon(context.getApplicationInfo().icon)
|
|
94
|
-
builder.setDefaults(NotificationCompat.DEFAULT_ALL)
|
|
95
|
-
builder.setPriority(NotificationCompat.PRIORITY_HIGH)
|
|
96
|
-
|
|
97
|
-
# Get Image
|
|
98
|
-
img=img_path
|
|
99
|
-
if img_path:
|
|
100
|
-
try:
|
|
101
|
-
img = get_image_uri(img_path)
|
|
102
|
-
except Exception as e:
|
|
103
|
-
print('Failed getting Image path',e)
|
|
104
|
-
|
|
105
|
-
# Add Actions (Buttons)
|
|
106
|
-
|
|
107
|
-
# add Action 1 Button
|
|
108
|
-
# try:
|
|
109
|
-
# # Create Action 1
|
|
110
|
-
# action_intent = Intent(context, PythonActivity)
|
|
111
|
-
# action_intent.setAction("ACTION_ONE")
|
|
112
|
-
# pending_action_intent = PendingIntent.getActivity(
|
|
113
|
-
# context,
|
|
114
|
-
# 0,
|
|
115
|
-
# action_intent,
|
|
116
|
-
# PendingIntent.FLAG_IMMUTABLE
|
|
117
|
-
# )
|
|
118
|
-
|
|
119
|
-
# # Convert text to CharSequence
|
|
120
|
-
# action_text = cast('java.lang.CharSequence', String("Action 1"))
|
|
121
|
-
|
|
122
|
-
# # Add action with proper types
|
|
123
|
-
# builder.addAction(
|
|
124
|
-
# int(context.getApplicationInfo().icon), # Cast icon to int
|
|
125
|
-
# action_text, # CharSequence text
|
|
126
|
-
# pending_action_intent # PendingIntent
|
|
127
|
-
# )
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
# # Set content intent for notification tap
|
|
131
|
-
# builder.setContentIntent(pending_action_intent)
|
|
132
|
-
# except Exception as e:
|
|
133
|
-
# print('Failed adding Action 1',e)
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
# Apply styles
|
|
137
|
-
if style == "big_text":
|
|
138
|
-
big_text_style = NotificationCompatBigTextStyle()
|
|
139
|
-
big_text_style.bigText(message)
|
|
140
|
-
builder.setStyle(big_text_style)
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
elif style == "big_picture" and img_path:
|
|
144
|
-
try:
|
|
145
|
-
bitmap = BitmapFactory.decodeStream(context.getContentResolver().openInputStream(img))
|
|
146
|
-
# bitmap = BitmapFactory.decodeFile(img_path)
|
|
147
|
-
builder.setLargeIcon(bitmap)
|
|
148
|
-
big_picture_style = NotificationCompatBigPictureStyle().bigPicture(bitmap)
|
|
149
|
-
# big_picture_style.bigPicture(bitmap).bigLargeIcon(None)
|
|
150
|
-
# big_picture_style.bigLargeIcon(bitmap) # This just changes dropdown app icon
|
|
151
|
-
|
|
152
|
-
builder.setStyle(big_picture_style)
|
|
153
|
-
except Exception as e:
|
|
154
|
-
print('Failed Adding Bitmap...', e)
|
|
155
|
-
elif style == "inbox":
|
|
156
|
-
inbox_style = NotificationCompatInboxStyle()
|
|
157
|
-
for line in message.split("\n"):
|
|
158
|
-
inbox_style.addLine(line)
|
|
159
|
-
builder.setStyle(inbox_style)
|
|
160
|
-
elif style == "large_icon" and img_path:
|
|
161
|
-
try:
|
|
162
|
-
bitmap = BitmapFactory.decodeStream(context.getContentResolver().openInputStream(img))
|
|
163
|
-
builder.setLargeIcon(bitmap)
|
|
164
|
-
except Exception as e:
|
|
165
|
-
print('Failed Large Icon...', e)
|
|
166
|
-
|
|
167
|
-
# Show the notification
|
|
168
|
-
notification_manager.notify(random.randint(0, 100), builder.build())
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|