android-notify 1.50.1__py3-none-any.whl → 1.51.1__py3-none-any.whl
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/styles.py +5 -4
- android_notify/sword.py +134 -66
- {android_notify-1.50.1.dist-info → android_notify-1.51.1.dist-info}/METADATA +41 -55
- android_notify-1.51.1.dist-info/RECORD +9 -0
- android_notify-1.50.1.dist-info/RECORD +0 -9
- {android_notify-1.50.1.dist-info → android_notify-1.51.1.dist-info}/WHEEL +0 -0
- {android_notify-1.50.1.dist-info → android_notify-1.51.1.dist-info}/top_level.txt +0 -0
android_notify/styles.py
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
+
"""Contains Safe way to call Styles"""
|
|
2
|
+
|
|
1
3
|
class NotificationStyles():
|
|
2
4
|
""" Safely Adding Styles"""
|
|
3
5
|
DEFAULT = "simple"
|
|
4
|
-
|
|
6
|
+
|
|
5
7
|
PROGRESS = "progress"
|
|
6
8
|
INBOX = "inbox"
|
|
7
9
|
BIG_TEXT = "big_text"
|
|
8
|
-
|
|
10
|
+
|
|
9
11
|
LARGE_ICON = "large_icon"
|
|
10
12
|
BIG_PICTURE = "big_picture"
|
|
11
13
|
BOTH_IMGS = "both_imgs"
|
|
12
|
-
|
|
14
|
+
|
|
13
15
|
MESSAGING = "messaging" # TODO
|
|
14
16
|
CUSTOM = "custom" # TODO
|
|
15
|
-
|
android_notify/sword.py
CHANGED
|
@@ -2,15 +2,19 @@
|
|
|
2
2
|
import difflib
|
|
3
3
|
import traceback
|
|
4
4
|
import os
|
|
5
|
+
import threading
|
|
5
6
|
import re
|
|
7
|
+
from .styles import NotificationStyles
|
|
6
8
|
|
|
7
9
|
DEV=0
|
|
8
10
|
ON_ANDROID = False
|
|
9
11
|
|
|
10
12
|
try:
|
|
13
|
+
# Android Imports
|
|
11
14
|
from jnius import autoclass,cast # Needs Java to be installed pylint: disable=W0611, C0114
|
|
12
15
|
from android import activity # pylint: disable=import-error
|
|
13
16
|
from android.config import ACTIVITY_CLASS_NAME # pylint: disable=import-error
|
|
17
|
+
from android.runnable import run_on_ui_thread # pylint: disable=import-error
|
|
14
18
|
|
|
15
19
|
# Get the required Java classes
|
|
16
20
|
Bundle = autoclass('android.os.Bundle')
|
|
@@ -28,6 +32,14 @@ except Exception as e:# pylint: disable=W0718
|
|
|
28
32
|
MESSAGE='This Package Only Runs on Android !!! ---> Check "https://github.com/Fector101/android_notify/" to see design patterns and more info.' # pylint: disable=C0301
|
|
29
33
|
print(MESSAGE if DEV else '')
|
|
30
34
|
|
|
35
|
+
# This is so no crashes when developing on PC
|
|
36
|
+
def run_on_ui_thread(func):
|
|
37
|
+
"""Fallback for Developing on PC"""
|
|
38
|
+
def wrapper(*args, **kwargs):
|
|
39
|
+
print("Simulating run on UI thread")
|
|
40
|
+
return func(*args, **kwargs)
|
|
41
|
+
return wrapper
|
|
42
|
+
|
|
31
43
|
if ON_ANDROID:
|
|
32
44
|
try:
|
|
33
45
|
from android.permissions import request_permissions, Permission,check_permission # pylint: disable=E0401
|
|
@@ -62,9 +74,12 @@ class Notification:
|
|
|
62
74
|
both_imgs == using lager icon and big picture
|
|
63
75
|
:param big_picture_path: Relative Path to the image resource.
|
|
64
76
|
:param large_icon_path: Relative Path to the image resource.
|
|
65
|
-
:param
|
|
77
|
+
:param progress_current_value: interger To set progress bar current value.
|
|
78
|
+
:param progress_max_value: interger To set Max range for progress bar.
|
|
79
|
+
:param subject: Preview text For `big_Text` style `message`.
|
|
66
80
|
---
|
|
67
81
|
(Advance Options)
|
|
82
|
+
:param callback: Function for notification Click.
|
|
68
83
|
:param channel_name: - str Defaults to "Default Channel"
|
|
69
84
|
:param channel_id: - str Defaults to "default_channel"
|
|
70
85
|
---
|
|
@@ -84,18 +99,23 @@ class Notification:
|
|
|
84
99
|
] # TODO make pattern for non-android Notifications
|
|
85
100
|
defaults={
|
|
86
101
|
'title':'Default Title',
|
|
87
|
-
'message':'Default Message',
|
|
102
|
+
'message':'Default Message',
|
|
88
103
|
'style':'simple',
|
|
89
104
|
'big_picture_path':'',
|
|
90
105
|
'large_icon_path':'',
|
|
91
106
|
'progress_max_value': 0,
|
|
92
107
|
'progress_current_value': 0,
|
|
108
|
+
'subject':'',
|
|
93
109
|
'channel_name':'Default Channel',
|
|
94
110
|
'channel_id':'default_channel',
|
|
95
111
|
'logs':True,
|
|
96
112
|
"identifer": '',
|
|
97
113
|
'callback': None
|
|
98
114
|
}
|
|
115
|
+
# TODO specify types in a better way instead of using
|
|
116
|
+
# if key not in non_string_keys: value = str(value) to fix
|
|
117
|
+
#non_string_keys=['progress_max_value','progress_current_value','callback','logs']
|
|
118
|
+
# TODO using default values to check types
|
|
99
119
|
# During Development (When running on PC)
|
|
100
120
|
logs=not ON_ANDROID
|
|
101
121
|
def __init__(self,**kwargs):
|
|
@@ -108,6 +128,7 @@ class Notification:
|
|
|
108
128
|
self.big_picture_path=''
|
|
109
129
|
self.progress_current_value=0
|
|
110
130
|
self.progress_max_value=0
|
|
131
|
+
self.subject= ''
|
|
111
132
|
|
|
112
133
|
# For Nofitication Functions
|
|
113
134
|
self.identifer=''
|
|
@@ -151,14 +172,17 @@ class Notification:
|
|
|
151
172
|
self.message=new_message
|
|
152
173
|
if ON_ANDROID:
|
|
153
174
|
self.__builder.setContentText(new_message)
|
|
154
|
-
|
|
175
|
+
return True
|
|
176
|
+
return 'Updated'
|
|
155
177
|
def updateProgressBar(self,current_value,message:str=''):
|
|
156
|
-
"""message defaults to last message"""
|
|
157
|
-
if not ON_ANDROID:
|
|
158
|
-
return
|
|
178
|
+
"""current_value is the value to set progressbar, message defaults to last message"""
|
|
159
179
|
|
|
160
180
|
if self.logs:
|
|
161
181
|
print(f'Progress Bar Update value: {current_value}')
|
|
182
|
+
|
|
183
|
+
if not ON_ANDROID:
|
|
184
|
+
return
|
|
185
|
+
|
|
162
186
|
self.__builder.setProgress(self.progress_max_value, current_value, False)
|
|
163
187
|
if message:
|
|
164
188
|
self.__builder.setContentText(String(message))
|
|
@@ -166,8 +190,16 @@ class Notification:
|
|
|
166
190
|
|
|
167
191
|
def removeProgressBar(self,message=''):
|
|
168
192
|
"""message defaults to last message"""
|
|
193
|
+
|
|
194
|
+
if self.logs:
|
|
195
|
+
print('removed')
|
|
196
|
+
|
|
197
|
+
if not ON_ANDROID:
|
|
198
|
+
return True
|
|
199
|
+
|
|
169
200
|
if message:
|
|
170
201
|
self.__builder.setContentText(String(message))
|
|
202
|
+
return True
|
|
171
203
|
self.__builder.setProgress(0, 0, False)
|
|
172
204
|
self.notification_manager.notify(self.__id, self.__builder.build())
|
|
173
205
|
|
|
@@ -183,8 +215,9 @@ class Notification:
|
|
|
183
215
|
self.notification_manager.notify(self.__id, self.__builder.build())
|
|
184
216
|
elif self.logs:
|
|
185
217
|
string_to_display=''
|
|
218
|
+
print("\n Sent Notification!!!")
|
|
186
219
|
for name,value in vars(self).items():
|
|
187
|
-
if value and name
|
|
220
|
+
if value and name in ["title", "message", "style", "subject", "large_icon_path", "big_picture_path", "progress_current_value", "progress_max_value", "channel_name"]:
|
|
188
221
|
string_to_display += f'\n {name}: {value}'
|
|
189
222
|
string_to_display +="\n (Won't Print Logs When Complied,except if selected `Notification.logs=True`)"
|
|
190
223
|
print(string_to_display)
|
|
@@ -254,63 +287,48 @@ class Notification:
|
|
|
254
287
|
self.notification_manager.createNotificationChannel(channel)
|
|
255
288
|
|
|
256
289
|
# Build the notification
|
|
257
|
-
#
|
|
290
|
+
# str() This is to prevent Error When user does Notification.title='blah' instead of Notification(title='blah'
|
|
291
|
+
# TODO fix this by creating a on_Title method in other versions
|
|
258
292
|
self.__builder.setContentTitle(str(self.title))
|
|
259
|
-
self.
|
|
293
|
+
if self.style == NotificationStyles.BIG_TEXT:
|
|
294
|
+
self.__builder.setContentText(str(self.subject))
|
|
295
|
+
else:
|
|
296
|
+
self.__builder.setContentText(str(self.message))
|
|
260
297
|
self.__builder.setSmallIcon(context.getApplicationInfo().icon)
|
|
261
298
|
self.__builder.setDefaults(NotificationCompat.DEFAULT_ALL) # pylint: disable=E0606
|
|
262
299
|
self.__builder.setPriority(NotificationCompat.PRIORITY_DEFAULT if self.silent else NotificationCompat.PRIORITY_HIGH)
|
|
300
|
+
self.__builder.setOnlyAlertOnce(True)
|
|
263
301
|
self.__addIntentToOpenApp()
|
|
302
|
+
|
|
264
303
|
def __addNotificationStyle(self):
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
large_icon_javapath=None
|
|
268
|
-
if self.large_icon_path:
|
|
269
|
-
try:
|
|
270
|
-
large_icon_javapath = self.__get_image_uri(self.large_icon_path)
|
|
271
|
-
except FileNotFoundError as e:
|
|
272
|
-
print('Failed Adding Big Picture Bitmap: ',e)
|
|
273
|
-
|
|
274
|
-
big_pic_javapath=None
|
|
275
|
-
if self.big_picture_path:
|
|
276
|
-
try:
|
|
277
|
-
big_pic_javapath = self.__get_image_uri(self.big_picture_path)
|
|
278
|
-
except FileNotFoundError as e:
|
|
279
|
-
print('Failed Adding Lagre Icon Bitmap: ',e)
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
if self.style == "big_text":
|
|
304
|
+
if self.style == NotificationStyles.BIG_TEXT:
|
|
283
305
|
big_text_style = NotificationCompatBigTextStyle() # pylint: disable=E0606
|
|
284
306
|
big_text_style.bigText(self.message)
|
|
285
307
|
self.__builder.setStyle(big_text_style)
|
|
286
|
-
|
|
287
|
-
elif self.style ==
|
|
308
|
+
|
|
309
|
+
elif self.style == NotificationStyles.INBOX:
|
|
288
310
|
inbox_style = NotificationCompatInboxStyle() # pylint: disable=E0606
|
|
289
311
|
for line in self.message.split("\n"):
|
|
290
312
|
inbox_style.addLine(line)
|
|
291
313
|
self.__builder.setStyle(inbox_style)
|
|
292
|
-
|
|
293
|
-
elif self.style ==
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
self.
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
big_picture_style = NotificationCompatBigPictureStyle().bigPicture(big_pic_bitmap)
|
|
306
|
-
self.__builder.setStyle(big_picture_style)
|
|
307
|
-
if large_icon_javapath:
|
|
308
|
-
large_icon_bitmap = self.__getBitmap(large_icon_javapath)
|
|
309
|
-
self.__builder.setLargeIcon(large_icon_bitmap)
|
|
314
|
+
|
|
315
|
+
elif self.style == NotificationStyles.BIG_PICTURE and self.big_picture_path:
|
|
316
|
+
self.__buildImg(self.big_picture_path, self.style)
|
|
317
|
+
|
|
318
|
+
elif self.style == NotificationStyles.LARGE_ICON and self.large_icon_path:
|
|
319
|
+
self.__buildImg(self.large_icon_path, self.style)
|
|
320
|
+
|
|
321
|
+
elif self.style == NotificationStyles.BOTH_IMGS and (self.big_picture_path or self.large_icon_path):
|
|
322
|
+
if self.big_picture_path:
|
|
323
|
+
self.__buildImg(self.big_picture_path, NotificationStyles.BIG_PICTURE)
|
|
324
|
+
if self.large_icon_path:
|
|
325
|
+
self.__buildImg(self.large_icon_path, NotificationStyles.LARGE_ICON)
|
|
326
|
+
|
|
310
327
|
elif self.style == 'progress':
|
|
311
328
|
self.__builder.setContentTitle(String(self.title))
|
|
312
329
|
self.__builder.setContentText(String(self.message))
|
|
313
330
|
self.__builder.setProgress(self.progress_max_value, self.progress_current_value, False)
|
|
331
|
+
|
|
314
332
|
# elif self.style == 'custom':
|
|
315
333
|
# self.__builder = self.__doCustomStyle()
|
|
316
334
|
|
|
@@ -318,6 +336,67 @@ class Notification:
|
|
|
318
336
|
# # TODO Will implement when needed
|
|
319
337
|
# return self.__builder
|
|
320
338
|
|
|
339
|
+
def __buildImg(self, user_img,img_style):
|
|
340
|
+
if user_img.startswith('http://') or user_img.startswith('https://'):
|
|
341
|
+
thread = threading.Thread(
|
|
342
|
+
target=self.__getImgFromURL,
|
|
343
|
+
args=(user_img,img_style,)
|
|
344
|
+
)
|
|
345
|
+
thread.start()
|
|
346
|
+
else:
|
|
347
|
+
if NotificationStyles.BIG_PICTURE:
|
|
348
|
+
bitmap = self.__getImgFromPath(user_img)
|
|
349
|
+
if bitmap:
|
|
350
|
+
big_picture_style = NotificationCompatBigPictureStyle().bigPicture(bitmap) # pylint: disable=E0606
|
|
351
|
+
self.__builder.setStyle(big_picture_style)
|
|
352
|
+
elif NotificationStyles.LARGE_ICON:
|
|
353
|
+
bitmap = self.__getImgFromPath(user_img)
|
|
354
|
+
if bitmap:
|
|
355
|
+
self.__builder.setLargeIcon(bitmap)
|
|
356
|
+
|
|
357
|
+
def __getImgFromPath(self, relative_path):
|
|
358
|
+
app_folder=os.path.join(app_storage_path(),'app') # pylint: disable=possibly-used-before-assignment
|
|
359
|
+
output_path = os.path.join(app_folder, relative_path)
|
|
360
|
+
if not os.path.exists(output_path):
|
|
361
|
+
print(f"\nImage not found at path: {output_path}, (Local images gotten from App Path)")
|
|
362
|
+
print("These are the existing files in your app Folder:")
|
|
363
|
+
print('['+', '.join(os.listdir(app_folder)) + ']')
|
|
364
|
+
return None
|
|
365
|
+
Uri = autoclass('android.net.Uri')
|
|
366
|
+
uri = Uri.parse(f"file://{output_path}")
|
|
367
|
+
return BitmapFactory.decodeStream(context.getContentResolver().openInputStream(uri))
|
|
368
|
+
|
|
369
|
+
def __getImgFromURL(self,url,img_style):
|
|
370
|
+
print("getting image from URL---")
|
|
371
|
+
try:
|
|
372
|
+
URL = autoclass('java.net.URL')
|
|
373
|
+
url = URL(url)
|
|
374
|
+
connection = url.openConnection()
|
|
375
|
+
connection.connect()
|
|
376
|
+
input_stream = connection.getInputStream()
|
|
377
|
+
bitmap = BitmapFactory.decodeStream(input_stream)
|
|
378
|
+
input_stream.close()
|
|
379
|
+
self.__applyNotificationImage(bitmap,img_style)
|
|
380
|
+
except Exception as e:
|
|
381
|
+
# TODO get type of JAVA Error
|
|
382
|
+
print('Error Type ',e)
|
|
383
|
+
print('Failed to get Img from URL ',traceback.format_exc())
|
|
384
|
+
|
|
385
|
+
@run_on_ui_thread
|
|
386
|
+
def __applyNotificationImage(self,bitmap,img_style):
|
|
387
|
+
print('appying notification image thread ', bitmap)
|
|
388
|
+
try:
|
|
389
|
+
if img_style == NotificationStyles.BIG_PICTURE:
|
|
390
|
+
big_picture_style = NotificationCompatBigPictureStyle().bigPicture(bitmap) # pylint: disable=E0606
|
|
391
|
+
self.__builder.setStyle(big_picture_style)
|
|
392
|
+
elif img_style == NotificationStyles.LARGE_ICON:
|
|
393
|
+
self.__builder.setLargeIcon(bitmap)
|
|
394
|
+
self.notification_manager.notify(self.__id, self.__builder.build())
|
|
395
|
+
print('added notification image done-------')
|
|
396
|
+
except Exception as e:
|
|
397
|
+
print('I could stop ',e)
|
|
398
|
+
print('could stop get Img from URL ',traceback.format_exc())
|
|
399
|
+
|
|
321
400
|
def __getUniqueID(self):
|
|
322
401
|
notification_id = self.notification_ids[-1] + 1
|
|
323
402
|
self.notification_ids.append(notification_id)
|
|
@@ -335,24 +414,6 @@ class Notification:
|
|
|
335
414
|
if not all(check_permission(p) for p in permissions):
|
|
336
415
|
request_permissions(permissions,on_permissions_result) # pylint: disable=E0606
|
|
337
416
|
|
|
338
|
-
def __get_image_uri(self,relative_path):
|
|
339
|
-
"""
|
|
340
|
-
Get the absolute URI for an image in the assets folder.
|
|
341
|
-
:param relative_path: The relative path to the image (e.g., 'assets/imgs/icon.png').
|
|
342
|
-
:return: Absolute URI java Object (e.g., 'file:///path/to/file.png').
|
|
343
|
-
"""
|
|
344
|
-
|
|
345
|
-
output_path = os.path.join(app_storage_path(),'app', relative_path) # pylint: disable=possibly-used-before-assignment
|
|
346
|
-
# print(output_path) # /data/user/0/(package.domain+package.name)/files/app/assets/imgs/icon.png | pylint: disable=:line-too-long
|
|
347
|
-
|
|
348
|
-
if not os.path.exists(output_path):
|
|
349
|
-
# TODO Use images From Any where even Web
|
|
350
|
-
raise FileNotFoundError(f"Image not found at path: {output_path}, (Can Only Use Images in App Path)")
|
|
351
|
-
Uri = autoclass('android.net.Uri')
|
|
352
|
-
return Uri.parse(f"file://{output_path}")
|
|
353
|
-
def __getBitmap(self,img_path):
|
|
354
|
-
return BitmapFactory.decodeStream(context.getContentResolver().openInputStream(img_path))
|
|
355
|
-
|
|
356
417
|
def __generate_channel_id(self,channel_name: str) -> str:
|
|
357
418
|
"""
|
|
358
419
|
Generate a readable and consistent channel ID from a channel name.
|
|
@@ -451,6 +512,7 @@ class Notification:
|
|
|
451
512
|
class NotificationHandler:
|
|
452
513
|
"""For Notification Operations """
|
|
453
514
|
__identifer = None
|
|
515
|
+
__bound = False
|
|
454
516
|
|
|
455
517
|
@classmethod
|
|
456
518
|
def getIdentifer(cls):
|
|
@@ -516,9 +578,13 @@ class NotificationHandler:
|
|
|
516
578
|
"""This Creates a Listener for All Notification Clicks and Functions"""
|
|
517
579
|
if not cls.is_on_android():
|
|
518
580
|
return "Not on Android"
|
|
519
|
-
#
|
|
581
|
+
#TODO keep trying BroadcastReceiver
|
|
582
|
+
if cls.__bound:
|
|
583
|
+
print("bounding done already ")
|
|
584
|
+
return True
|
|
520
585
|
try:
|
|
521
586
|
activity.bind(on_new_intent=cls.__notificationHandler)
|
|
587
|
+
cls.__bound = True
|
|
522
588
|
return True
|
|
523
589
|
except Exception as e: # pylint: disable=broad-exception-caught
|
|
524
590
|
print('Failed to bin notitfications listener',e)
|
|
@@ -541,3 +607,5 @@ class NotificationHandler:
|
|
|
541
607
|
def is_on_android():
|
|
542
608
|
"""Utility to check if the app is running on Android."""
|
|
543
609
|
return ON_ANDROID
|
|
610
|
+
|
|
611
|
+
NotificationHandler.bindNotifyListener()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: android-notify
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.51.1
|
|
4
4
|
Summary: A Python package that simpilfies creating Android notifications in Kivy apps.
|
|
5
5
|
Home-page: https://github.com/fector101/android-notify
|
|
6
6
|
Author: Fabian
|
|
@@ -47,7 +47,7 @@ Dynamic: summary
|
|
|
47
47
|
|
|
48
48
|
- Also Compatible with Android 8.0+.
|
|
49
49
|
- Supports including images in notifications.
|
|
50
|
-
- All Notifications can take Functions (version 1.50+) [functions
|
|
50
|
+
- All Notifications can take Functions (version 1.50+) [functions section](#functions).
|
|
51
51
|
- Support for multiple notification styles:
|
|
52
52
|
- [Simple](#basic-usage)
|
|
53
53
|
- [Progress](#progress-bar-notification)
|
|
@@ -88,6 +88,7 @@ android.permissions = POST_NOTIFICATIONS
|
|
|
88
88
|
# Required dependencies (write exactly as shown, no quotation marks)
|
|
89
89
|
android.gradle_dependencies = androidx.core:core:1.6.0, androidx.core:core-ktx:1.15.0
|
|
90
90
|
android.enable_androidx = True
|
|
91
|
+
android.api = 35
|
|
91
92
|
```
|
|
92
93
|
|
|
93
94
|
---
|
|
@@ -142,7 +143,14 @@ Clock.schedule_once(lambda dt: notification.updateProgressBar(30, "30% downloade
|
|
|
142
143
|
**Sample Image:**
|
|
143
144
|

|
|
144
145
|
|
|
145
|
-
####
|
|
146
|
+
#### Images
|
|
147
|
+
|
|
148
|
+
##### Notification with an Image (Big Picture Style)
|
|
149
|
+
|
|
150
|
+
> [!NOTE]
|
|
151
|
+
> Online Images should start with `http://` or `https://`
|
|
152
|
+
> And request for permission, `android.permissions = INTERNET`
|
|
153
|
+
> No additionally permissions needed for images in App folder
|
|
146
154
|
|
|
147
155
|
```python
|
|
148
156
|
# Image notification
|
|
@@ -159,36 +167,36 @@ notification.send()
|
|
|
159
167
|
**Sample Image:**
|
|
160
168
|

|
|
161
169
|
|
|
162
|
-
|
|
170
|
+
##### Notification with an Image (Large Icon Style)
|
|
163
171
|
|
|
164
172
|
```python
|
|
165
|
-
# Send a notification with inbox style
|
|
166
173
|
notification = Notification(
|
|
167
|
-
title=
|
|
168
|
-
message=
|
|
169
|
-
style=
|
|
174
|
+
title="FabianDev_",
|
|
175
|
+
message="A twitter about some programming stuff",
|
|
176
|
+
style="large_icon",
|
|
177
|
+
large_icon_path="assets/imgs/profile.png"
|
|
170
178
|
)
|
|
171
|
-
notification.send()
|
|
172
179
|
|
|
173
180
|
```
|
|
174
181
|
|
|
175
|
-
**Sample Image:**
|
|
176
|
-

|
|
177
184
|
|
|
178
|
-
#### Notification
|
|
185
|
+
#### Inbox Notification Style
|
|
179
186
|
|
|
180
187
|
```python
|
|
188
|
+
# Send a notification with inbox style
|
|
181
189
|
notification = Notification(
|
|
182
|
-
title=
|
|
183
|
-
message=
|
|
184
|
-
style=
|
|
185
|
-
large_icon_path="assets/imgs/profile.png"
|
|
190
|
+
title='Inbox Notification',
|
|
191
|
+
message='Line 1\nLine 2\nLine 3',
|
|
192
|
+
style='inbox'
|
|
186
193
|
)
|
|
194
|
+
notification.send()
|
|
187
195
|
|
|
188
196
|
```
|
|
189
197
|
|
|
190
|
-
**Sample Image:**
|
|
191
|
-

|
|
192
200
|
|
|
193
201
|
#### Notification with Buttons
|
|
194
202
|
|
|
@@ -212,16 +220,19 @@ notification.send()
|
|
|
212
220
|
**Sample Image:**
|
|
213
221
|

|
|
214
222
|
|
|
215
|
-
#### Big text notification
|
|
223
|
+
#### Big text notification
|
|
216
224
|
|
|
217
225
|
```python
|
|
218
226
|
notification = Notification(
|
|
219
227
|
title="Article",
|
|
220
|
-
|
|
228
|
+
subject="Histroy of Loerm Ipsuim",
|
|
229
|
+
message="Lorem Ipsum is simply dummy text of the printing and ...",
|
|
221
230
|
style="big_text"
|
|
222
231
|
)
|
|
223
232
|
```
|
|
224
233
|
|
|
234
|
+

|
|
235
|
+
|
|
225
236
|
## Advanced Features
|
|
226
237
|
|
|
227
238
|
### Updating Notifications
|
|
@@ -281,19 +292,13 @@ notification.send(silent=True)
|
|
|
281
292
|
|
|
282
293
|
## Functions
|
|
283
294
|
|
|
284
|
-
### NotificationHandler - To Attach Listener
|
|
285
|
-
|
|
286
|
-
Add this to your main.py App Class so it runs Once, In later Versions It'll be Attached Automatical
|
|
287
|
-
|
|
288
295
|
```python
|
|
289
296
|
from kivymd.app import MDApp
|
|
290
|
-
from android_notify import Notification
|
|
297
|
+
from android_notify import Notification
|
|
291
298
|
|
|
292
299
|
class Myapp(MDApp):
|
|
293
300
|
|
|
294
301
|
def on_start(self):
|
|
295
|
-
# Is called Once when app is Starts up
|
|
296
|
-
NotificationHandler.bindNotifyListener() # if successfull returns True
|
|
297
302
|
Notification(title="Hello", message="This is a basic notification.",callback=self.doSomething).send()
|
|
298
303
|
|
|
299
304
|
def doSomething(self):
|
|
@@ -318,8 +323,6 @@ class Myapp(MDApp):
|
|
|
318
323
|
notify1 = Notification(title="Change Colour", message="Click to change App Colour", identifer='change_app_color')
|
|
319
324
|
notify1.send()
|
|
320
325
|
|
|
321
|
-
NotificationHandler.bindNotifyListener()
|
|
322
|
-
|
|
323
326
|
def on_resume(self):
|
|
324
327
|
# Is called everytime app is reopened
|
|
325
328
|
notify_identifer = NotificationHandler.getIdentifer()
|
|
@@ -331,22 +334,8 @@ class Myapp(MDApp):
|
|
|
331
334
|
pass
|
|
332
335
|
```
|
|
333
336
|
|
|
334
|
-
|
|
335
|
-
|
|
336
337
|
### Assist
|
|
337
338
|
|
|
338
|
-
- How to Copy image to app folder
|
|
339
|
-
|
|
340
|
-
```python
|
|
341
|
-
import shutil,os # These modules come packaged with python
|
|
342
|
-
from android.storage import app_storage_path # type: ignore -- This works only on android
|
|
343
|
-
|
|
344
|
-
app_path = os.path.join(app_storage_path(),'app')
|
|
345
|
-
image_path= "/storage/emulated/0/Download/profile.png"
|
|
346
|
-
|
|
347
|
-
shutil.copy(image_path, os.path.join(app_path, "profile.png"))
|
|
348
|
-
```
|
|
349
|
-
|
|
350
339
|
- Avoiding Human Error when using different notification styles
|
|
351
340
|
|
|
352
341
|
```python
|
|
@@ -375,9 +364,8 @@ notification.send()
|
|
|
375
364
|
|
|
376
365
|
## Image Requirements
|
|
377
366
|
|
|
378
|
-
- Images
|
|
379
|
-
-
|
|
380
|
-
- Example: `assets/imgs/icon.png`
|
|
367
|
+
- Online Images should start with `http://` or `https://`
|
|
368
|
+
- Local Images must be located within your app's folder
|
|
381
369
|
|
|
382
370
|
## Error Handling
|
|
383
371
|
|
|
@@ -385,22 +373,20 @@ The library validates arguments and provides helpful error messages:
|
|
|
385
373
|
|
|
386
374
|
- Invalid style names will suggest the closest matching style
|
|
387
375
|
- Invalid arguments will list all valid options
|
|
388
|
-
- Missing image files will
|
|
376
|
+
- Missing image files will list all files in App Directory
|
|
389
377
|
|
|
390
|
-
##
|
|
378
|
+
## Limitation
|
|
391
379
|
|
|
392
380
|
1. Only works on Android devices
|
|
393
|
-
2. Images must be within the app's storage path
|
|
394
|
-
3. Channel names are limited to 40 characters
|
|
395
|
-
4. Channel IDs are limited to 50 characters
|
|
396
381
|
|
|
397
382
|
## Best Practices
|
|
398
383
|
|
|
399
384
|
1. Always handle permissions appropriately
|
|
400
|
-
2.
|
|
401
|
-
3.
|
|
402
|
-
4.
|
|
403
|
-
5.
|
|
385
|
+
2. use `NotificationStyles` to set `style`, use `style=NotificationStyles.LARGE_ICON` instead of `style="large_icon"`
|
|
386
|
+
3. Use meaningful channel names for organization
|
|
387
|
+
4. Keep progress bar updates reasonable (don't update too frequently)
|
|
388
|
+
5. Test notifications on different Android versions
|
|
389
|
+
6. Consider using silent notifications for frequent updates
|
|
404
390
|
|
|
405
391
|
## Debugging Tips
|
|
406
392
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
android_notify/__init__.py,sha256=lcLjyfegXgU7cyGhfSphAOBipXwemrVkdYy3mcF6X5Y,172
|
|
2
|
+
android_notify/__main__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
android_notify/core.py,sha256=B3gOgbLGGI6tz-Q_T2wmk74oggOSDX0Qz4lqj00vaFo,6114
|
|
4
|
+
android_notify/styles.py,sha256=3olKruhAbTrk5OzuhDnk_Pgpv8XYk8dWFmr48Q9rQVk,352
|
|
5
|
+
android_notify/sword.py,sha256=mmQM5G9lOGYGKuVCXd_t2iFeh_MHXDrWvJJlv1kU9e0,25840
|
|
6
|
+
android_notify-1.51.1.dist-info/METADATA,sha256=VvBJSj8BMS9et-3viP7H5W9E6XXXTNJxRNuObw9ubx0,12737
|
|
7
|
+
android_notify-1.51.1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
8
|
+
android_notify-1.51.1.dist-info/top_level.txt,sha256=IR1ONMrRSRINZpWn2X0dL5gbWwWINsK7PW8Jy2p4fU8,15
|
|
9
|
+
android_notify-1.51.1.dist-info/RECORD,,
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
android_notify/__init__.py,sha256=lcLjyfegXgU7cyGhfSphAOBipXwemrVkdYy3mcF6X5Y,172
|
|
2
|
-
android_notify/__main__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
android_notify/core.py,sha256=B3gOgbLGGI6tz-Q_T2wmk74oggOSDX0Qz4lqj00vaFo,6114
|
|
4
|
-
android_notify/styles.py,sha256=I2p31qStg9DaML9U4nXRvdpGzpppK6RS-qlDKuOv_Tk,328
|
|
5
|
-
android_notify/sword.py,sha256=2T9JlFRqTLDDMtqFWrn6qvYeCQsO6Aky2UlAWuIYYVY,23172
|
|
6
|
-
android_notify-1.50.1.dist-info/METADATA,sha256=RLYXmIWoV6O5-DRLqvPVJ6NqMbmsnD4CZtBmo18dZGA,13165
|
|
7
|
-
android_notify-1.50.1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
8
|
-
android_notify-1.50.1.dist-info/top_level.txt,sha256=IR1ONMrRSRINZpWn2X0dL5gbWwWINsK7PW8Jy2p4fU8,15
|
|
9
|
-
android_notify-1.50.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|