cordova-plugin-local-notifications-continued 1.2.4
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.
- package/.github/FUNDING.yml +1 -0
- package/.github/ISSUE_TEMPLATE/report_issue.yml +126 -0
- package/CHANGELOG.md +358 -0
- package/LICENSE +202 -0
- package/README.md +1531 -0
- package/images/android-actions-with-input-clicked.png +0 -0
- package/images/android-actions-with-input-not-clicked.png +0 -0
- package/images/android-actions.png +0 -0
- package/images/android-alarms-and-reminders-in-app-settings.png +0 -0
- package/images/android-alarms-and-reminders-setting.png +0 -0
- package/images/android-app-hibernation-notification.png +0 -0
- package/images/android-app-hibernation-settings-android-12.png +0 -0
- package/images/android-app-hibernation-settings-android-13-14.png +0 -0
- package/images/android-app-hibernation-settings-android-15.png +0 -0
- package/images/android-attachments-image-folded.png +0 -0
- package/images/android-attachments-image-unfolded.png +0 -0
- package/images/android-chat.png +0 -0
- package/images/android-icon.svg +19 -0
- package/images/android-inbox.png +0 -0
- package/images/android-notification-example.png +0 -0
- package/images/android-progress.png +0 -0
- package/images/android-request-permission.png +0 -0
- package/images/android-stack.png +0 -0
- package/images/apple-icon.svg +1 -0
- package/images/cordova-app-notified-logo.png +0 -0
- package/images/ios-actions-with-input.png +0 -0
- package/images/ios-actions.png +0 -0
- package/images/ios-attachments-image-folded.png +0 -0
- package/images/ios-attachments-image-unfolded.png +0 -0
- package/images/ios-notification.png +0 -0
- package/images/ios-request-permission.png +0 -0
- package/images/logo.png +0 -0
- package/package.json +53 -0
- package/plugin.xml +266 -0
- package/src/android/ClickActivity.java +72 -0
- package/src/android/LocalNotification.java +779 -0
- package/src/android/Manager.java +327 -0
- package/src/android/Notification.java +844 -0
- package/src/android/Options.java +956 -0
- package/src/android/OptionsTrigger.java +104 -0
- package/src/android/action/Action.java +214 -0
- package/src/android/action/ActionGroup.java +135 -0
- package/src/android/build/localnotification.gradle +29 -0
- package/src/android/receiver/ClearReceiver.java +61 -0
- package/src/android/receiver/RestoreReceiver.java +70 -0
- package/src/android/receiver/TriggerReceiver.java +70 -0
- package/src/android/trigger/TriggerHandler.java +195 -0
- package/src/android/trigger/TriggerHandlerAt.java +63 -0
- package/src/android/trigger/TriggerHandlerEvery.java +257 -0
- package/src/android/trigger/TriggerHandlerIn.java +69 -0
- package/src/android/util/AssetUtil.java +385 -0
- package/src/android/util/CallbackContextUtil.java +88 -0
- package/src/android/util/PluginFileProvider.java +34 -0
- package/src/android/xml/shared_files_provider_paths.xml +38 -0
- package/src/ios/APPLocalNotification.h +56 -0
- package/src/ios/APPLocalNotification.m +650 -0
- package/src/ios/APPNotificationCategory.h +28 -0
- package/src/ios/APPNotificationCategory.m +107 -0
- package/src/ios/APPNotificationContent.h +32 -0
- package/src/ios/APPNotificationContent.m +122 -0
- package/src/ios/APPNotificationOptions.h +42 -0
- package/src/ios/APPNotificationOptions.m +689 -0
- package/src/ios/UNNotificationRequest+APPLocalNotification.h +32 -0
- package/src/ios/UNNotificationRequest+APPLocalNotification.m +100 -0
- package/src/ios/UNUserNotificationCenter+APPLocalNotification.h +60 -0
- package/src/ios/UNUserNotificationCenter+APPLocalNotification.m +344 -0
- package/www/local-notification.js +1104 -0
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Apache 2.0 License
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) Sebastian Katzer 2017
|
|
5
|
+
* Copyright (c) Manuel Beck 2024
|
|
6
|
+
*
|
|
7
|
+
* This file contains Original Code and/or Modifications of Original Code
|
|
8
|
+
* as defined in and that are subject to the Apache License
|
|
9
|
+
* Version 2.0 (the 'License'). You may not use this file except in
|
|
10
|
+
* compliance with the License. Please obtain a copy of the License at
|
|
11
|
+
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
|
|
12
|
+
* file.
|
|
13
|
+
*
|
|
14
|
+
* The Original Code and all software distributed under the License are
|
|
15
|
+
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
|
16
|
+
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
|
17
|
+
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
|
19
|
+
* Please see the License for the specific language governing rights and
|
|
20
|
+
* limitations under the License.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
// codebeat:disable[TOO_MANY_FUNCTIONS]
|
|
24
|
+
|
|
25
|
+
package de.appplant.cordova.plugin.localnotification;
|
|
26
|
+
|
|
27
|
+
import android.annotation.SuppressLint;
|
|
28
|
+
import android.app.AlarmManager;
|
|
29
|
+
import android.app.NotificationChannel;
|
|
30
|
+
import androidx.core.app.NotificationManagerCompat;
|
|
31
|
+
import android.content.Context;
|
|
32
|
+
import android.content.Intent;
|
|
33
|
+
import android.content.SharedPreferences;
|
|
34
|
+
import android.service.notification.StatusBarNotification;
|
|
35
|
+
import android.media.AudioAttributes;
|
|
36
|
+
import android.net.Uri;
|
|
37
|
+
import android.util.Log;
|
|
38
|
+
import android.os.PowerManager;
|
|
39
|
+
|
|
40
|
+
import org.json.JSONException;
|
|
41
|
+
import org.json.JSONObject;
|
|
42
|
+
|
|
43
|
+
import java.util.ArrayList;
|
|
44
|
+
import java.util.Calendar;
|
|
45
|
+
import java.util.List;
|
|
46
|
+
import java.util.Random;
|
|
47
|
+
import java.util.Set;
|
|
48
|
+
|
|
49
|
+
import static android.os.Build.VERSION.SDK_INT;
|
|
50
|
+
import static android.os.Build.VERSION_CODES.O;
|
|
51
|
+
import static android.os.Build.VERSION_CODES.P;
|
|
52
|
+
import static android.os.Build.VERSION_CODES.S;
|
|
53
|
+
import static de.appplant.cordova.plugin.localnotification.Notification.Type.TRIGGERED;
|
|
54
|
+
import de.appplant.cordova.plugin.localnotification.util.AssetUtil;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Central way to access all or single local notifications set by specific
|
|
58
|
+
* state like triggered or scheduled. Offers shortcut ways to schedule,
|
|
59
|
+
* cancel or clear local notifications.
|
|
60
|
+
*/
|
|
61
|
+
public final class Manager {
|
|
62
|
+
// Key for shared preferences
|
|
63
|
+
static final String PREF_KEY_ID = "NOTIFICATION_ID";
|
|
64
|
+
|
|
65
|
+
public static final String TAG = "Manager";
|
|
66
|
+
|
|
67
|
+
private Context context;
|
|
68
|
+
|
|
69
|
+
private static final Random randomGenerator = new Random();
|
|
70
|
+
|
|
71
|
+
public Manager(Context context) {
|
|
72
|
+
this.context = context;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Check if the setting to schedule exact alarms is enabled.
|
|
77
|
+
*/
|
|
78
|
+
public static boolean canScheduleExactAlarms(Context context) {
|
|
79
|
+
// Supported since Android 12
|
|
80
|
+
if (SDK_INT < S) return true;
|
|
81
|
+
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
|
|
82
|
+
return alarmManager.canScheduleExactAlarms();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
public static NotificationChannel getChannel(Context context, Options options) {
|
|
86
|
+
// Channels are only supported since Android 8
|
|
87
|
+
if (SDK_INT < O) return null;
|
|
88
|
+
return NotificationManagerCompat.from(context).getNotificationChannel(options.getAndroidChannelId());
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Create Notification channel with options
|
|
93
|
+
* @param options Set of channel options.
|
|
94
|
+
*
|
|
95
|
+
*/
|
|
96
|
+
public static void createChannel(Context context, Options options) {
|
|
97
|
+
// Channels are only supported since Android 8
|
|
98
|
+
if (SDK_INT < O) return;
|
|
99
|
+
|
|
100
|
+
// Check if channel exists
|
|
101
|
+
NotificationChannel channel = getChannel(context, options);
|
|
102
|
+
|
|
103
|
+
// Channel already created
|
|
104
|
+
if (channel != null) return;
|
|
105
|
+
|
|
106
|
+
Log.d(TAG, "Create channel" +
|
|
107
|
+
", id=" + options.getAndroidChannelId() +
|
|
108
|
+
", name=" + options.getAndroidChannelName() +
|
|
109
|
+
", options=" + options);
|
|
110
|
+
|
|
111
|
+
// Create new channel
|
|
112
|
+
channel = new NotificationChannel(
|
|
113
|
+
options.getAndroidChannelId(),
|
|
114
|
+
options.getAndroidChannelName(), options.getAndroidChannelImportance());
|
|
115
|
+
|
|
116
|
+
channel.setDescription(options.getAndroidChannelDescription());
|
|
117
|
+
channel.enableVibration(options.isAndroidChannelEnableVibration());
|
|
118
|
+
channel.enableLights(options.getAndroidChannelEnableLights());
|
|
119
|
+
|
|
120
|
+
Uri soundUri = options.getSoundUri();
|
|
121
|
+
Log.d(TAG, "sound uri: " + soundUri);
|
|
122
|
+
|
|
123
|
+
// Grant permission to the system to play the sound, needed only in Android 8
|
|
124
|
+
if (soundUri != Uri.EMPTY && SDK_INT < P) {
|
|
125
|
+
grantUriPermission(context, soundUri);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// If options.getSoundUri() is Uri.EMPTY, an empty sound will be set, which means no sound
|
|
129
|
+
channel.setSound(soundUri, new AudioAttributes.Builder().setUsage(options.getSoundUsage()).build());
|
|
130
|
+
|
|
131
|
+
NotificationManagerCompat.from(context).createNotificationChannel(channel);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Deletes a notification channel by an id. If you create a new channel with this same id,
|
|
136
|
+
* the deleted channel will be un-deleted with all of the same settings it had before it was deleted.
|
|
137
|
+
* @param channelId Like "my_channel_01"
|
|
138
|
+
*/
|
|
139
|
+
public void deleteChannel(String channelId) {
|
|
140
|
+
// Channels are supported since Android 8
|
|
141
|
+
if (SDK_INT < O) return;
|
|
142
|
+
|
|
143
|
+
Log.d(TAG, "Delete channel, id=" + channelId);
|
|
144
|
+
|
|
145
|
+
// Cancel all notifications regarding this channel
|
|
146
|
+
for (Notification notification : new Manager(context).getNotificationsFromSharedPreferences()) {
|
|
147
|
+
if (notification.getOptions().getAndroidChannelId().equals(channelId)) {
|
|
148
|
+
notification.cancel();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
NotificationManagerCompat.from(context).deleteNotificationChannel(channelId);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Update local notification specified by ID.
|
|
157
|
+
* @param notificationId The ID of the notification.
|
|
158
|
+
* @param updates JSON object with notification options.
|
|
159
|
+
*/
|
|
160
|
+
public Notification update(int notificationId, JSONObject updates) {
|
|
161
|
+
Notification notification = Notification.getFromSharedPreferences(context, notificationId);
|
|
162
|
+
if (notification == null) return null;
|
|
163
|
+
|
|
164
|
+
notification.update(updates);
|
|
165
|
+
|
|
166
|
+
return notification;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Clear all local notifications.
|
|
171
|
+
*/
|
|
172
|
+
public void clearAll() {
|
|
173
|
+
for (Notification notification : getByType(TRIGGERED)) {
|
|
174
|
+
notification.clear();
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
NotificationManagerCompat.from(context).cancelAll();
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Cancel all local notifications.
|
|
182
|
+
*/
|
|
183
|
+
public void cancelAll() {
|
|
184
|
+
for (Notification notification : getNotificationsFromSharedPreferences()) {
|
|
185
|
+
notification.cancel();
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
NotificationManagerCompat.from(context).cancelAll();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Get saved notification ids
|
|
193
|
+
*/
|
|
194
|
+
public List<Integer> getNotificationIds() {
|
|
195
|
+
List<Integer> notificationIds = new ArrayList<Integer>();
|
|
196
|
+
|
|
197
|
+
// Options are stored by the notification id in the shared preferences
|
|
198
|
+
for (String key : getSharedPreferences().getAll().keySet()) {
|
|
199
|
+
// Skip keys with underscore for e.g. _occurrence
|
|
200
|
+
if (key.contains("_")) continue;
|
|
201
|
+
|
|
202
|
+
try {
|
|
203
|
+
notificationIds.add(Integer.parseInt(key));
|
|
204
|
+
} catch (NumberFormatException exception) {
|
|
205
|
+
exception.printStackTrace();
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return notificationIds;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Get saved notification ids for a given type.
|
|
214
|
+
* @param type The notification life cycle type
|
|
215
|
+
*/
|
|
216
|
+
public List<Integer> getNotificationIdsByType(Notification.Type type) {
|
|
217
|
+
// Returns triggered and scheduled notifications
|
|
218
|
+
if (type == Notification.Type.ALL) return getNotificationIds();
|
|
219
|
+
|
|
220
|
+
List<Integer> activeIds = new ArrayList<Integer>();
|
|
221
|
+
|
|
222
|
+
for (StatusBarNotification statusBarNotification : getActiveNotifications()) {
|
|
223
|
+
activeIds.add(statusBarNotification.getId());
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (type == TRIGGERED) return activeIds;
|
|
227
|
+
|
|
228
|
+
// Return scheduled notifications
|
|
229
|
+
List<Integer> notificationIds = getNotificationIds();
|
|
230
|
+
// Remove triggered notifications
|
|
231
|
+
notificationIds.removeAll(activeIds);
|
|
232
|
+
|
|
233
|
+
return notificationIds;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* List of all local notification.
|
|
238
|
+
*/
|
|
239
|
+
public List<Notification> getNotificationsFromSharedPreferences() {
|
|
240
|
+
return getNotificationsFromSharedPreferences(getNotificationIds());
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* List of local notifications with matching ID.
|
|
245
|
+
*/
|
|
246
|
+
public List<Notification> getNotificationsFromSharedPreferences(List<Integer> notificationIds) {
|
|
247
|
+
List<Notification> notifications = new ArrayList<Notification>();
|
|
248
|
+
|
|
249
|
+
for (int notificationId : notificationIds) {
|
|
250
|
+
Notification notification = Notification.getFromSharedPreferences(context, notificationId);
|
|
251
|
+
if (notification != null) notifications.add(notification);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return notifications;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* List of local notifications from given type.
|
|
259
|
+
*
|
|
260
|
+
* @param type The notification life cycle type
|
|
261
|
+
*/
|
|
262
|
+
public List<Notification> getByType(Notification.Type type) {
|
|
263
|
+
return type == Notification.Type.ALL ? getNotificationsFromSharedPreferences() : getNotificationsFromSharedPreferences(getNotificationIdsByType(type));
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Returns the active status bar notification with the specified notificationId.
|
|
268
|
+
* If there is no active status bar notification, null will be returned.
|
|
269
|
+
* @param notificationId
|
|
270
|
+
*/
|
|
271
|
+
StatusBarNotification getActiveNotification(int notificationId) {
|
|
272
|
+
for (StatusBarNotification statusBarNotification : getActiveNotifications()) {
|
|
273
|
+
if (statusBarNotification.getId() == notificationId) {
|
|
274
|
+
return statusBarNotification;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
return null;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
public SharedPreferences getSharedPreferences() {
|
|
282
|
+
return getSharedPreferences(context);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Shared private preferences for the application.
|
|
287
|
+
*/
|
|
288
|
+
public static SharedPreferences getSharedPreferences(Context context) {
|
|
289
|
+
return context.getSharedPreferences(PREF_KEY_ID, Context.MODE_PRIVATE);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Get all active status bar notifications.
|
|
294
|
+
*/
|
|
295
|
+
public List<StatusBarNotification> getActiveNotifications() {
|
|
296
|
+
return NotificationManagerCompat.from(context).getActiveNotifications();
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Wake up the screen and returns a WakeLock, which have to be release, after the work is done.
|
|
301
|
+
* @return WakeLock, which have to be release, after the work is done.
|
|
302
|
+
*/
|
|
303
|
+
public static PowerManager.WakeLock wakeUpScreen(Context context) {
|
|
304
|
+
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
|
305
|
+
PowerManager.WakeLock wakeLook = powerManager.newWakeLock(
|
|
306
|
+
PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "LocalNotification");
|
|
307
|
+
wakeLook.acquire();
|
|
308
|
+
return wakeLook;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* In Android 7 and 8, the app will crash if an external process has no
|
|
313
|
+
* permission to access content:// Uris, which are used for shared files in [App path]/files/shared_files.
|
|
314
|
+
* This was fixed in Android 9.
|
|
315
|
+
* See: https://stackoverflow.com/questions/39359465/android-7-0-notification-sound-from-file-provider-uri-not-playing
|
|
316
|
+
*/
|
|
317
|
+
public static void grantUriPermission(Context context, Uri uri) {
|
|
318
|
+
context.grantUriPermission("com.android.systemui", uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Gets a random request code between 1 and Integer.MAX_VALUE.
|
|
323
|
+
*/
|
|
324
|
+
public static int getRandomRequestCode() {
|
|
325
|
+
return randomGenerator.nextInt(Integer.MAX_VALUE) + 1;
|
|
326
|
+
}
|
|
327
|
+
}
|