android-notify 1.59.4__py3-none-any.whl → 1.60.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.
@@ -1,4 +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
+ """"For Easier Imports For Public Classes"""
2
+ from .core import send_notification
3
+ from .styles import NotificationStyles
4
+ from .sword import Notification,NotificationHandler
@@ -0,0 +1,24 @@
1
+ import argparse
2
+ from .config import __version__
3
+
4
+ def print_version():
5
+ text = f"android_notify: v{__version__}"
6
+ border = '+'+'-'*(len(text) + 2)+'+'
7
+ print(border)
8
+ print(f'| {text} |')
9
+ print(border)
10
+
11
+ def main():
12
+ parser = argparse.ArgumentParser(description="Android Notify CLI")
13
+ parser.add_argument('-v','--version', action='store_true', help="Show the version of android_notify")
14
+ args = parser.parse_args()
15
+
16
+ if args.version:
17
+ print_version()
18
+ # # Placeholder for the main functionality
19
+ # print("Android Notify CLI is running...")
20
+ # DEV: pip install -e ., when edit and test project locally
21
+
22
+
23
+ if __name__ == "__main__":
24
+ main()
@@ -1,91 +1,226 @@
1
- """For autocomplete Storing Reference to Available Methods"""
2
- from typing import Literal
3
- Importance = Literal['urgent','high','medium','low','none']
4
- """
5
- :argument urgent - Makes a sound and appears as a heads-up notification.
6
-
7
- :argument high - Makes a sound.
8
-
9
- :argument urgent - Makes no sound.
10
-
11
- :argument urgent - Makes no sound and doesn't appear in the status bar.
12
-
13
- :argument urgent - Makes no sound and doesn't in the status bar or shade.
14
- """
15
-
16
- # Idea for typing autocompletion and reference
17
- # class Bundle:
18
- # pass
19
- # class PythonActivity:
20
- # mActivity=''# Get the app's context
21
- # pass
22
- # class String(str):
23
- # pass
24
- # class Intent:
25
- # def __init__(self,context,activity):
26
- # pass
27
- # class PendingIntent:
28
- # FLAG_IMMUTABLE=''
29
- # FLAG_UPDATE_CURRENT=''
30
- # def getActivity(self,context,value,action_intent,pending_intent_type):
31
- # pass
32
- # class BitmapFactory:
33
- # def decodeStream(self,stream):
34
- # pass
35
- # class BuildVersion:
36
- # SDK_INT=0
37
- # class NotificationManager:
38
- # pass
39
- # class NotificationChannel:
40
- # def __init__(self,channel_id,channel_name,importance):
41
- # pass
42
- # def createNotificationChannel(self, channel):
43
- # pass
44
- #
45
- # def getNotificationChannel(self, channel_id):
46
- # pass
47
- # class IconCompat:
48
- # def createWithBitmap(self,bitmap):
49
- # pass
50
- #
51
- # class NotificationManagerCompat:
52
- # IMPORTANCE_DEFAULT=3
53
- # IMPORTANCE_HIGH=4
54
- #
55
- #
56
- # class NotificationCompat:
57
- # DEFAULT_ALL=3
58
- # PRIORITY_HIGH=4
59
- #
60
- # def __init__(self,context):
61
- # pass
62
- # def Builder(self,context,channel_id):
63
- # pass
64
- # class NotificationCompatBuilder:
65
- # def __init__(self,context,channel_id):
66
- # pass
67
- # def setContentTitle(self,title):
68
- # pass
69
- # def setContentText(self,text):
70
- # pass
71
- # def setSmallIcon(self,icon):
72
- # pass
73
- # def setLargeIcon(self,icon):
74
- # pass
75
- # def setAutoCancel(self,auto_cancel):
76
- # pass
77
- # def setPriority(self,priority):
78
- # pass
79
- # def setDefaults(self,defaults):
80
- # pass
81
- # def build(self):
82
- # pass
83
- # class NotificationCompatBigTextStyle:
84
- # pass
85
- # class NotificationCompatBigPictureStyle:
86
- # pass
87
- # class NotificationCompatInboxStyle:
88
- # pass
89
-
90
- #Now writing Knowledge from errors
91
- # notify.(int, Builder.build()) # must be int
1
+ """For autocomplete Storing Reference to Available Methods"""
2
+ from typing import Literal
3
+ Importance = Literal['urgent','high','medium','low','none']
4
+ """
5
+ :argument urgent - Makes a sound and appears as a heads-up notification.
6
+
7
+ :argument high - Makes a sound.
8
+
9
+ :argument urgent - Makes no sound.
10
+
11
+ :argument urgent - Makes no sound and doesn't appear in the status bar.
12
+
13
+ :argument urgent - Makes no sound and doesn't in the status bar or shade.
14
+ """
15
+
16
+
17
+ # For Dev
18
+ # Idea for typing autocompletion and reference
19
+ class Bundle:
20
+ def putString(self,key,value):
21
+ print(self,key,value)
22
+
23
+ def putInt(self,key,value):
24
+ print(self, key, value)
25
+
26
+ class String(str):
27
+ pass
28
+
29
+
30
+ class Intent:
31
+ def __init__(self,context,activity):
32
+ self.obj={}
33
+ pass
34
+
35
+ def setAction(self,action):
36
+ print(action)
37
+ return self
38
+
39
+ def setFlags(self,intent_flag):
40
+ print(intent_flag)
41
+ return self
42
+
43
+ def getAction(self):
44
+ return self
45
+
46
+ def getStringExtra(self,key):
47
+ return self
48
+
49
+ def putExtra(self,key,value):
50
+ self.obj[key] = value
51
+
52
+ def putExtras(self,bundle:Bundle):
53
+ self.obj['bundle'] = bundle
54
+
55
+ class PendingIntent:
56
+ FLAG_IMMUTABLE=''
57
+ FLAG_UPDATE_CURRENT=''
58
+
59
+ def getActivity(self,context,value,action_intent,pending_intent_type):
60
+ pass
61
+
62
+ class BitmapFactory:
63
+ def decodeStream(self,stream):
64
+ pass
65
+
66
+ class BuildVersion:
67
+ SDK_INT=0
68
+
69
+ class NotificationManager:
70
+ pass
71
+
72
+ class NotificationChannel:
73
+ def __init__(self,channel_id,channel_name,importance):
74
+ self.description = None
75
+ self.channel_id = None
76
+ self.channel = None
77
+ def createNotificationChannel(self, channel):
78
+ self.channel=channel
79
+
80
+ def getNotificationChannel(self, channel_id):
81
+ self.channel_id=channel_id
82
+ pass
83
+
84
+ def setDescription(self, description):
85
+ self.description=description
86
+
87
+ def getId(self):
88
+ return self.channel_id
89
+
90
+ class IconCompat:
91
+ def createWithBitmap(self,bitmap):
92
+ pass
93
+
94
+ class Color:
95
+ def __init__(self):
96
+ pass
97
+ def parseColor(self,color:str):
98
+ return self
99
+
100
+ class RemoteViews:
101
+ def __init__(self, package_name, small_layout_id):
102
+ pass
103
+ def createWithBitmap(self,bitmap):
104
+ pass
105
+ def setTextViewText(self,id, text):
106
+ pass
107
+ def setTextColor(self,id, color:Color):
108
+ pass
109
+
110
+ class NotificationManagerCompat:
111
+ IMPORTANCE_HIGH=4
112
+ IMPORTANCE_DEFAULT=3
113
+ IMPORTANCE_LOW=''
114
+ IMPORTANCE_MIN=''
115
+ IMPORTANCE_NONE=''
116
+
117
+ class NotificationCompat:
118
+ DEFAULT_ALL=3
119
+ PRIORITY_HIGH=4
120
+ PRIORITY_DEFAULT = ''
121
+ PRIORITY_LOW=''
122
+ PRIORITY_MIN=''
123
+
124
+ class MActions:
125
+ def clear(self):
126
+ """This Removes all buttons"""
127
+ print('dummy clear')
128
+
129
+ class NotificationCompatBuilder:
130
+ def __init__(self,context,channel_id):
131
+ self.mActions = MActions()
132
+ pass
133
+ def setProgress(self,max_value,current_value,endless):
134
+ pass
135
+ def setStyle(self,style):
136
+ pass
137
+ def setContentTitle(self,title):
138
+ pass
139
+ def setContentText(self,text):
140
+ pass
141
+ def setSmallIcon(self,icon):
142
+ pass
143
+ def setLargeIcon(self,icon):
144
+ pass
145
+ def setAutoCancel(self,auto_cancel:bool):
146
+ pass
147
+ def setPriority(self,priority:Importance):
148
+ pass
149
+ def setDefaults(self,defaults:NotificationCompat.DEFAULT_ALL):
150
+ pass
151
+ def setOngoing(self,persistent:bool):
152
+ pass
153
+ def setOnlyAlertOnce(self,state):
154
+ pass
155
+ def build(self):
156
+ pass
157
+ def setContentIntent(self,pending_action_intent:PendingIntent):
158
+ pass
159
+ def addAction(self,icon_int,action_text,pending_action_intent):
160
+ pass
161
+ def setShowWhen(self,state):
162
+ pass
163
+ def setWhen(self,time_ms):
164
+ pass
165
+ def setCustomContentView(self,layout):
166
+ pass
167
+ def setCustomBigContentView(self,layout):
168
+ pass
169
+ def setSubText(self,text):
170
+ pass
171
+ def setColor(self, color:Color) -> None:
172
+ pass
173
+ class NotificationCompatBigTextStyle:
174
+ def bigText(self,body):
175
+ return self
176
+
177
+ class NotificationCompatBigPictureStyle:
178
+ def bigPicture(self,bitmap):
179
+ return self
180
+
181
+ class NotificationCompatInboxStyle:
182
+ def addLine(self,line):
183
+ return self
184
+
185
+ class NotificationCompatDecoratedCustomViewStyle:
186
+ pass
187
+
188
+ class Permission:
189
+ POST_NOTIFICATIONS=''
190
+
191
+ def check_permission(permission:Permission.POST_NOTIFICATIONS):
192
+ print(permission)
193
+
194
+ def request_permissions(_list: [], _callback):
195
+ _callback()
196
+
197
+ class AndroidActivity:
198
+ def bind(self,on_new_intent):
199
+ pass
200
+ def unbind(self,on_new_intent):
201
+ pass
202
+
203
+ class PythonActivity:
204
+ pass
205
+
206
+ class DummyIcon:
207
+ icon = 101
208
+ pass
209
+ class Context:
210
+ def __init__(self):
211
+ pass
212
+
213
+ @staticmethod
214
+ def getApplicationInfo():
215
+ return DummyIcon
216
+
217
+ @staticmethod
218
+ def getResources():
219
+ return None
220
+
221
+ @staticmethod
222
+ def getPackageName():
223
+ return None # TODO get package name from buildozer.spec file
224
+
225
+ #Now writing Knowledge from errors
226
+ # notify.(int, Builder.build()) # must be int
@@ -1,18 +1,129 @@
1
- """Collection of useful functions"""
2
-
3
- import inspect
4
- def can_accept_arguments(func, *args, **kwargs):
5
- try:
6
- sig = inspect.signature(func)
7
- sig.bind(*args, **kwargs)
8
- return True
9
- except TypeError:
10
- return False
11
-
12
-
13
- def run_on_ui_thread(func):
14
- """Fallback for Developing on PC"""
15
- def wrapper(*args, **kwargs):
16
- # print("Simulating run on UI thread")
17
- return func(*args, **kwargs)
18
- return wrapper
1
+ """Collection of useful functions"""
2
+
3
+ import inspect, os, re, traceback
4
+ from .config import autoclass
5
+ from .an_types import Importance
6
+ from .config import (
7
+ get_python_activity_context, app_storage_path,ON_ANDROID,
8
+ BitmapFactory, BuildVersion, Bundle,
9
+ NotificationManagerCompat,NotificationCompat
10
+ )
11
+
12
+ if ON_ANDROID:
13
+ Color = autoclass('android.graphics.Color')
14
+ else:
15
+ from .an_types import Color
16
+
17
+ def can_accept_arguments(func, *args, **kwargs):
18
+ try:
19
+ sig = inspect.signature(func)
20
+ sig.bind(*args, **kwargs)
21
+ return True
22
+ except TypeError:
23
+ return False
24
+
25
+ if ON_ANDROID:
26
+ context = get_python_activity_context()
27
+ else:
28
+ context = None
29
+
30
+ def get_android_importance(importance: Importance):
31
+ """
32
+ Returns Android Importance Values
33
+ :param importance: ['urgent','high','medium','low','none']
34
+ :return: Android equivalent int or empty str
35
+ """
36
+ if not ON_ANDROID:
37
+ return None
38
+ value = ''
39
+ if importance == 'urgent':
40
+ value = NotificationCompat.PRIORITY_HIGH if BuildVersion.SDK_INT <= 25 else NotificationManagerCompat.IMPORTANCE_HIGH
41
+ elif importance == 'high':
42
+ value = NotificationCompat.PRIORITY_DEFAULT if BuildVersion.SDK_INT <= 25 else NotificationManagerCompat.IMPORTANCE_DEFAULT
43
+ elif importance == 'medium':
44
+ value = NotificationCompat.PRIORITY_LOW if BuildVersion.SDK_INT <= 25 else NotificationManagerCompat.IMPORTANCE_LOW
45
+ elif importance == 'low':
46
+ value = NotificationCompat.PRIORITY_MIN if BuildVersion.SDK_INT <= 25 else NotificationManagerCompat.IMPORTANCE_MIN
47
+ elif importance == 'none':
48
+ value = '' if BuildVersion.SDK_INT <= 25 else NotificationManagerCompat.IMPORTANCE_NONE
49
+
50
+ return value
51
+ # side-note 'medium' = NotificationCompat.PRIORITY_LOW and 'low' = NotificationCompat.PRIORITY_MIN # weird but from docs
52
+
53
+ def generate_channel_id(channel_name: str) -> str:
54
+ """
55
+ Generate a readable and consistent channel ID from a channel name.
56
+
57
+ Args:
58
+ channel_name (str): The name of the notification channel.
59
+
60
+ Returns:
61
+ str: A sanitized channel ID.
62
+ """
63
+ # Normalize the channel name
64
+ channel_id = channel_name.strip().lower()
65
+ # Replace spaces and special characters with underscores
66
+ channel_id = re.sub(r'[^a-z0-9]+', '_', channel_id)
67
+ # Remove leading/trailing underscores
68
+ channel_id = channel_id.strip('_')
69
+ return channel_id[:50]
70
+
71
+ def get_img_from_path(relative_path):
72
+ app_folder = os.path.join(app_storage_path(), 'app')
73
+ output_path = os.path.join(app_folder, relative_path)
74
+ if not os.path.exists(output_path):
75
+ print(f"\nImage not found at path: {app_folder}, (Local images gotten from App Path)")
76
+ try:
77
+ print("- These are the existing files in your app Folder:")
78
+ print('[' + ', '.join(os.listdir(app_folder)) + ']')
79
+ except Exception as could_not_get_files_in_path_error:
80
+ print('Exception: ', could_not_get_files_in_path_error)
81
+ print("Couldn't get Files in App Folder")
82
+ return None
83
+ # TODO test with a badly written Image and catch error
84
+ Uri = autoclass('android.net.Uri')
85
+ uri = Uri.parse(f"file://{output_path}")
86
+ return BitmapFactory.decodeStream(context.getContentResolver().openInputStream(uri))
87
+
88
+ def setLayoutText(layout, id, text, color):
89
+ # checked if self.title_color available before entering method
90
+ if id and text:
91
+ layout.setTextViewText(id, text)
92
+ if color:
93
+ layout.setTextColor(id, Color.parseColor(color))
94
+
95
+ def get_bitmap_from_url(url, callback, logs):
96
+ """Gets Bitmap from url
97
+
98
+ Args:
99
+ :param url: img url
100
+ :param callback: function to be called after thread done, callback receives bitmap data as argument
101
+ :param logs:
102
+ """
103
+ if logs:
104
+ print("getting Bitmap from URL---")
105
+ try:
106
+ URL = autoclass('java.net.URL')
107
+ url = URL(url)
108
+ connection = url.openConnection()
109
+ connection.connect()
110
+ input_stream = connection.getInputStream()
111
+ bitmap = BitmapFactory.decodeStream(input_stream)
112
+ input_stream.close()
113
+ if bitmap:
114
+ callback(bitmap)
115
+ else:
116
+ print('Error No Bitmap for small icon ------------')
117
+ except Exception as extracting_bitmap_frm_URL_error:
118
+ callback(None)
119
+ # TODO get all types of JAVA Error that can fail here
120
+ print('Error Type ', extracting_bitmap_frm_URL_error)
121
+ print('Failed to get Bitmap from URL ', traceback.format_exc())
122
+
123
+ def add_data_to_intent(intent, title):
124
+ """Persist Some data to notification object for later use"""
125
+ bundle = Bundle()
126
+ bundle.putString("title", title or 'Title Placeholder')
127
+ # bundle.putInt("notify_id", self.__id)
128
+ bundle.putInt("notify_id", 101)
129
+ intent.putExtras(bundle)