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,104 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Apache 2.0 License
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) Manuel Beck 2025
|
|
5
|
+
*
|
|
6
|
+
* This file contains Original Code and/or Modifications of Original Code
|
|
7
|
+
* as defined in and that are subject to the Apache License
|
|
8
|
+
* Version 2.0 (the 'License'). You may not use this file except in
|
|
9
|
+
* compliance with the License. Please obtain a copy of the License at
|
|
10
|
+
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
|
|
11
|
+
* file.
|
|
12
|
+
*
|
|
13
|
+
* The Original Code and all software distributed under the License are
|
|
14
|
+
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
|
15
|
+
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
|
16
|
+
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
|
18
|
+
* Please see the License for the specific language governing rights and
|
|
19
|
+
* limitations under the License.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
package de.appplant.cordova.plugin.localnotification;
|
|
23
|
+
|
|
24
|
+
import org.json.JSONObject;
|
|
25
|
+
|
|
26
|
+
public class OptionsTrigger {
|
|
27
|
+
|
|
28
|
+
private JSONObject triggerJSON;
|
|
29
|
+
|
|
30
|
+
public OptionsTrigger(JSONObject triggerJSON) {
|
|
31
|
+
this.triggerJSON = triggerJSON;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public boolean has(String key) {
|
|
35
|
+
return triggerJSON.has(key);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public long getAt() {
|
|
39
|
+
return triggerJSON.optLong("at", 0);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public int getIn() {
|
|
43
|
+
return triggerJSON.optInt("in", 0);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public String getUnit() {
|
|
47
|
+
return triggerJSON.optString("unit", null);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Only for repeating notifications, when the first notification should be triggered.
|
|
52
|
+
*/
|
|
53
|
+
public long getFirstAt() {
|
|
54
|
+
return triggerJSON.optLong("firstAt", 0);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Only for repeating notifications, when the first notification should be triggered.
|
|
59
|
+
*/
|
|
60
|
+
public long getAfter() {
|
|
61
|
+
return triggerJSON.optLong("after", 0);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* If a repeating notification should be stopped after some occurrences. -1 means infinite.
|
|
66
|
+
* @return
|
|
67
|
+
*/
|
|
68
|
+
public int getCount() {
|
|
69
|
+
return triggerJSON.optInt("count", -1);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Can be a {@link String} or {@link JSONObject}.
|
|
74
|
+
*/
|
|
75
|
+
public Object getEvery() {
|
|
76
|
+
return triggerJSON.opt("every");
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Gets trigger.every as {@link String}. If trigger.every is a {@link JSONObject}, it returns null
|
|
81
|
+
*/
|
|
82
|
+
public String getEveryAsString() {
|
|
83
|
+
return getEvery() instanceof String ? (String) getEvery() : null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Gets trigger.every as {@link JSONObject}. If trigger.every is a {@link String}, it returns null
|
|
88
|
+
*/
|
|
89
|
+
public JSONObject getEveryAsJSONObject() {
|
|
90
|
+
return getEvery() instanceof JSONObject ? (JSONObject) getEvery() : null;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
public long getBefore() {
|
|
94
|
+
return triggerJSON.optLong("before", 0);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
public JSONObject getJSON() {
|
|
98
|
+
return triggerJSON;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
public String toString() {
|
|
102
|
+
return triggerJSON.toString();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,214 @@
|
|
|
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
|
+
package de.appplant.cordova.plugin.localnotification.action;
|
|
24
|
+
|
|
25
|
+
import android.content.Context;
|
|
26
|
+
import android.content.Intent;
|
|
27
|
+
import android.os.Bundle;
|
|
28
|
+
import android.os.Looper;
|
|
29
|
+
import android.util.Log;
|
|
30
|
+
import androidx.core.app.RemoteInput;
|
|
31
|
+
|
|
32
|
+
import org.json.JSONArray;
|
|
33
|
+
import org.json.JSONObject;
|
|
34
|
+
import org.json.JSONException;
|
|
35
|
+
|
|
36
|
+
import de.appplant.cordova.plugin.localnotification.LocalNotification;
|
|
37
|
+
import de.appplant.cordova.plugin.localnotification.Notification;
|
|
38
|
+
import de.appplant.cordova.plugin.localnotification.util.AssetUtil;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Holds the icon and title components that would be used in a
|
|
42
|
+
* NotificationCompat.Action object. Does not include the PendingIntent so
|
|
43
|
+
* that it may be generated each time the notification is built. Necessary to
|
|
44
|
+
* compensate for missing functionality in the support library.
|
|
45
|
+
*/
|
|
46
|
+
public class Action {
|
|
47
|
+
|
|
48
|
+
private static final String TAG = "Action";
|
|
49
|
+
|
|
50
|
+
// Key name for bundled extras
|
|
51
|
+
public static final String EXTRA_ID = "NOTIFICATION_ACTION_ID";
|
|
52
|
+
|
|
53
|
+
private Context context;
|
|
54
|
+
|
|
55
|
+
private JSONObject actionOptionsJSON;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Structure to encapsulate a named action that can be shown as part of
|
|
59
|
+
* this notification.
|
|
60
|
+
*
|
|
61
|
+
* @param context The application context.
|
|
62
|
+
* @param actionOptionsJSON The action options.
|
|
63
|
+
*/
|
|
64
|
+
public Action(Context context, JSONObject actionOptionsJSON) {
|
|
65
|
+
this.context = context;
|
|
66
|
+
this.actionOptionsJSON = actionOptionsJSON;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Gets the ID for the action.
|
|
71
|
+
*/
|
|
72
|
+
public String getId() {
|
|
73
|
+
return actionOptionsJSON.optString("id", getTitle());
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
public String getType() {
|
|
77
|
+
return actionOptionsJSON.optString("type", "button");
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Gets the Title for the action.
|
|
82
|
+
*/
|
|
83
|
+
public String getTitle() {
|
|
84
|
+
return actionOptionsJSON.optString("title", "unknown");
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Gets the icon for the action. Since Android 7 (Nougat) icons for actions
|
|
89
|
+
* are not shown anymore. They would only be used on Android Wear.
|
|
90
|
+
* See: https://android-developers.googleblog.com/2016/06/notifications-in-android-n.html
|
|
91
|
+
*/
|
|
92
|
+
public int getIcon() {
|
|
93
|
+
String iconPath = actionOptionsJSON.optString("icon");
|
|
94
|
+
|
|
95
|
+
// Get icon from the app resources or system resources
|
|
96
|
+
int resId = new AssetUtil(context).getResourceId(iconPath, AssetUtil.RESOURCE_TYPE_DRAWABLE);
|
|
97
|
+
|
|
98
|
+
// Fallback, nothing found
|
|
99
|
+
if (resId == 0) resId = android.R.drawable.screen_background_dark;
|
|
100
|
+
|
|
101
|
+
return resId;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* If the app shpould be launched when the action is clicked.
|
|
106
|
+
* Default is <code>false</code>.
|
|
107
|
+
*/
|
|
108
|
+
public boolean isLaunch() {
|
|
109
|
+
return actionOptionsJSON.optBoolean("launch", false);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Returns true if the action is of type input.
|
|
114
|
+
*/
|
|
115
|
+
public boolean isInput() {
|
|
116
|
+
return getType().equals("input");
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Gets the input config in case of the action is of type input.
|
|
121
|
+
*/
|
|
122
|
+
public RemoteInput buildRemoteInput() {
|
|
123
|
+
return new RemoteInput.Builder(getId())
|
|
124
|
+
.setLabel(actionOptionsJSON.optString("emptyText"))
|
|
125
|
+
// Specifies whether the user can provide arbitrary text values
|
|
126
|
+
// The default is true. If you specify false, you must either provide a non-null and
|
|
127
|
+
// non-empty array to setChoices, or enable a data result in setAllowDataType.
|
|
128
|
+
// Otherwise an IllegalArgumentException is thrown
|
|
129
|
+
.setAllowFreeFormInput(actionOptionsJSON.optBoolean("editable", true))
|
|
130
|
+
.setChoices(getChoices())
|
|
131
|
+
.build();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* List of possible choices for input actions.
|
|
136
|
+
*/
|
|
137
|
+
private String[] getChoices() {
|
|
138
|
+
JSONArray opts = actionOptionsJSON.optJSONArray("choices");
|
|
139
|
+
|
|
140
|
+
if (opts == null)
|
|
141
|
+
return null;
|
|
142
|
+
|
|
143
|
+
String[] choices = new String[opts.length()];
|
|
144
|
+
|
|
145
|
+
for (int i = 0; i < choices.length; i++) {
|
|
146
|
+
choices[i] = opts.optString(i);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return choices;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
public void handleClick(Intent intent, Notification notification) {
|
|
153
|
+
Log.d(TAG, "Handle action click, options=" + actionOptionsJSON);
|
|
154
|
+
|
|
155
|
+
// Fire action click event to JS
|
|
156
|
+
LocalNotification.fireEvent(
|
|
157
|
+
getId(),
|
|
158
|
+
notification,
|
|
159
|
+
// Get input data for action, if it is an input action
|
|
160
|
+
getRemoteInputData(intent));
|
|
161
|
+
|
|
162
|
+
// Clear notification from statusbar if it should not be ongoing
|
|
163
|
+
// This will also remove the notification from the SharedPreferences
|
|
164
|
+
// if it is the last one
|
|
165
|
+
if (!notification.getOptions().isAndroidOngoing()) {
|
|
166
|
+
// A clear does not work on notifications with input fields:
|
|
167
|
+
// https://stackoverflow.com/questions/54219914/cancel-notification-with-remoteinput-not-working
|
|
168
|
+
// Google recommends after a reply to update the notificiation without the input action:
|
|
169
|
+
// https://developer.android.com/develop/ui/views/notifications/build-notification#retrieve-user-reply
|
|
170
|
+
// We update the notification without actions and cancel it after a timeout
|
|
171
|
+
if (isInput()) {
|
|
172
|
+
try {
|
|
173
|
+
notification.update(new JSONObject("{\"actions\": null}"));
|
|
174
|
+
// Clear the notification after a delay, because the update needs a little bit time to complete
|
|
175
|
+
// To be compatible with Android 7, this is done with a Handler
|
|
176
|
+
// Since Android 8, this could be handled with the property androidTimeoutAfter
|
|
177
|
+
new android.os.Handler(Looper.getMainLooper()).postDelayed(
|
|
178
|
+
new Runnable() {
|
|
179
|
+
public void run() {
|
|
180
|
+
notification.clear();
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
500);
|
|
184
|
+
} catch (JSONException e) {
|
|
185
|
+
Log.e(TAG, "Failed to update notification", e);
|
|
186
|
+
}
|
|
187
|
+
} else {
|
|
188
|
+
notification.clear();
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Launch the app if required
|
|
193
|
+
if (isLaunch()) LocalNotification.launchApp(context);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Gets the input data for an action, if available.
|
|
198
|
+
* @param intent The received intent.
|
|
199
|
+
* @param actionId The action where to look for.
|
|
200
|
+
*/
|
|
201
|
+
private JSONObject getRemoteInputData(Intent intent) {
|
|
202
|
+
Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
|
|
203
|
+
if (remoteInput == null) return null;
|
|
204
|
+
|
|
205
|
+
try {
|
|
206
|
+
JSONObject data = new JSONObject();
|
|
207
|
+
data.put("text", remoteInput.getCharSequence(getId()).toString());
|
|
208
|
+
return data;
|
|
209
|
+
} catch (JSONException jsonException) {
|
|
210
|
+
Log.e(TAG, "Failed to build remote input JSON", jsonException);
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
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
|
+
package de.appplant.cordova.plugin.localnotification.action;
|
|
24
|
+
|
|
25
|
+
import android.content.Context;
|
|
26
|
+
import android.util.Log;
|
|
27
|
+
|
|
28
|
+
import org.json.JSONArray;
|
|
29
|
+
import org.json.JSONException;
|
|
30
|
+
|
|
31
|
+
import java.util.ArrayList;
|
|
32
|
+
import java.util.List;
|
|
33
|
+
|
|
34
|
+
import de.appplant.cordova.plugin.localnotification.Manager;
|
|
35
|
+
|
|
36
|
+
public class ActionGroup {
|
|
37
|
+
|
|
38
|
+
private static final String TAG = "ActionGroup";
|
|
39
|
+
|
|
40
|
+
// Action group id
|
|
41
|
+
private String id;
|
|
42
|
+
|
|
43
|
+
// Actions JSON array, needed for storage
|
|
44
|
+
private JSONArray actionsJSONArray;
|
|
45
|
+
|
|
46
|
+
// List of actions
|
|
47
|
+
private List<Action> actions;
|
|
48
|
+
|
|
49
|
+
private Context context;
|
|
50
|
+
|
|
51
|
+
public ActionGroup(Context context, String actionGroupId, JSONArray actionsJSONArray) {
|
|
52
|
+
this.context = context;
|
|
53
|
+
this.id = actionGroupId;
|
|
54
|
+
this.actionsJSONArray = actionsJSONArray;
|
|
55
|
+
this.actions = new ArrayList<Action>(actionsJSONArray.length());
|
|
56
|
+
|
|
57
|
+
for (int i = 0; i < actionsJSONArray.length(); i++) {
|
|
58
|
+
this.actions.add(new Action(context, actionsJSONArray.optJSONObject(i)));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Gets the action group id.
|
|
64
|
+
*/
|
|
65
|
+
public String getId() {
|
|
66
|
+
return id;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Gets the action list.
|
|
71
|
+
*/
|
|
72
|
+
public List<Action> getActions() {
|
|
73
|
+
return actions;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Gets the action by id.
|
|
78
|
+
* @param actionId The id of the action to get.
|
|
79
|
+
* @return The action with the specified id or <code>null</code> if not found.
|
|
80
|
+
*/
|
|
81
|
+
public Action getActionById(String actionId) {
|
|
82
|
+
for (Action action : actions) {
|
|
83
|
+
if (action.getId().equals(actionId)) {
|
|
84
|
+
return action;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
Log.w(TAG, "Action not found, id=" + actionId);
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Stores this action group in the {@link SharedPreferences}.
|
|
94
|
+
*/
|
|
95
|
+
public void store() {
|
|
96
|
+
Manager.getSharedPreferences(context).edit()
|
|
97
|
+
.putString("ACTION_GROUP_" + id, actionsJSONArray.toString())
|
|
98
|
+
.apply();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Removes the action group from the {@link SharedPreferences}.
|
|
103
|
+
* @param context
|
|
104
|
+
* @param actionGroupId
|
|
105
|
+
*/
|
|
106
|
+
public static void remove(Context context, String actionGroupId) {
|
|
107
|
+
Manager.getSharedPreferences(context).edit()
|
|
108
|
+
.remove("ACTION_GROUP_" + actionGroupId)
|
|
109
|
+
.apply();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Gets the action group with the specified actionGroupId from the
|
|
114
|
+
* {@link SharedPreferences}.
|
|
115
|
+
*
|
|
116
|
+
* @param context The application context.
|
|
117
|
+
* @param actionGroupId The id of the action group to get.
|
|
118
|
+
*
|
|
119
|
+
* @return The restored action group from {@link SharedPreferences} or <code>null</code> if not found.
|
|
120
|
+
*/
|
|
121
|
+
public static ActionGroup get(Context context, String actionGroupId) {
|
|
122
|
+
String actionsJSON = Manager.getSharedPreferences(context)
|
|
123
|
+
.getString("ACTION_GROUP_" + actionGroupId, null);
|
|
124
|
+
|
|
125
|
+
if (actionsJSON == null) return null;
|
|
126
|
+
|
|
127
|
+
try {
|
|
128
|
+
JSONArray actionsJSONArray = new JSONArray(actionsJSON);
|
|
129
|
+
return new ActionGroup(context, actionGroupId, actionsJSONArray);
|
|
130
|
+
} catch (JSONException jsonException) {
|
|
131
|
+
Log.e(TAG, "Failed to restore action group: " + actionGroupId, jsonException);
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file contains Original Code and/or Modifications of Original Code
|
|
3
|
+
* as defined in and that are subject to the Apache License
|
|
4
|
+
* Version 2.0 (the 'License'). You may not use this file except in
|
|
5
|
+
* compliance with the License. Please obtain a copy of the License at
|
|
6
|
+
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
|
|
7
|
+
* file.
|
|
8
|
+
*
|
|
9
|
+
* The Original Code and all software distributed under the License are
|
|
10
|
+
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
|
11
|
+
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
|
12
|
+
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
|
13
|
+
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
|
14
|
+
* Please see the License for the specific language governing rights and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
repositories {
|
|
19
|
+
mavenCentral()
|
|
20
|
+
maven {
|
|
21
|
+
url "https://maven.google.com"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
dependencies {
|
|
26
|
+
// Needed for getUnusedAppRestrictionsStatus:
|
|
27
|
+
// - Class ListenableFuture
|
|
28
|
+
implementation("com.google.guava:guava:33.4.0-android")
|
|
29
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
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
|
+
package de.appplant.cordova.plugin.localnotification.receiver;
|
|
24
|
+
|
|
25
|
+
import android.content.BroadcastReceiver;
|
|
26
|
+
import android.content.Context;
|
|
27
|
+
import android.content.Intent;
|
|
28
|
+
import android.os.Bundle;
|
|
29
|
+
import android.util.Log;
|
|
30
|
+
|
|
31
|
+
import de.appplant.cordova.plugin.localnotification.Notification;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The clear intent receiver is triggered when the user clears a
|
|
35
|
+
* notification manually. It removes the notification from the
|
|
36
|
+
* SharedPreferences if it was the last onex to trigger.
|
|
37
|
+
*/
|
|
38
|
+
public class ClearReceiver extends BroadcastReceiver {
|
|
39
|
+
|
|
40
|
+
public static final String TAG = "ClearReceiver";
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Called when the notification was cleared from the notification center.
|
|
44
|
+
* @param context Application context
|
|
45
|
+
* @param intent Received intent with content data
|
|
46
|
+
*/
|
|
47
|
+
@Override
|
|
48
|
+
public void onReceive(Context context, Intent intent) {
|
|
49
|
+
Log.d(TAG, "Notification cleared, extras=" + intent.getExtras());
|
|
50
|
+
Notification notification = Notification.getFromSharedPreferences(context, intent.getIntExtra(Notification.EXTRA_ID, -1));
|
|
51
|
+
|
|
52
|
+
// Notification not found for id in SharedPreferences
|
|
53
|
+
if (notification == null) {
|
|
54
|
+
Log.w(TAG, "Notification not found for id, doing nothing, id=" + intent.getIntExtra(Notification.EXTRA_ID, -1));
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Will remove the notification from SharedPreferences if it is the last one
|
|
59
|
+
notification.clear();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2014-2015 by appPlant UG. All rights reserved.
|
|
3
|
+
*
|
|
4
|
+
* @APPPLANT_LICENSE_HEADER_START@
|
|
5
|
+
*
|
|
6
|
+
* This file contains Original Code and/or Modifications of Original Code
|
|
7
|
+
* as defined in and that are subject to the Apache License
|
|
8
|
+
* Version 2.0 (the 'License'). You may not use this file except in
|
|
9
|
+
* compliance with the License. Please obtain a copy of the License at
|
|
10
|
+
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
|
|
11
|
+
* file.
|
|
12
|
+
*
|
|
13
|
+
* The Original Code and all software distributed under the License are
|
|
14
|
+
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
|
15
|
+
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
|
16
|
+
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
|
18
|
+
* Please see the License for the specific language governing rights and
|
|
19
|
+
* limitations under the License.
|
|
20
|
+
*
|
|
21
|
+
* @APPPLANT_LICENSE_HEADER_END@
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
package de.appplant.cordova.plugin.localnotification.receiver;
|
|
25
|
+
|
|
26
|
+
import android.app.AlarmManager;
|
|
27
|
+
import android.content.BroadcastReceiver;
|
|
28
|
+
import android.content.Context;
|
|
29
|
+
import android.content.Intent;
|
|
30
|
+
import android.util.Log;
|
|
31
|
+
|
|
32
|
+
import java.util.List;
|
|
33
|
+
|
|
34
|
+
import de.appplant.cordova.plugin.localnotification.Manager;
|
|
35
|
+
import de.appplant.cordova.plugin.localnotification.Notification;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* This class is triggered, when the system has cleared the alarms and notifications,
|
|
39
|
+
* e.g. because of a device reboot, app update or granting the SCHEDULE_EXACT_ALARM permission.
|
|
40
|
+
* The alarms and notifications needs to be restored.
|
|
41
|
+
*/
|
|
42
|
+
public class RestoreReceiver extends BroadcastReceiver {
|
|
43
|
+
|
|
44
|
+
public static final String TAG = "RestoreReceiver";
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Called when alarms and notifications need to be restored.
|
|
48
|
+
* @param context Application context
|
|
49
|
+
* @param intent Received intent with content data
|
|
50
|
+
*/
|
|
51
|
+
@Override
|
|
52
|
+
public void onReceive(Context context, Intent intent) {
|
|
53
|
+
Log.d(TAG, "Received action: " + intent.getAction());
|
|
54
|
+
|
|
55
|
+
// The device was booted and is unlocked
|
|
56
|
+
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED) ||
|
|
57
|
+
// The app was updated
|
|
58
|
+
intent.getAction().equals(Intent.ACTION_MY_PACKAGE_REPLACED) ||
|
|
59
|
+
// The app is granted the SCHEDULE_EXACT_ALARM permission
|
|
60
|
+
intent.getAction().equals(AlarmManager.ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED)) {
|
|
61
|
+
|
|
62
|
+
List<Notification> notifications = new Manager(context).getNotificationsFromSharedPreferences();
|
|
63
|
+
Log.d(TAG, "Restoring notifications, count: " + notifications.size());
|
|
64
|
+
|
|
65
|
+
for (Notification notification : notifications) {
|
|
66
|
+
notification.schedule();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
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
|
+
package de.appplant.cordova.plugin.localnotification.receiver;
|
|
24
|
+
|
|
25
|
+
import android.content.BroadcastReceiver;
|
|
26
|
+
import android.content.Context;
|
|
27
|
+
import android.content.Intent;
|
|
28
|
+
import android.util.Log;
|
|
29
|
+
|
|
30
|
+
import de.appplant.cordova.plugin.localnotification.Notification;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The alarm receiver is triggered when a scheduled alarm is fired. This class
|
|
34
|
+
* reads the information in the intent and displays this information in the
|
|
35
|
+
* Android notification bar. The notification uses the default notification
|
|
36
|
+
* sound and it vibrates the phone.
|
|
37
|
+
*/
|
|
38
|
+
public class TriggerReceiver extends BroadcastReceiver {
|
|
39
|
+
|
|
40
|
+
public static final String TAG = "TriggerReceiver";
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Called when an alarm was triggered.
|
|
44
|
+
* @param context Application context
|
|
45
|
+
* @param intent Received intent with content data
|
|
46
|
+
*/
|
|
47
|
+
@Override
|
|
48
|
+
public void onReceive(Context context, Intent intent) {
|
|
49
|
+
Log.d(TAG, "Received action: " + intent.getAction() + ", extras=" + intent.getExtras());
|
|
50
|
+
|
|
51
|
+
Notification notification = Notification.getFromSharedPreferences(context, intent.getIntExtra(Notification.EXTRA_ID, -1));
|
|
52
|
+
|
|
53
|
+
// Notification not found for id in SharedPreferences
|
|
54
|
+
if (notification == null) {
|
|
55
|
+
Log.w(TAG, "Notification not found for id, doing nothing, id=" + intent.getIntExtra(Notification.EXTRA_ID, -1));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Show the notification
|
|
60
|
+
notification.show(false);
|
|
61
|
+
|
|
62
|
+
// Schedule next notification if available. The notification
|
|
63
|
+
// will not be removed from the SharedPreferences, if there is no
|
|
64
|
+
// next trigger. So the ClickActivity
|
|
65
|
+
// and ClearReceiver can still read the notification data. They
|
|
66
|
+
// will remove the notification from the SharedPreferences if they are
|
|
67
|
+
// executed. A notification can ony be cleared or clicked.
|
|
68
|
+
notification.scheduleNext();
|
|
69
|
+
}
|
|
70
|
+
}
|