android-notify 1.41__tar.gz → 1.50.1__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.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: android-notify
3
- Version: 1.41
3
+ Version: 1.50.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,6 +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 docs](#functions).
50
51
  - Support for multiple notification styles:
51
52
  - [Simple](#basic-usage)
52
53
  - [Progress](#progress-bar-notification)
@@ -278,6 +279,60 @@ notification = Notification(title="Silent Update")
278
279
  notification.send(silent=True)
279
280
  ```
280
281
 
282
+ ## Functions
283
+
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
+ ```python
289
+ from kivymd.app import MDApp
290
+ from android_notify import Notification, NotificationHandler
291
+
292
+ class Myapp(MDApp):
293
+
294
+ def on_start(self):
295
+ # Is called Once when app is Starts up
296
+ NotificationHandler.bindNotifyListener() # if successfull returns True
297
+ Notification(title="Hello", message="This is a basic notification.",callback=self.doSomething).send()
298
+
299
+ def doSomething(self):
300
+ print("print in Debug Console")
301
+ ```
302
+
303
+ ### Get Which Notification was used to Open App - identifer (str)
304
+
305
+ If you just want to get the Exact Notification Clicked to Open App, you can use NotificationHandler to get unique identifer
306
+
307
+ ```python
308
+ from kivymd.app import MDApp
309
+ from android_notify import Notification, NotificationHandler
310
+
311
+ class Myapp(MDApp):
312
+
313
+ def on_start(self):
314
+
315
+ notify = Notification(title="Change Page", message="Click to change App page.", identifer='change_app_page')
316
+ notify.send()
317
+
318
+ notify1 = Notification(title="Change Colour", message="Click to change App Colour", identifer='change_app_color')
319
+ notify1.send()
320
+
321
+ NotificationHandler.bindNotifyListener()
322
+
323
+ def on_resume(self):
324
+ # Is called everytime app is reopened
325
+ notify_identifer = NotificationHandler.getIdentifer()
326
+ if notify_identifer == 'change_app_page':
327
+ # Code to change Screen
328
+ pass
329
+ elif notify_identifer == 'change_app_color':
330
+ # Code to change Screen Color
331
+ pass
332
+ ```
333
+
334
+
335
+
281
336
  ### Assist
282
337
 
283
338
  - How to Copy image to app folder
@@ -11,6 +11,7 @@
11
11
 
12
12
  - Also Compatible with Android 8.0+.
13
13
  - Supports including images in notifications.
14
+ - All Notifications can take Functions (version 1.50+) [functions docs](#functions).
14
15
  - Support for multiple notification styles:
15
16
  - [Simple](#basic-usage)
16
17
  - [Progress](#progress-bar-notification)
@@ -242,6 +243,60 @@ notification = Notification(title="Silent Update")
242
243
  notification.send(silent=True)
243
244
  ```
244
245
 
246
+ ## Functions
247
+
248
+ ### NotificationHandler - To Attach Listener
249
+
250
+ Add this to your main.py App Class so it runs Once, In later Versions It'll be Attached Automatical
251
+
252
+ ```python
253
+ from kivymd.app import MDApp
254
+ from android_notify import Notification, NotificationHandler
255
+
256
+ class Myapp(MDApp):
257
+
258
+ def on_start(self):
259
+ # Is called Once when app is Starts up
260
+ NotificationHandler.bindNotifyListener() # if successfull returns True
261
+ Notification(title="Hello", message="This is a basic notification.",callback=self.doSomething).send()
262
+
263
+ def doSomething(self):
264
+ print("print in Debug Console")
265
+ ```
266
+
267
+ ### Get Which Notification was used to Open App - identifer (str)
268
+
269
+ If you just want to get the Exact Notification Clicked to Open App, you can use NotificationHandler to get unique identifer
270
+
271
+ ```python
272
+ from kivymd.app import MDApp
273
+ from android_notify import Notification, NotificationHandler
274
+
275
+ class Myapp(MDApp):
276
+
277
+ def on_start(self):
278
+
279
+ notify = Notification(title="Change Page", message="Click to change App page.", identifer='change_app_page')
280
+ notify.send()
281
+
282
+ notify1 = Notification(title="Change Colour", message="Click to change App Colour", identifer='change_app_color')
283
+ notify1.send()
284
+
285
+ NotificationHandler.bindNotifyListener()
286
+
287
+ def on_resume(self):
288
+ # Is called everytime app is reopened
289
+ notify_identifer = NotificationHandler.getIdentifer()
290
+ if notify_identifer == 'change_app_page':
291
+ # Code to change Screen
292
+ pass
293
+ elif notify_identifer == 'change_app_color':
294
+ # Code to change Screen Color
295
+ pass
296
+ ```
297
+
298
+
299
+
245
300
  ### Assist
246
301
 
247
302
  - How to Copy image to app folder
@@ -0,0 +1,4 @@
1
+ """"For Easier Imports For Public Classes"""
2
+ from .core import send_notification
3
+ from .styles import NotificationStyles
4
+ from .sword import Notification,NotificationHandler
@@ -1,6 +1,6 @@
1
1
  """This Module Contain Class for creating Notification With Java"""
2
2
  import difflib
3
- import random
3
+ import traceback
4
4
  import os
5
5
  import re
6
6
 
@@ -9,7 +9,11 @@ ON_ANDROID = False
9
9
 
10
10
  try:
11
11
  from jnius import autoclass,cast # Needs Java to be installed pylint: disable=W0611, C0114
12
+ from android import activity # pylint: disable=import-error
13
+ from android.config import ACTIVITY_CLASS_NAME # pylint: disable=import-error
14
+
12
15
  # Get the required Java classes
16
+ Bundle = autoclass('android.os.Bundle')
13
17
  PythonActivity = autoclass('org.kivy.android.PythonActivity')
14
18
  String = autoclass('java.lang.String')
15
19
  Intent = autoclass('android.content.Intent')
@@ -56,18 +60,21 @@ class Notification:
56
60
  :param style: Style of the notification
57
61
  ('simple', 'progress', 'big_text', 'inbox', 'big_picture', 'large_icon', 'both_imgs').
58
62
  both_imgs == using lager icon and big picture
59
- :param big_picture_path: Path to the image resource.
60
- :param large_icon_path: Path to the image resource.
63
+ :param big_picture_path: Relative Path to the image resource.
64
+ :param large_icon_path: Relative Path to the image resource.
65
+ :param callback: Function for notification Click.
61
66
  ---
62
67
  (Advance Options)
63
- :param channel_name: Defaults to "Default Channel"
64
- :param channel_id: Defaults to "default_channel"
68
+ :param channel_name: - str Defaults to "Default Channel"
69
+ :param channel_id: - str Defaults to "default_channel"
65
70
  ---
66
71
  (Options during Dev On PC)
67
- :param logs: Defaults to True
72
+ :param logs: - Bool Defaults to True
68
73
  """
69
- notification_ids=[]
70
- button_ids=[]
74
+ notification_ids=[0]
75
+ button_ids=[0]
76
+ btns_box={}
77
+ main_functions={}
71
78
  style_values=[
72
79
  '','simple',
73
80
  'progress','big_text',
@@ -86,6 +93,8 @@ class Notification:
86
93
  'channel_name':'Default Channel',
87
94
  'channel_id':'default_channel',
88
95
  'logs':True,
96
+ "identifer": '',
97
+ 'callback': None
89
98
  }
90
99
  # During Development (When running on PC)
91
100
  logs=not ON_ANDROID
@@ -99,15 +108,23 @@ class Notification:
99
108
  self.big_picture_path=''
100
109
  self.progress_current_value=0
101
110
  self.progress_max_value=0
111
+
112
+ # For Nofitication Functions
113
+ self.identifer=''
114
+ self.callback = None
115
+
102
116
  # Advance Options
103
117
  self.channel_name='Default Channel'
104
118
  self.channel_id='default_channel'
105
119
  self.silent=False
120
+
106
121
  # During Dev on PC
107
122
  self.logs=self.logs
123
+
108
124
  # Private (Don't Touch)
109
125
  self.__id = self.__getUniqueID()
110
126
  self.__setArgs(kwargs)
127
+
111
128
  if not ON_ANDROID:
112
129
  return
113
130
  # TODO make send method wait for __asks_permission_if_needed method
@@ -139,7 +156,7 @@ class Notification:
139
156
  """message defaults to last message"""
140
157
  if not ON_ANDROID:
141
158
  return
142
-
159
+
143
160
  if self.logs:
144
161
  print(f'Progress Bar Update value: {current_value}')
145
162
  self.__builder.setProgress(self.progress_max_value, current_value, False)
@@ -203,7 +220,11 @@ class Notification:
203
220
  checkInReference([inputted_kwargs['style']],self.style_values,'values')
204
221
 
205
222
  def __setArgs(self,options_dict:dict):
223
+ non_string_keys=['progress_max_value','progress_current_value','callback','logs']
224
+
206
225
  for key,value in options_dict.items():
226
+ if key not in non_string_keys: # Fixing Types
227
+ value = str(value)
207
228
  if key == 'channel_name' and value.strip():
208
229
  setattr(self,key, value[:40])
209
230
  elif key == 'channel_id' and value.strip(): # If user input's a channel id (i format properly)
@@ -234,8 +255,8 @@ class Notification:
234
255
 
235
256
  # Build the notification
236
257
  # self.__builder = NotificationCompatBuilder(context, self.channel_id)# pylint: disable=E0606
237
- self.__builder.setContentTitle(self.title)
238
- self.__builder.setContentText(self.message)
258
+ self.__builder.setContentTitle(str(self.title))
259
+ self.__builder.setContentText(str(self.message))
239
260
  self.__builder.setSmallIcon(context.getApplicationInfo().icon)
240
261
  self.__builder.setDefaults(NotificationCompat.DEFAULT_ALL) # pylint: disable=E0606
241
262
  self.__builder.setPriority(NotificationCompat.PRIORITY_DEFAULT if self.silent else NotificationCompat.PRIORITY_HIGH)
@@ -283,7 +304,7 @@ class Notification:
283
304
  big_pic_bitmap = self.__getBitmap(big_pic_javapath)
284
305
  big_picture_style = NotificationCompatBigPictureStyle().bigPicture(big_pic_bitmap)
285
306
  self.__builder.setStyle(big_picture_style)
286
- elif large_icon_javapath:
307
+ if large_icon_javapath:
287
308
  large_icon_bitmap = self.__getBitmap(large_icon_javapath)
288
309
  self.__builder.setLargeIcon(large_icon_bitmap)
289
310
  elif self.style == 'progress':
@@ -298,10 +319,7 @@ class Notification:
298
319
  # return self.__builder
299
320
 
300
321
  def __getUniqueID(self):
301
- reasonable_amount_of_notifications=101
302
- notification_id = random.randint(1, reasonable_amount_of_notifications)
303
- while notification_id in self.notification_ids:
304
- notification_id = random.randint(1, reasonable_amount_of_notifications)
322
+ notification_id = self.notification_ids[-1] + 1
305
323
  self.notification_ids.append(notification_id)
306
324
  return notification_id
307
325
 
@@ -352,9 +370,15 @@ class Notification:
352
370
  # Remove leading/trailing underscores
353
371
  channel_id = channel_id.strip('_')
354
372
  return channel_id[:50]
373
+
355
374
  def __addIntentToOpenApp(self):
356
375
  intent = Intent(context, PythonActivity)
357
- intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP)
376
+ action = str(self.identifer) or f"ACTION_{self.__id}"
377
+ intent.setAction(action)
378
+ self.__addDataToIntent(intent)
379
+ self.main_functions[action]=self.callback
380
+ intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
381
+
358
382
  pending_intent = PendingIntent.getActivity(
359
383
  context, 0,
360
384
  intent, PendingIntent.FLAG_IMMUTABLE if BuildVersion.SDK_INT >= 31 else PendingIntent.FLAG_UPDATE_CURRENT
@@ -362,13 +386,17 @@ class Notification:
362
386
  self.__builder.setContentIntent(pending_intent)
363
387
  self.__builder.setAutoCancel(True)
364
388
 
389
+ def __addDataToIntent(self,intent):
390
+ """Persit Some data to notification object for later use"""
391
+ bundle = Bundle()
392
+ bundle.putString("title", self.title or 'Title Placeholder')
393
+ bundle.putInt("notify_id", self.__id)
394
+ intent.putExtras(bundle)
395
+
365
396
  def __getIDForButton(self):
366
- reasonable_amount_of_notifications=101
367
- btn_id = random.randint(1, reasonable_amount_of_notifications)
368
- while btn_id in self.button_ids:
369
- btn_id = random.randint(1, reasonable_amount_of_notifications)
397
+ btn_id = self.button_ids[-1] + 1
370
398
  self.button_ids.append(btn_id)
371
- return str(btn_id)
399
+ return btn_id
372
400
 
373
401
  def addButton(self, text:str,on_release):
374
402
  """For adding action buttons
@@ -376,21 +404,40 @@ class Notification:
376
404
  Args:
377
405
  text (str): Text For Button
378
406
  """
407
+ if self.logs:
408
+ print('Added Button: ', text)
409
+
379
410
  if not ON_ANDROID:
380
411
  return
381
412
 
382
- if self.logs:
383
- print('Added Button: '+text)
413
+ btn_id= self.__getIDForButton()
414
+ action = f"BTN_ACTION_{btn_id}"
415
+
384
416
  action_intent = Intent(context, PythonActivity)
385
- action_intent.setAction("ACTION "+ self.__getIDForButton())
417
+ action_intent.setAction(action)
418
+ action_intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
419
+ bundle = Bundle()
420
+ bundle.putString("title", self.title or 'Title Placeholder')
421
+ bundle.putInt("key_int", 123)
422
+ action_intent.putExtras(bundle)
423
+ action_intent.putExtra("button_id", btn_id)
424
+
425
+ self.btns_box[action] = on_release
426
+ # action_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP)
427
+
428
+ if self.logs:
429
+ print('Button id: ',btn_id)
386
430
  pending_action_intent = PendingIntent.getActivity(
387
431
  context,
388
432
  0,
389
433
  action_intent,
390
- PendingIntent.FLAG_IMMUTABLE
434
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
391
435
  )
392
436
  # Convert text to CharSequence
393
437
  action_text = cast('java.lang.CharSequence', String(text))
438
+
439
+
440
+
394
441
  # Add action with proper types
395
442
  self.__builder.addAction(
396
443
  int(context.getApplicationInfo().icon), # Cast icon to int
@@ -399,38 +446,98 @@ class Notification:
399
446
  )
400
447
  # Set content intent for notification tap
401
448
  self.__builder.setContentIntent(pending_action_intent)
402
- # on_release()
403
-
404
- # def buttonsListener():
405
- # """Handle notification button clicks"""
406
- # try:
407
- # intent = context.getIntent()
408
- # action = context.getAction()
409
- # print("The Action --> ",action)
410
- # intent.setAction("")
411
- # context.setIntent(intent)
412
- # except Exception as e:
413
- # print("Catching Intents Error ",e)
414
-
415
- # notify=Notification(titl='My Title',channel_name='Go')#,logs=False)
416
- # # notify.channel_name='Downloads'
417
- # notify.message="Blah"
418
- # notify.send()
419
- # notify.updateTitle('New Title')
420
- # notify.updateMessage('New Message')
421
- # notify.send(True)
422
- # except Exception as e:
423
- # print(e)
424
-
425
- # notify=Notification(title='My Title1')
426
- # # notify.updateTitle('New Title1')
427
- # notify.send()
428
-
429
-
430
- # Notification.logs=False # Add in Readme
431
- # notify=Notification(style='large_icon',title='My Title',channel_name='Some thing about a thing ')#,logs=False)
432
- # # notify.channel_name='Downloads'
433
- # notify.message="Blah"
434
- # notify.send()
435
- # notify.updateTitle('New Title')
436
- # notify.updateMessage('New Message')
449
+
450
+
451
+ class NotificationHandler:
452
+ """For Notification Operations """
453
+ __identifer = None
454
+
455
+ @classmethod
456
+ def getIdentifer(cls):
457
+ """Returns identifer for Clicked Notification."""
458
+ if not cls.is_on_android():
459
+ return "Not on Android"
460
+
461
+ saved_intent = cls.__identifer
462
+ if not saved_intent or (isinstance(saved_intent, str) and saved_intent.startswith("android.intent")):
463
+ # All other notifications are not None after First notification opens app
464
+ # NOTE these notifications are also from Last time app was opened and they Still Give Value after first one opens App
465
+ # TODO Find a way to get intent when App if Swiped From recents
466
+ __PythonActivity = autoclass(ACTIVITY_CLASS_NAME)
467
+ __mactivity = __PythonActivity.mActivity
468
+ __context = cast('android.content.Context', __mactivity)
469
+ __Intent = autoclass('android.content.Intent')
470
+ __intent = __Intent(__context, __PythonActivity)
471
+ action = __intent.getAction()
472
+ print('Start up Intent ----', action)
473
+ print('start Up Title --->',__intent.getStringExtra("title"))
474
+
475
+ return saved_intent
476
+
477
+ @classmethod
478
+ def __notificationHandler(cls,intent):
479
+ """Calls Function Attached to notification on click.
480
+ Don't Call this function manual, it's Already Attach to Notification.
481
+
482
+ Returns:
483
+ str: The Identiter of Nofication that was clicked.
484
+ """
485
+ if not cls.is_on_android():
486
+ return "Not on Android"
487
+ buttons_object=Notification.btns_box
488
+ notifty_functions=Notification.main_functions
489
+ if DEV:
490
+ print("notifty_functions ",notifty_functions)
491
+ print("buttons_object", buttons_object)
492
+ action = None
493
+ try:
494
+ action = intent.getAction()
495
+ cls.__identifer = action
496
+
497
+ print("The Action --> ",action)
498
+ if action == "android.intent.action.MAIN": # Not Open From Notification
499
+ return 'Not notification'
500
+
501
+ print(intent.getStringExtra("title"))
502
+ try:
503
+ if action in notifty_functions and notifty_functions[action]:
504
+ notifty_functions[action]()
505
+ elif action in buttons_object:
506
+ buttons_object[action]()
507
+ except Exception as e: # pylint: disable=broad-exception-caught
508
+ print('Failed to run function: ', traceback.format_exc())
509
+ print("Error Type ",e)
510
+ except Exception as e: # pylint: disable=broad-exception-caught
511
+ print('Notify Hanlder Failed ',e)
512
+ return action
513
+
514
+ @classmethod
515
+ def bindNotifyListener(cls):
516
+ """This Creates a Listener for All Notification Clicks and Functions"""
517
+ if not cls.is_on_android():
518
+ return "Not on Android"
519
+ #Beta TODO Automatic bind when Notification object is called the first time use keep trying BroadcastReceiver
520
+ try:
521
+ activity.bind(on_new_intent=cls.__notificationHandler)
522
+ return True
523
+ except Exception as e: # pylint: disable=broad-exception-caught
524
+ print('Failed to bin notitfications listener',e)
525
+ return False
526
+ @classmethod
527
+ def unbindNotifyListener(cls):
528
+ """Removes Listener for Notifications Click"""
529
+ if not cls.is_on_android():
530
+ return "Not on Android"
531
+
532
+ #Beta TODO use BroadcastReceiver
533
+ try:
534
+ activity.unbind(on_new_intent=cls.__notificationHandler)
535
+ return True
536
+ except Exception as e: # pylint: disable=broad-exception-caught
537
+ print("Failed to unbind notifications listener: ",e)
538
+ return False
539
+
540
+ @staticmethod
541
+ def is_on_android():
542
+ """Utility to check if the app is running on Android."""
543
+ return ON_ANDROID
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: android-notify
3
- Version: 1.41
3
+ Version: 1.50.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,6 +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 docs](#functions).
50
51
  - Support for multiple notification styles:
51
52
  - [Simple](#basic-usage)
52
53
  - [Progress](#progress-bar-notification)
@@ -278,6 +279,60 @@ notification = Notification(title="Silent Update")
278
279
  notification.send(silent=True)
279
280
  ```
280
281
 
282
+ ## Functions
283
+
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
+ ```python
289
+ from kivymd.app import MDApp
290
+ from android_notify import Notification, NotificationHandler
291
+
292
+ class Myapp(MDApp):
293
+
294
+ def on_start(self):
295
+ # Is called Once when app is Starts up
296
+ NotificationHandler.bindNotifyListener() # if successfull returns True
297
+ Notification(title="Hello", message="This is a basic notification.",callback=self.doSomething).send()
298
+
299
+ def doSomething(self):
300
+ print("print in Debug Console")
301
+ ```
302
+
303
+ ### Get Which Notification was used to Open App - identifer (str)
304
+
305
+ If you just want to get the Exact Notification Clicked to Open App, you can use NotificationHandler to get unique identifer
306
+
307
+ ```python
308
+ from kivymd.app import MDApp
309
+ from android_notify import Notification, NotificationHandler
310
+
311
+ class Myapp(MDApp):
312
+
313
+ def on_start(self):
314
+
315
+ notify = Notification(title="Change Page", message="Click to change App page.", identifer='change_app_page')
316
+ notify.send()
317
+
318
+ notify1 = Notification(title="Change Colour", message="Click to change App Colour", identifer='change_app_color')
319
+ notify1.send()
320
+
321
+ NotificationHandler.bindNotifyListener()
322
+
323
+ def on_resume(self):
324
+ # Is called everytime app is reopened
325
+ notify_identifer = NotificationHandler.getIdentifer()
326
+ if notify_identifer == 'change_app_page':
327
+ # Code to change Screen
328
+ pass
329
+ elif notify_identifer == 'change_app_color':
330
+ # Code to change Screen Color
331
+ pass
332
+ ```
333
+
334
+
335
+
281
336
  ### Assist
282
337
 
283
338
  - How to Copy image to app folder
@@ -1,4 +1,4 @@
1
- """ For Packing"""
1
+ """ For Packing """
2
2
  from setuptools import setup, find_packages
3
3
 
4
4
  with open("README.md", "r", encoding="utf-8") as readme_data:
@@ -6,7 +6,7 @@ with open("README.md", "r", encoding="utf-8") as readme_data:
6
6
 
7
7
  setup(
8
8
  name="android-notify",
9
- version="1.41",
9
+ version="1.50.1",
10
10
  author="Fabian",
11
11
  author_email='fector101@yahoo.com',
12
12
  description="A Python package that simpilfies creating Android notifications in Kivy apps.",
@@ -1,3 +0,0 @@
1
- from .core import send_notification
2
- from .styles import NotificationStyles
3
- from .sword import Notification
File without changes