diff --git a/android/capacitor/build.gradle b/android/capacitor/build.gradle
index 934fd0427b..35bbffa879 100644
--- a/android/capacitor/build.gradle
+++ b/android/capacitor/build.gradle
@@ -3,9 +3,7 @@ ext {
androidxCoreVersion = project.hasProperty('androidxCoreVersion') ? rootProject.ext.androidxCoreVersion : '1.2.0'
androidxMaterialVersion = project.hasProperty('androidxMaterialVersion') ? rootProject.ext.androidxMaterialVersion : '1.1.0-rc02'
androidxBrowserVersion = project.hasProperty('androidxBrowserVersion') ? rootProject.ext.androidxBrowserVersion : '1.2.0'
- androidxLocalbroadcastmanagerVersion = project.hasProperty('androidxLocalbroadcastmanagerVersion') ? rootProject.ext.androidxLocalbroadcastmanagerVersion : '1.0.0'
androidxExifInterfaceVersion = project.hasProperty('androidxExifInterfaceVersion') ? rootProject.ext.androidxExifInterfaceVersion : '1.2.0'
- firebaseMessagingVersion = project.hasProperty('firebaseMessagingVersion') ? rootProject.ext.firebaseMessagingVersion : '20.1.2'
playServicesLocationVersion = project.hasProperty('playServicesLocationVersion') ? rootProject.ext.playServicesLocationVersion : '17.0.0'
junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.12'
androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.1.1'
@@ -64,9 +62,7 @@ dependencies {
implementation "androidx.core:core:$androidxCoreVersion"
implementation "com.google.android.material:material:$androidxMaterialVersion"
implementation "androidx.browser:browser:$androidxBrowserVersion"
- implementation "androidx.localbroadcastmanager:localbroadcastmanager:$androidxLocalbroadcastmanagerVersion"
implementation "androidx.exifinterface:exifinterface:$androidxExifInterfaceVersion"
- implementation "com.google.firebase:firebase-messaging:$firebaseMessagingVersion"
implementation "com.google.android.gms:play-services-location:$playServicesLocationVersion"
testImplementation "junit:junit:$junitVersion"
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
diff --git a/android/capacitor/src/main/AndroidManifest.xml b/android/capacitor/src/main/AndroidManifest.xml
index cf14288244..156de97b1b 100644
--- a/android/capacitor/src/main/AndroidManifest.xml
+++ b/android/capacitor/src/main/AndroidManifest.xml
@@ -5,24 +5,7 @@
android:required="false" />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
\ No newline at end of file
diff --git a/android/capacitor/src/main/java/com/getcapacitor/Bridge.java b/android/capacitor/src/main/java/com/getcapacitor/Bridge.java
index c6acf88275..646387c619 100644
--- a/android/capacitor/src/main/java/com/getcapacitor/Bridge.java
+++ b/android/capacitor/src/main/java/com/getcapacitor/Bridge.java
@@ -15,8 +15,6 @@
import android.webkit.ValueCallback;
import android.webkit.WebSettings;
import android.webkit.WebView;
-import com.getcapacitor.plugin.LocalNotifications;
-import com.getcapacitor.plugin.PushNotifications;
import com.getcapacitor.plugin.SplashScreen;
import com.getcapacitor.util.HostMask;
import java.io.File;
@@ -382,8 +380,6 @@ private void initWebView() {
* Register our core Plugin APIs
*/
private void registerAllPlugins() {
- this.registerPlugin(LocalNotifications.class);
- this.registerPlugin(PushNotifications.class);
this.registerPlugin(SplashScreen.class);
this.registerPlugin(com.getcapacitor.plugin.WebView.class);
diff --git a/android/capacitor/src/main/java/com/getcapacitor/CapacitorFirebaseMessagingService.java b/android/capacitor/src/main/java/com/getcapacitor/CapacitorFirebaseMessagingService.java
deleted file mode 100644
index 2e92b68762..0000000000
--- a/android/capacitor/src/main/java/com/getcapacitor/CapacitorFirebaseMessagingService.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.getcapacitor;
-
-import com.getcapacitor.plugin.PushNotifications;
-import com.google.firebase.messaging.FirebaseMessagingService;
-import com.google.firebase.messaging.RemoteMessage;
-
-public class CapacitorFirebaseMessagingService extends FirebaseMessagingService {
-
- @Override
- public void onNewToken(String newToken) {
- super.onNewToken(newToken);
- PushNotifications.onNewToken(newToken);
- }
-
- @Override
- public void onMessageReceived(RemoteMessage remoteMessage) {
- super.onMessageReceived(remoteMessage);
- PushNotifications.sendRemoteMessage(remoteMessage);
- }
-}
diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/LocalNotifications.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/LocalNotifications.java
deleted file mode 100644
index 600b182795..0000000000
--- a/android/capacitor/src/main/java/com/getcapacitor/plugin/LocalNotifications.java
+++ /dev/null
@@ -1,135 +0,0 @@
-package com.getcapacitor.plugin;
-
-import android.content.Intent;
-import com.getcapacitor.JSArray;
-import com.getcapacitor.JSObject;
-import com.getcapacitor.NativePlugin;
-import com.getcapacitor.Plugin;
-import com.getcapacitor.PluginCall;
-import com.getcapacitor.PluginMethod;
-import com.getcapacitor.PluginRequestCodes;
-import com.getcapacitor.plugin.notification.LocalNotification;
-import com.getcapacitor.plugin.notification.LocalNotificationManager;
-import com.getcapacitor.plugin.notification.NotificationAction;
-import com.getcapacitor.plugin.notification.NotificationChannelManager;
-import com.getcapacitor.plugin.notification.NotificationStorage;
-import java.util.List;
-import java.util.Map;
-import org.json.JSONArray;
-
-/**
- * Plugin for scheduling local notifications
- * Plugins allows to create and trigger various types of notifications an specific times
- * Please refer to individual documentation for reference
- */
-@NativePlugin(requestCodes = PluginRequestCodes.NOTIFICATION_OPEN)
-public class LocalNotifications extends Plugin {
-
- private LocalNotificationManager manager;
- private NotificationStorage notificationStorage;
- private NotificationChannelManager notificationChannelManager;
-
- public LocalNotifications() {}
-
- @Override
- public void load() {
- super.load();
- notificationStorage = new NotificationStorage(getContext());
- manager = new LocalNotificationManager(notificationStorage, getActivity(), getContext(), this.bridge.getConfig());
- manager.createNotificationChannel();
- notificationChannelManager = new NotificationChannelManager(getActivity());
- }
-
- @Override
- protected void handleOnNewIntent(Intent data) {
- super.handleOnNewIntent(data);
- if (!Intent.ACTION_MAIN.equals(data.getAction())) {
- return;
- }
- JSObject dataJson = manager.handleNotificationActionPerformed(data, notificationStorage);
- if (dataJson != null) {
- notifyListeners("localNotificationActionPerformed", dataJson, true);
- }
- }
-
- @Override
- protected void handleOnActivityResult(int requestCode, int resultCode, Intent data) {
- super.handleOnActivityResult(requestCode, resultCode, data);
- this.handleOnNewIntent(data);
- }
-
- /**
- * Schedule a notification call from JavaScript
- * Creates local notification in system.
- */
- @PluginMethod
- public void schedule(PluginCall call) {
- List localNotifications = LocalNotification.buildNotificationList(call);
- if (localNotifications == null) {
- return;
- }
- JSONArray ids = manager.schedule(call, localNotifications);
- if (ids != null) {
- notificationStorage.appendNotifications(localNotifications);
- JSObject result = new JSObject();
- JSArray jsArray = new JSArray();
- for (int i = 0; i < ids.length(); i++) {
- try {
- JSObject notification = new JSObject().put("id", ids.getString(i));
- jsArray.put(notification);
- } catch (Exception ex) {}
- }
- result.put("notifications", jsArray);
- call.success(result);
- }
- }
-
- @PluginMethod
- public void requestPermission(PluginCall call) {
- JSObject result = new JSObject();
- result.put("granted", true);
- call.success(result);
- }
-
- @PluginMethod
- public void cancel(PluginCall call) {
- manager.cancel(call);
- }
-
- @PluginMethod
- public void getPending(PluginCall call) {
- List ids = notificationStorage.getSavedNotificationIds();
- JSObject result = LocalNotification.buildLocalNotificationPendingList(ids);
- call.success(result);
- }
-
- @PluginMethod
- public void registerActionTypes(PluginCall call) {
- JSArray types = call.getArray("types");
- Map typesArray = NotificationAction.buildTypes(types);
- notificationStorage.writeActionGroup(typesArray);
- call.success();
- }
-
- @PluginMethod
- public void areEnabled(PluginCall call) {
- JSObject data = new JSObject();
- data.put("value", manager.areNotificationsEnabled());
- call.success(data);
- }
-
- @PluginMethod
- public void createChannel(PluginCall call) {
- notificationChannelManager.createChannel(call);
- }
-
- @PluginMethod
- public void deleteChannel(PluginCall call) {
- notificationChannelManager.deleteChannel(call);
- }
-
- @PluginMethod
- public void listChannels(PluginCall call) {
- notificationChannelManager.listChannels(call);
- }
-}
diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/PushNotifications.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/PushNotifications.java
deleted file mode 100644
index 05500616e6..0000000000
--- a/android/capacitor/src/main/java/com/getcapacitor/plugin/PushNotifications.java
+++ /dev/null
@@ -1,239 +0,0 @@
-package com.getcapacitor.plugin;
-
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Bundle;
-import android.service.notification.StatusBarNotification;
-import com.getcapacitor.Bridge;
-import com.getcapacitor.JSArray;
-import com.getcapacitor.JSObject;
-import com.getcapacitor.NativePlugin;
-import com.getcapacitor.Plugin;
-import com.getcapacitor.PluginCall;
-import com.getcapacitor.PluginHandle;
-import com.getcapacitor.PluginMethod;
-import com.getcapacitor.plugin.notification.NotificationChannelManager;
-import com.google.firebase.iid.FirebaseInstanceId;
-import com.google.firebase.messaging.FirebaseMessaging;
-import com.google.firebase.messaging.RemoteMessage;
-import java.util.ArrayList;
-import java.util.List;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-@NativePlugin
-public class PushNotifications extends Plugin {
-
- public static Bridge staticBridge = null;
- public static RemoteMessage lastMessage = null;
- public NotificationManager notificationManager;
- private NotificationChannelManager notificationChannelManager;
-
- private static final String EVENT_TOKEN_CHANGE = "registration";
- private static final String EVENT_TOKEN_ERROR = "registrationError";
-
- @Override
- public void load() {
- notificationManager = (NotificationManager) getActivity().getSystemService(Context.NOTIFICATION_SERVICE);
- staticBridge = this.bridge;
- if (lastMessage != null) {
- fireNotification(lastMessage);
- lastMessage = null;
- }
- notificationChannelManager = new NotificationChannelManager(getActivity(), notificationManager);
- }
-
- @Override
- protected void handleOnNewIntent(Intent data) {
- super.handleOnNewIntent(data);
- Bundle bundle = data.getExtras();
- if (bundle != null && bundle.containsKey("google.message_id")) {
- JSObject notificationJson = new JSObject();
- JSObject dataObject = new JSObject();
- for (String key : bundle.keySet()) {
- if (key.equals("google.message_id")) {
- notificationJson.put("id", bundle.get(key));
- } else {
- Object value = bundle.get(key);
- String valueStr = (value != null) ? value.toString() : null;
- dataObject.put(key, valueStr);
- }
- }
- notificationJson.put("data", dataObject);
- JSObject actionJson = new JSObject();
- actionJson.put("actionId", "tap");
- actionJson.put("notification", notificationJson);
- notifyListeners("pushNotificationActionPerformed", actionJson, true);
- }
- }
-
- @PluginMethod
- public void register(PluginCall call) {
- FirebaseMessaging.getInstance().setAutoInitEnabled(true);
- FirebaseInstanceId
- .getInstance()
- .getInstanceId()
- .addOnSuccessListener(getActivity(), instanceIdResult -> sendToken(instanceIdResult.getToken()));
- FirebaseInstanceId.getInstance().getInstanceId().addOnFailureListener(e -> sendError(e.getLocalizedMessage()));
- call.success();
- }
-
- @PluginMethod
- public void requestPermission(PluginCall call) {
- JSObject result = new JSObject();
- result.put("granted", true);
- call.success(result);
- }
-
- @PluginMethod
- public void getDeliveredNotifications(PluginCall call) {
- JSArray notifications = new JSArray();
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- StatusBarNotification[] activeNotifications = notificationManager.getActiveNotifications();
-
- for (StatusBarNotification notif : activeNotifications) {
- JSObject jsNotif = new JSObject();
-
- jsNotif.put("id", notif.getId());
-
- Notification notification = notif.getNotification();
- if (notification != null) {
- jsNotif.put("title", notification.extras.getCharSequence(Notification.EXTRA_TITLE));
- jsNotif.put("body", notification.extras.getCharSequence(Notification.EXTRA_TEXT));
- jsNotif.put("group", notification.getGroup());
- jsNotif.put("groupSummary", 0 != (notification.flags & Notification.FLAG_GROUP_SUMMARY));
-
- JSObject extras = new JSObject();
-
- for (String key : notification.extras.keySet()) {
- extras.put(key, notification.extras.get(key));
- }
-
- jsNotif.put("data", extras);
- }
-
- notifications.put(jsNotif);
- }
- }
-
- JSObject result = new JSObject();
- result.put("notifications", notifications);
- call.resolve(result);
- }
-
- @PluginMethod
- public void removeDeliveredNotifications(PluginCall call) {
- JSArray notifications = call.getArray("notifications");
-
- List ids = new ArrayList<>();
- try {
- for (Object o : notifications.toList()) {
- if (o instanceof JSONObject) {
- JSObject notif = JSObject.fromJSONObject((JSONObject) o);
- Integer id = notif.getInteger("id");
- ids.add(id);
- } else {
- call.reject("Expected notifications to be a list of notification objects");
- }
- }
- } catch (JSONException e) {
- call.reject(e.getMessage());
- }
-
- for (int id : ids) {
- notificationManager.cancel(id);
- }
-
- call.resolve();
- }
-
- @PluginMethod
- public void removeAllDeliveredNotifications(PluginCall call) {
- notificationManager.cancelAll();
- call.success();
- }
-
- @PluginMethod
- public void createChannel(PluginCall call) {
- notificationChannelManager.createChannel(call);
- }
-
- @PluginMethod
- public void deleteChannel(PluginCall call) {
- notificationChannelManager.deleteChannel(call);
- }
-
- @PluginMethod
- public void listChannels(PluginCall call) {
- notificationChannelManager.listChannels(call);
- }
-
- public void sendToken(String token) {
- JSObject data = new JSObject();
- data.put("value", token);
- notifyListeners(EVENT_TOKEN_CHANGE, data, true);
- }
-
- public void sendError(String error) {
- JSObject data = new JSObject();
- data.put("error", error);
- notifyListeners(EVENT_TOKEN_ERROR, data, true);
- }
-
- public static void onNewToken(String newToken) {
- PushNotifications pushPlugin = PushNotifications.getPushNotificationsInstance();
- if (pushPlugin != null) {
- pushPlugin.sendToken(newToken);
- }
- }
-
- public static void sendRemoteMessage(RemoteMessage remoteMessage) {
- PushNotifications pushPlugin = PushNotifications.getPushNotificationsInstance();
- if (pushPlugin != null) {
- pushPlugin.fireNotification(remoteMessage);
- } else {
- lastMessage = remoteMessage;
- }
- }
-
- public void fireNotification(RemoteMessage remoteMessage) {
- JSObject remoteMessageData = new JSObject();
-
- JSObject data = new JSObject();
- remoteMessageData.put("id", remoteMessage.getMessageId());
- for (String key : remoteMessage.getData().keySet()) {
- Object value = remoteMessage.getData().get(key);
- data.put(key, value);
- }
- remoteMessageData.put("data", data);
-
- RemoteMessage.Notification notification = remoteMessage.getNotification();
- if (notification != null) {
- remoteMessageData.put("title", notification.getTitle());
- remoteMessageData.put("body", notification.getBody());
- remoteMessageData.put("click_action", notification.getClickAction());
-
- Uri link = notification.getLink();
- if (link != null) {
- remoteMessageData.put("link", link.toString());
- }
- }
-
- notifyListeners("pushNotificationReceived", remoteMessageData, true);
- }
-
- public static PushNotifications getPushNotificationsInstance() {
- if (staticBridge != null && staticBridge.getWebView() != null) {
- PluginHandle handle = staticBridge.getPlugin("PushNotifications");
- if (handle == null) {
- return null;
- }
- return (PushNotifications) handle.getInstance();
- }
- return null;
- }
-}
diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/DateMatch.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/DateMatch.java
deleted file mode 100644
index 15931de460..0000000000
--- a/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/DateMatch.java
+++ /dev/null
@@ -1,213 +0,0 @@
-package com.getcapacitor.plugin.notification;
-
-import java.util.Calendar;
-import java.util.Date;
-
-/**
- * Class that holds logic for on triggers
- * (Specific time)
- */
-public class DateMatch {
-
- private static final String separator = " ";
-
- private Integer year;
- private Integer month;
- private Integer day;
- private Integer hour;
- private Integer minute;
-
- // Unit used to save the last used unit for a trigger.
- // One of the Calendar constants values
- private Integer unit = -1;
-
- public DateMatch() {}
-
- public Integer getYear() {
- return year;
- }
-
- public void setYear(Integer year) {
- this.year = year;
- }
-
- public Integer getMonth() {
- return month;
- }
-
- public void setMonth(Integer month) {
- this.month = month;
- }
-
- public Integer getDay() {
- return day;
- }
-
- public void setDay(Integer day) {
- this.day = day;
- }
-
- public Integer getHour() {
- return hour;
- }
-
- public void setHour(Integer hour) {
- this.hour = hour;
- }
-
- public Integer getMinute() {
- return minute;
- }
-
- public void setMinute(Integer minute) {
- this.minute = minute;
- }
-
- /**
- * Gets a calendar instance pointing to the specified date.
- *
- * @param date The date to point.
- */
- private Calendar buildCalendar(Date date) {
- Calendar cal = Calendar.getInstance();
- cal.setTime(date);
- cal.set(Calendar.MILLISECOND, 0);
- cal.set(Calendar.SECOND, 0);
- return cal;
- }
-
- /**
- * Calculates next trigger date for
- *
- * @param date base date used to calculate trigger
- * @return next trigger timestamp
- */
- public long nextTrigger(Date date) {
- Calendar current = buildCalendar(date);
- Calendar next = buildNextTriggerTime(date);
- return postponeTriggerIfNeeded(current, next);
- }
-
- /**
- * Postpone trigger if first schedule matches the past
- */
- private long postponeTriggerIfNeeded(Calendar current, Calendar next) {
- if (next.getTimeInMillis() <= current.getTimeInMillis() && unit != -1) {
- Integer incrementUnit = -1;
- if (unit == Calendar.YEAR || unit == Calendar.MONTH) {
- incrementUnit = Calendar.YEAR;
- } else if (unit == Calendar.DAY_OF_MONTH) {
- incrementUnit = Calendar.MONTH;
- } else if (unit == Calendar.HOUR_OF_DAY) {
- incrementUnit = Calendar.DAY_OF_MONTH;
- } else if (unit == Calendar.MINUTE) {
- incrementUnit = Calendar.HOUR_OF_DAY;
- }
-
- if (incrementUnit != -1) {
- next.set(incrementUnit, next.get(incrementUnit) + 1);
- }
- }
- return next.getTimeInMillis();
- }
-
- private Calendar buildNextTriggerTime(Date date) {
- Calendar next = buildCalendar(date);
- if (year != null) {
- next.set(Calendar.YEAR, year);
- if (unit == -1) unit = Calendar.YEAR;
- }
- if (month != null) {
- next.set(Calendar.MONTH, month);
- if (unit == -1) unit = Calendar.MONTH;
- }
- if (day != null) {
- next.set(Calendar.DAY_OF_MONTH, day);
- if (unit == -1) unit = Calendar.DAY_OF_MONTH;
- }
- if (hour != null) {
- next.set(Calendar.HOUR_OF_DAY, hour);
- if (unit == -1) unit = Calendar.HOUR_OF_DAY;
- }
- if (minute != null) {
- next.set(Calendar.MINUTE, minute);
- if (unit == -1) unit = Calendar.MINUTE;
- }
- return next;
- }
-
- @Override
- public String toString() {
- return "DateMatch{" + "year=" + year + ", month=" + month + ", day=" + day + ", hour=" + hour + ", minute=" + minute + '}';
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- DateMatch dateMatch = (DateMatch) o;
-
- if (year != null ? !year.equals(dateMatch.year) : dateMatch.year != null) return false;
- if (month != null ? !month.equals(dateMatch.month) : dateMatch.month != null) return false;
- if (day != null ? !day.equals(dateMatch.day) : dateMatch.day != null) return false;
- if (hour != null ? !hour.equals(dateMatch.hour) : dateMatch.hour != null) return false;
- return minute != null ? minute.equals(dateMatch.minute) : dateMatch.minute == null;
- }
-
- @Override
- public int hashCode() {
- int result = year != null ? year.hashCode() : 0;
- result = 31 * result + (month != null ? month.hashCode() : 0);
- result = 31 * result + (day != null ? day.hashCode() : 0);
- result = 31 * result + (hour != null ? hour.hashCode() : 0);
- result = 31 * result + (minute != null ? minute.hashCode() : 0);
- return result;
- }
-
- /**
- * Transform DateMatch object to CronString
- *
- * @return
- */
- public String toMatchString() {
- String matchString = year + separator + month + separator + day + separator + hour + separator + minute + separator + unit;
- return matchString.replace("null", "*");
- }
-
- /**
- * Create DateMatch object from stored string
- *
- * @param matchString
- * @return
- */
- public static DateMatch fromMatchString(String matchString) {
- DateMatch date = new DateMatch();
- String[] split = matchString.split(separator);
- if (split != null && split.length == 6) {
- date.setYear(getValueFromCronElement(split[0]));
- date.setMonth(getValueFromCronElement(split[1]));
- date.setDay(getValueFromCronElement(split[2]));
- date.setHour(getValueFromCronElement(split[3]));
- date.setMinute(getValueFromCronElement(split[4]));
- date.setUnit(getValueFromCronElement(split[5]));
- }
- return date;
- }
-
- public static Integer getValueFromCronElement(String token) {
- try {
- return Integer.parseInt(token);
- } catch (NumberFormatException e) {
- return null;
- }
- }
-
- public Integer getUnit() {
- return unit;
- }
-
- public void setUnit(Integer unit) {
- this.unit = unit;
- }
-}
diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/LocalNotification.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/LocalNotification.java
deleted file mode 100644
index 7438845e73..0000000000
--- a/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/LocalNotification.java
+++ /dev/null
@@ -1,383 +0,0 @@
-package com.getcapacitor.plugin.notification;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import com.getcapacitor.JSArray;
-import com.getcapacitor.JSObject;
-import com.getcapacitor.Logger;
-import com.getcapacitor.PluginCall;
-import com.getcapacitor.plugin.util.AssetUtil;
-import java.text.ParseException;
-import java.util.ArrayList;
-import java.util.List;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-/**
- * Local notification object mapped from json plugin
- */
-public class LocalNotification {
-
- private String title;
- private String body;
- private Integer id;
- private String sound;
- private String smallIcon;
- private String iconColor;
- private String actionTypeId;
- private String group;
- private boolean groupSummary;
- private boolean ongoing;
- private boolean autoCancel;
- private JSObject extra;
- private List attachments;
- private LocalNotificationSchedule schedule;
- private String channelId;
-
- private String source;
-
- public String getTitle() {
- return title;
- }
-
- public void setTitle(String title) {
- this.title = title;
- }
-
- public String getBody() {
- return body;
- }
-
- public void setBody(String body) {
- this.body = body;
- }
-
- public LocalNotificationSchedule getSchedule() {
- return schedule;
- }
-
- public void setSchedule(LocalNotificationSchedule schedule) {
- this.schedule = schedule;
- }
-
- public String getSound(Context context, int defaultSound) {
- String soundPath = null;
- int resId = AssetUtil.RESOURCE_ID_ZERO_VALUE;
- String name = AssetUtil.getResourceBaseName(sound);
- if (name != null) {
- resId = AssetUtil.getResourceID(context, name, "raw");
- }
- if (resId == AssetUtil.RESOURCE_ID_ZERO_VALUE) {
- resId = defaultSound;
- }
- if (resId != AssetUtil.RESOURCE_ID_ZERO_VALUE) {
- soundPath = ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + context.getPackageName() + "/" + resId;
- }
- return soundPath;
- }
-
- public void setSound(String sound) {
- this.sound = sound;
- }
-
- public void setSmallIcon(String smallIcon) {
- this.smallIcon = AssetUtil.getResourceBaseName(smallIcon);
- }
-
- public String getIconColor(String globalColor) {
- // use the one defined local before trying for a globally defined color
- if (iconColor != null) {
- return iconColor;
- }
-
- return globalColor;
- }
-
- public void setIconColor(String iconColor) {
- this.iconColor = iconColor;
- }
-
- public List getAttachments() {
- return attachments;
- }
-
- public void setAttachments(List attachments) {
- this.attachments = attachments;
- }
-
- public String getActionTypeId() {
- return actionTypeId;
- }
-
- public void setActionTypeId(String actionTypeId) {
- this.actionTypeId = actionTypeId;
- }
-
- public String getGroup() {
- return group;
- }
-
- public void setGroup(String group) {
- this.group = group;
- }
-
- public JSObject getExtra() {
- return extra;
- }
-
- public void setExtra(JSObject extra) {
- this.extra = extra;
- }
-
- public Integer getId() {
- return id;
- }
-
- public void setId(Integer id) {
- this.id = id;
- }
-
- public boolean isGroupSummary() {
- return groupSummary;
- }
-
- public void setGroupSummary(boolean groupSummary) {
- this.groupSummary = groupSummary;
- }
-
- public boolean isOngoing() {
- return ongoing;
- }
-
- public void setOngoing(boolean ongoing) {
- this.ongoing = ongoing;
- }
-
- public boolean isAutoCancel() {
- return autoCancel;
- }
-
- public void setAutoCancel(boolean autoCancel) {
- this.autoCancel = autoCancel;
- }
-
- public String getChannelId() {
- return channelId;
- }
-
- public void setChannelId(String channelId) {
- this.channelId = channelId;
- }
-
- /**
- * Build list of the notifications from remote plugin call
- */
- public static List buildNotificationList(PluginCall call) {
- JSArray notificationArray = call.getArray("notifications");
- if (notificationArray == null) {
- call.error("Must provide notifications array as notifications option");
- return null;
- }
- List resultLocalNotifications = new ArrayList<>(notificationArray.length());
- List notificationsJson;
- try {
- notificationsJson = notificationArray.toList();
- } catch (JSONException e) {
- call.error("Provided notification format is invalid");
- return null;
- }
-
- for (JSONObject jsonNotification : notificationsJson) {
- JSObject notification = null;
- try {
- notification = JSObject.fromJSONObject(jsonNotification);
- } catch (JSONException e) {
- call.error("Invalid JSON object sent to NotificationPlugin", e);
- return null;
- }
-
- try {
- LocalNotification activeLocalNotification = buildNotificationFromJSObject(notification);
- resultLocalNotifications.add(activeLocalNotification);
- } catch (ParseException e) {
- call.error("Invalid date format sent to Notification plugin", e);
- return null;
- }
- }
- return resultLocalNotifications;
- }
-
- public static LocalNotification buildNotificationFromJSObject(JSObject jsonObject) throws ParseException {
- LocalNotification localNotification = new LocalNotification();
- localNotification.setSource(jsonObject.toString());
- localNotification.setId(jsonObject.getInteger("id"));
- localNotification.setBody(jsonObject.getString("body"));
- localNotification.setActionTypeId(jsonObject.getString("actionTypeId"));
- localNotification.setGroup(jsonObject.getString("group"));
- localNotification.setSound(jsonObject.getString("sound"));
- localNotification.setTitle(jsonObject.getString("title"));
- localNotification.setSmallIcon(jsonObject.getString("smallIcon"));
- localNotification.setIconColor(jsonObject.getString("iconColor"));
- localNotification.setAttachments(LocalNotificationAttachment.getAttachments(jsonObject));
- localNotification.setGroupSummary(jsonObject.getBoolean("groupSummary", false));
- localNotification.setChannelId(jsonObject.getString("channelId"));
- localNotification.setSchedule(new LocalNotificationSchedule(jsonObject));
- localNotification.setExtra(jsonObject.getJSObject("extra"));
- localNotification.setOngoing(jsonObject.getBoolean("ongoing", false));
- localNotification.setAutoCancel(jsonObject.getBoolean("autoCancel", true));
-
- return localNotification;
- }
-
- public static List getLocalNotificationPendingList(PluginCall call) {
- List notifications = null;
- try {
- notifications = call.getArray("notifications").toList();
- } catch (JSONException e) {}
- if (notifications == null || notifications.size() == 0) {
- call.error("Must provide notifications array as notifications option");
- return null;
- }
- List notificationsList = new ArrayList<>(notifications.size());
- for (JSONObject notificationToCancel : notifications) {
- try {
- notificationsList.add(notificationToCancel.getInt("id"));
- } catch (JSONException e) {}
- }
- return notificationsList;
- }
-
- public static JSObject buildLocalNotificationPendingList(List ids) {
- JSObject result = new JSObject();
- JSArray jsArray = new JSArray();
- for (String id : ids) {
- JSObject notification = new JSObject();
- notification.put("id", id);
- jsArray.put(notification);
- }
- result.put("notifications", jsArray);
- return result;
- }
-
- public int getSmallIcon(Context context, int defaultIcon) {
- int resId = AssetUtil.RESOURCE_ID_ZERO_VALUE;
-
- if (smallIcon != null) {
- resId = AssetUtil.getResourceID(context, smallIcon, "drawable");
- }
-
- if (resId == AssetUtil.RESOURCE_ID_ZERO_VALUE) {
- resId = defaultIcon;
- }
-
- return resId;
- }
-
- public boolean isScheduled() {
- return (
- this.schedule != null && (this.schedule.getOn() != null || this.schedule.getAt() != null || this.schedule.getEvery() != null)
- );
- }
-
- @Override
- public String toString() {
- return (
- "LocalNotification{" +
- "title='" +
- title +
- '\'' +
- ", body='" +
- body +
- '\'' +
- ", id=" +
- id +
- ", sound='" +
- sound +
- '\'' +
- ", smallIcon='" +
- smallIcon +
- '\'' +
- ", iconColor='" +
- iconColor +
- '\'' +
- ", actionTypeId='" +
- actionTypeId +
- '\'' +
- ", group='" +
- group +
- '\'' +
- ", extra=" +
- extra +
- ", attachments=" +
- attachments +
- ", schedule=" +
- schedule +
- ", groupSummary=" +
- groupSummary +
- ", ongoing=" +
- ongoing +
- ", autoCancel=" +
- autoCancel +
- '}'
- );
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- LocalNotification that = (LocalNotification) o;
-
- if (title != null ? !title.equals(that.title) : that.title != null) return false;
- if (body != null ? !body.equals(that.body) : that.body != null) return false;
- if (id != null ? !id.equals(that.id) : that.id != null) return false;
- if (sound != null ? !sound.equals(that.sound) : that.sound != null) return false;
- if (smallIcon != null ? !smallIcon.equals(that.smallIcon) : that.smallIcon != null) return false;
- if (iconColor != null ? !iconColor.equals(that.iconColor) : that.iconColor != null) return false;
- if (actionTypeId != null ? !actionTypeId.equals(that.actionTypeId) : that.actionTypeId != null) return false;
- if (group != null ? !group.equals(that.group) : that.group != null) return false;
- if (extra != null ? !extra.equals(that.extra) : that.extra != null) return false;
- if (attachments != null ? !attachments.equals(that.attachments) : that.attachments != null) return false;
- if (groupSummary != that.groupSummary) return false;
- if (ongoing != that.ongoing) return false;
- if (autoCancel != that.autoCancel) return false;
- return schedule != null ? schedule.equals(that.schedule) : that.schedule == null;
- }
-
- @Override
- public int hashCode() {
- int result = title != null ? title.hashCode() : 0;
- result = 31 * result + (body != null ? body.hashCode() : 0);
- result = 31 * result + (id != null ? id.hashCode() : 0);
- result = 31 * result + (sound != null ? sound.hashCode() : 0);
- result = 31 * result + (smallIcon != null ? smallIcon.hashCode() : 0);
- result = 31 * result + (iconColor != null ? iconColor.hashCode() : 0);
- result = 31 * result + (actionTypeId != null ? actionTypeId.hashCode() : 0);
- result = 31 * result + (group != null ? group.hashCode() : 0);
- result = 31 * result + Boolean.hashCode(groupSummary);
- result = 31 * result + Boolean.hashCode(ongoing);
- result = 31 * result + Boolean.hashCode(autoCancel);
- result = 31 * result + (extra != null ? extra.hashCode() : 0);
- result = 31 * result + (attachments != null ? attachments.hashCode() : 0);
- result = 31 * result + (schedule != null ? schedule.hashCode() : 0);
- return result;
- }
-
- public void setExtraFromString(String extraFromString) {
- try {
- JSONObject jsonObject = new JSONObject(extraFromString);
- this.extra = JSObject.fromJSONObject(jsonObject);
- } catch (JSONException e) {
- Logger.error(Logger.tags("LN"), "Cannot rebuild extra data", e);
- }
- }
-
- public String getSource() {
- return source;
- }
-
- public void setSource(String source) {
- this.source = source;
- }
-}
diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/LocalNotificationAttachment.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/LocalNotificationAttachment.java
deleted file mode 100644
index 2e088d7ac8..0000000000
--- a/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/LocalNotificationAttachment.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.getcapacitor.plugin.notification;
-
-import com.getcapacitor.JSObject;
-import java.util.ArrayList;
-import java.util.List;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-public class LocalNotificationAttachment {
-
- private String id;
- private String url;
- private JSONObject options;
-
- public String getId() {
- return id;
- }
-
- public void setId(String id) {
- this.id = id;
- }
-
- public String getUrl() {
- return url;
- }
-
- public void setUrl(String url) {
- this.url = url;
- }
-
- public JSONObject getOptions() {
- return options;
- }
-
- public void setOptions(JSONObject options) {
- this.options = options;
- }
-
- public static List getAttachments(JSObject notification) {
- List attachmentsList = new ArrayList<>();
- JSONArray attachments = null;
- try {
- attachments = notification.getJSONArray("attachments");
- } catch (Exception e) {}
- if (attachments != null) {
- for (int i = 0; i < attachments.length(); i++) {
- LocalNotificationAttachment newAttachment = new LocalNotificationAttachment();
- JSONObject jsonObject = null;
- try {
- jsonObject = attachments.getJSONObject(i);
- } catch (JSONException e) {}
- if (jsonObject != null) {
- JSObject jsObject = null;
- try {
- jsObject = JSObject.fromJSONObject(jsonObject);
- } catch (JSONException e) {}
- newAttachment.setId(jsObject.getString("id"));
- newAttachment.setUrl(jsObject.getString("url"));
- try {
- newAttachment.setOptions(jsObject.getJSONObject("options"));
- } catch (JSONException e) {}
- attachmentsList.add(newAttachment);
- }
- }
- }
-
- return attachmentsList;
- }
-}
diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/LocalNotificationManager.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/LocalNotificationManager.java
deleted file mode 100644
index 75771a43f8..0000000000
--- a/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/LocalNotificationManager.java
+++ /dev/null
@@ -1,427 +0,0 @@
-package com.getcapacitor.plugin.notification;
-
-import android.app.Activity;
-import android.app.AlarmManager;
-import android.app.Notification;
-import android.app.NotificationChannel;
-import android.app.PendingIntent;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.Color;
-import android.media.AudioAttributes;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Bundle;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.core.app.NotificationCompat;
-import androidx.core.app.NotificationManagerCompat;
-import androidx.core.app.RemoteInput;
-import com.getcapacitor.CapConfig;
-import com.getcapacitor.JSObject;
-import com.getcapacitor.Logger;
-import com.getcapacitor.PluginCall;
-import com.getcapacitor.android.R;
-import com.getcapacitor.plugin.util.AssetUtil;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.List;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-/**
- * Contains implementations for all notification actions
- */
-public class LocalNotificationManager {
-
- private static final String CONFIG_KEY_PREFIX = "plugins.LocalNotifications.";
- private static int defaultSoundID = AssetUtil.RESOURCE_ID_ZERO_VALUE;
- private static int defaultSmallIconID = AssetUtil.RESOURCE_ID_ZERO_VALUE;
- // Action constants
- public static final String NOTIFICATION_INTENT_KEY = "LocalNotificationId";
- public static final String NOTIFICATION_OBJ_INTENT_KEY = "LocalNotficationObject";
- public static final String ACTION_INTENT_KEY = "LocalNotificationUserAction";
- public static final String NOTIFICATION_IS_REMOVABLE_KEY = "LocalNotificationRepeating";
- public static final String REMOTE_INPUT_KEY = "LocalNotificationRemoteInput";
-
- public static final String DEFAULT_NOTIFICATION_CHANNEL_ID = "default";
- private static final String DEFAULT_PRESS_ACTION = "tap";
-
- private Context context;
- private Activity activity;
- private NotificationStorage storage;
- private CapConfig config;
-
- public LocalNotificationManager(NotificationStorage notificationStorage, Activity activity, Context context, CapConfig config) {
- storage = notificationStorage;
- this.activity = activity;
- this.context = context;
- this.config = config;
- }
-
- /**
- * Method extecuted when notification is launched by user from the notification bar.
- */
- public JSObject handleNotificationActionPerformed(Intent data, NotificationStorage notificationStorage) {
- Logger.debug(Logger.tags("LN"), "LocalNotification received: " + data.getDataString());
- int notificationId = data.getIntExtra(LocalNotificationManager.NOTIFICATION_INTENT_KEY, Integer.MIN_VALUE);
- if (notificationId == Integer.MIN_VALUE) {
- Logger.debug(Logger.tags("LN"), "Activity started without notification attached");
- return null;
- }
- boolean isRemovable = data.getBooleanExtra(LocalNotificationManager.NOTIFICATION_IS_REMOVABLE_KEY, true);
- if (isRemovable) {
- notificationStorage.deleteNotification(Integer.toString(notificationId));
- }
- JSObject dataJson = new JSObject();
-
- Bundle results = RemoteInput.getResultsFromIntent(data);
- if (results != null) {
- CharSequence input = results.getCharSequence(LocalNotificationManager.REMOTE_INPUT_KEY);
- dataJson.put("inputValue", input.toString());
- }
- String menuAction = data.getStringExtra(LocalNotificationManager.ACTION_INTENT_KEY);
-
- dismissVisibleNotification(notificationId);
-
- dataJson.put("actionId", menuAction);
- JSONObject request = null;
- try {
- String notificationJsonString = data.getStringExtra(LocalNotificationManager.NOTIFICATION_OBJ_INTENT_KEY);
- if (notificationJsonString != null) {
- request = new JSObject(notificationJsonString);
- }
- } catch (JSONException e) {}
- dataJson.put("notification", request);
- return dataJson;
- }
-
- /**
- * Create notification channel
- */
- public void createNotificationChannel() {
- // Create the NotificationChannel, but only on API 26+ because
- // the NotificationChannel class is new and not in the support library
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- CharSequence name = "Default";
- String description = "Default";
- int importance = android.app.NotificationManager.IMPORTANCE_DEFAULT;
- NotificationChannel channel = new NotificationChannel(DEFAULT_NOTIFICATION_CHANNEL_ID, name, importance);
- channel.setDescription(description);
- AudioAttributes audioAttributes = new AudioAttributes.Builder()
- .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
- .setUsage(AudioAttributes.USAGE_ALARM)
- .build();
- Uri soundUri = this.getDefaultSoundUrl(context);
- if (soundUri != null) {
- channel.setSound(soundUri, audioAttributes);
- }
- // Register the channel with the system; you can't change the importance
- // or other notification behaviors after this
- android.app.NotificationManager notificationManager = context.getSystemService(android.app.NotificationManager.class);
- notificationManager.createNotificationChannel(channel);
- }
- }
-
- @Nullable
- public JSONArray schedule(PluginCall call, List localNotifications) {
- JSONArray ids = new JSONArray();
- NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
-
- boolean notificationsEnabled = notificationManager.areNotificationsEnabled();
- if (!notificationsEnabled) {
- if (call != null) {
- call.error("Notifications not enabled on this device");
- }
- return null;
- }
- for (LocalNotification localNotification : localNotifications) {
- Integer id = localNotification.getId();
- if (localNotification.getId() == null) {
- if (call != null) {
- call.error("LocalNotification missing identifier");
- }
- return null;
- }
- dismissVisibleNotification(id);
- cancelTimerForNotification(id);
- buildNotification(notificationManager, localNotification, call);
- ids.put(id);
- }
- return ids;
- }
-
- // TODO Progressbar support
- // TODO System categories (DO_NOT_DISTURB etc.)
- // TODO control visibility by flag Notification.VISIBILITY_PRIVATE
- // TODO Group notifications (setGroup, setGroupSummary, setNumber)
- // TODO use NotificationCompat.MessagingStyle for latest API
- // TODO expandable notification NotificationCompat.MessagingStyle
- // TODO media style notification support NotificationCompat.MediaStyle
- // TODO custom small/large icons
- private void buildNotification(NotificationManagerCompat notificationManager, LocalNotification localNotification, PluginCall call) {
- String channelId = DEFAULT_NOTIFICATION_CHANNEL_ID;
- if (localNotification.getChannelId() != null) {
- channelId = localNotification.getChannelId();
- }
- NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this.context, channelId)
- .setContentTitle(localNotification.getTitle())
- .setContentText(localNotification.getBody())
- .setAutoCancel(localNotification.isAutoCancel())
- .setOngoing(localNotification.isOngoing())
- .setPriority(NotificationCompat.PRIORITY_DEFAULT)
- .setGroupSummary(localNotification.isGroupSummary());
-
- // support multiline text
- mBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(localNotification.getBody()));
-
- String sound = localNotification.getSound(context, getDefaultSound(context));
- if (sound != null) {
- Uri soundUri = Uri.parse(sound);
- // Grant permission to use sound
- context.grantUriPermission("com.android.systemui", soundUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
- mBuilder.setSound(soundUri);
- mBuilder.setDefaults(Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS);
- } else {
- mBuilder.setDefaults(Notification.DEFAULT_ALL);
- }
-
- String group = localNotification.getGroup();
- if (group != null) {
- mBuilder.setGroup(group);
- }
-
- // make sure scheduled time is shown instead of display time
- if (localNotification.isScheduled() && localNotification.getSchedule().getAt() != null) {
- mBuilder.setWhen(localNotification.getSchedule().getAt().getTime()).setShowWhen(true);
- }
-
- mBuilder.setVisibility(NotificationCompat.VISIBILITY_PRIVATE);
- mBuilder.setOnlyAlertOnce(true);
-
- mBuilder.setSmallIcon(localNotification.getSmallIcon(context, getDefaultSmallIcon(context)));
-
- String iconColor = localNotification.getIconColor(config.getString(CONFIG_KEY_PREFIX + "iconColor"));
- if (iconColor != null) {
- try {
- mBuilder.setColor(Color.parseColor(iconColor));
- } catch (IllegalArgumentException ex) {
- if (call != null) {
- call.error("Invalid color provided. Must be a hex string (ex: #ff0000");
- }
- return;
- }
- }
-
- createActionIntents(localNotification, mBuilder);
- // notificationId is a unique int for each localNotification that you must define
- Notification buildNotification = mBuilder.build();
- if (localNotification.isScheduled()) {
- triggerScheduledNotification(buildNotification, localNotification);
- } else {
- notificationManager.notify(localNotification.getId(), buildNotification);
- }
- }
-
- // Create intents for open/dissmis actions
- private void createActionIntents(LocalNotification localNotification, NotificationCompat.Builder mBuilder) {
- // Open intent
- Intent intent = buildIntent(localNotification, DEFAULT_PRESS_ACTION);
-
- PendingIntent pendingIntent = PendingIntent.getActivity(
- context,
- localNotification.getId(),
- intent,
- PendingIntent.FLAG_CANCEL_CURRENT
- );
- mBuilder.setContentIntent(pendingIntent);
-
- // Build action types
- String actionTypeId = localNotification.getActionTypeId();
- if (actionTypeId != null) {
- NotificationAction[] actionGroup = storage.getActionGroup(actionTypeId);
- for (NotificationAction notificationAction : actionGroup) {
- // TODO Add custom icons to actions
- Intent actionIntent = buildIntent(localNotification, notificationAction.getId());
- PendingIntent actionPendingIntent = PendingIntent.getActivity(
- context,
- localNotification.getId() + notificationAction.getId().hashCode(),
- actionIntent,
- PendingIntent.FLAG_CANCEL_CURRENT
- );
- NotificationCompat.Action.Builder actionBuilder = new NotificationCompat.Action.Builder(
- R.drawable.ic_transparent,
- notificationAction.getTitle(),
- actionPendingIntent
- );
- if (notificationAction.isInput()) {
- RemoteInput remoteInput = new RemoteInput.Builder(REMOTE_INPUT_KEY).setLabel(notificationAction.getTitle()).build();
- actionBuilder.addRemoteInput(remoteInput);
- }
- mBuilder.addAction(actionBuilder.build());
- }
- }
-
- // Dismiss intent
- Intent dissmissIntent = new Intent(context, NotificationDismissReceiver.class);
- dissmissIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
- dissmissIntent.putExtra(NOTIFICATION_INTENT_KEY, localNotification.getId());
- dissmissIntent.putExtra(ACTION_INTENT_KEY, "dismiss");
- LocalNotificationSchedule schedule = localNotification.getSchedule();
- dissmissIntent.putExtra(NOTIFICATION_IS_REMOVABLE_KEY, schedule == null || schedule.isRemovable());
- PendingIntent deleteIntent = PendingIntent.getBroadcast(context, localNotification.getId(), dissmissIntent, 0);
- mBuilder.setDeleteIntent(deleteIntent);
- }
-
- @NonNull
- private Intent buildIntent(LocalNotification localNotification, String action) {
- Intent intent;
- if (activity != null) {
- intent = new Intent(context, activity.getClass());
- } else {
- String packageName = context.getPackageName();
- intent = context.getPackageManager().getLaunchIntentForPackage(packageName);
- }
- intent.setAction(Intent.ACTION_MAIN);
- intent.addCategory(Intent.CATEGORY_LAUNCHER);
- intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
- intent.putExtra(NOTIFICATION_INTENT_KEY, localNotification.getId());
- intent.putExtra(ACTION_INTENT_KEY, action);
- intent.putExtra(NOTIFICATION_OBJ_INTENT_KEY, localNotification.getSource());
- LocalNotificationSchedule schedule = localNotification.getSchedule();
- intent.putExtra(NOTIFICATION_IS_REMOVABLE_KEY, schedule == null || schedule.isRemovable());
- return intent;
- }
-
- /**
- * Build a notification trigger, such as triggering each N seconds, or
- * on a certain date "shape" (such as every first of the month)
- */
- // TODO support different AlarmManager.RTC modes depending on priority
- private void triggerScheduledNotification(Notification notification, LocalNotification request) {
- AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
- LocalNotificationSchedule schedule = request.getSchedule();
- Intent notificationIntent = new Intent(context, TimedNotificationPublisher.class);
- notificationIntent.putExtra(NOTIFICATION_INTENT_KEY, request.getId());
- notificationIntent.putExtra(TimedNotificationPublisher.NOTIFICATION_KEY, notification);
- PendingIntent pendingIntent = PendingIntent.getBroadcast(
- context,
- request.getId(),
- notificationIntent,
- PendingIntent.FLAG_CANCEL_CURRENT
- );
-
- // Schedule at specific time (with repeating support)
- Date at = schedule.getAt();
- if (at != null) {
- if (at.getTime() < new Date().getTime()) {
- Logger.error(Logger.tags("LN"), "Scheduled time must be *after* current time", null);
- return;
- }
- if (schedule.isRepeating()) {
- long interval = at.getTime() - new Date().getTime();
- alarmManager.setRepeating(AlarmManager.RTC, at.getTime(), interval, pendingIntent);
- } else {
- alarmManager.setExact(AlarmManager.RTC, at.getTime(), pendingIntent);
- }
- return;
- }
-
- // Schedule at specific intervals
- String every = schedule.getEvery();
- if (every != null) {
- Long everyInterval = schedule.getEveryInterval();
- if (everyInterval != null) {
- long startTime = new Date().getTime() + everyInterval;
- alarmManager.setRepeating(AlarmManager.RTC, startTime, everyInterval, pendingIntent);
- }
- return;
- }
-
- // Cron like scheduler
- DateMatch on = schedule.getOn();
- if (on != null) {
- long trigger = on.nextTrigger(new Date());
- notificationIntent.putExtra(TimedNotificationPublisher.CRON_KEY, on.toMatchString());
- pendingIntent = PendingIntent.getBroadcast(context, request.getId(), notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);
- alarmManager.setExact(AlarmManager.RTC, trigger, pendingIntent);
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
- Logger.debug(Logger.tags("LN"), "notification " + request.getId() + " will next fire at " + sdf.format(new Date(trigger)));
- }
- }
-
- public void cancel(PluginCall call) {
- List notificationsToCancel = LocalNotification.getLocalNotificationPendingList(call);
- if (notificationsToCancel != null) {
- for (Integer id : notificationsToCancel) {
- dismissVisibleNotification(id);
- cancelTimerForNotification(id);
- storage.deleteNotification(Integer.toString(id));
- }
- }
- call.success();
- }
-
- private void cancelTimerForNotification(Integer notificationId) {
- Intent intent = new Intent(context, TimedNotificationPublisher.class);
- PendingIntent pi = PendingIntent.getBroadcast(context, notificationId, intent, 0);
- if (pi != null) {
- AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
- alarmManager.cancel(pi);
- }
- }
-
- private void dismissVisibleNotification(int notificationId) {
- NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this.context);
- notificationManager.cancel(notificationId);
- }
-
- public boolean areNotificationsEnabled() {
- NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
- return notificationManager.areNotificationsEnabled();
- }
-
- public Uri getDefaultSoundUrl(Context context) {
- int soundId = this.getDefaultSound(context);
- if (soundId != AssetUtil.RESOURCE_ID_ZERO_VALUE) {
- return Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + context.getPackageName() + "/" + soundId);
- }
- return null;
- }
-
- private int getDefaultSound(Context context) {
- if (defaultSoundID != AssetUtil.RESOURCE_ID_ZERO_VALUE) return defaultSoundID;
-
- int resId = AssetUtil.RESOURCE_ID_ZERO_VALUE;
- String soundConfigResourceName = config.getString(CONFIG_KEY_PREFIX + "sound");
- soundConfigResourceName = AssetUtil.getResourceBaseName(soundConfigResourceName);
-
- if (soundConfigResourceName != null) {
- resId = AssetUtil.getResourceID(context, soundConfigResourceName, "raw");
- }
-
- defaultSoundID = resId;
- return resId;
- }
-
- private int getDefaultSmallIcon(Context context) {
- if (defaultSmallIconID != AssetUtil.RESOURCE_ID_ZERO_VALUE) return defaultSmallIconID;
-
- int resId = AssetUtil.RESOURCE_ID_ZERO_VALUE;
- String smallIconConfigResourceName = config.getString(CONFIG_KEY_PREFIX + "smallIcon");
- smallIconConfigResourceName = AssetUtil.getResourceBaseName(smallIconConfigResourceName);
-
- if (smallIconConfigResourceName != null) {
- resId = AssetUtil.getResourceID(context, smallIconConfigResourceName, "drawable");
- }
-
- if (resId == AssetUtil.RESOURCE_ID_ZERO_VALUE) {
- resId = android.R.drawable.ic_dialog_info;
- }
-
- defaultSmallIconID = resId;
- return resId;
- }
-}
diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/LocalNotificationRestoreReceiver.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/LocalNotificationRestoreReceiver.java
deleted file mode 100644
index 34d605f9df..0000000000
--- a/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/LocalNotificationRestoreReceiver.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.getcapacitor.plugin.notification;
-
-import static android.os.Build.VERSION.SDK_INT;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.os.UserManager;
-import com.getcapacitor.CapConfig;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
-public class LocalNotificationRestoreReceiver extends BroadcastReceiver {
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (SDK_INT >= 24) {
- UserManager um = context.getSystemService(UserManager.class);
- if (um == null || !um.isUserUnlocked()) return;
- }
-
- NotificationStorage storage = new NotificationStorage(context);
- List ids = storage.getSavedNotificationIds();
-
- ArrayList notifications = new ArrayList<>(ids.size());
- ArrayList updatedNotifications = new ArrayList<>();
- for (String id : ids) {
- LocalNotification notification = storage.getSavedNotification(id);
- if (notification == null) {
- continue;
- }
-
- LocalNotificationSchedule schedule = notification.getSchedule();
- if (schedule != null) {
- Date at = schedule.getAt();
- if (at != null && at.before(new Date())) {
- // modify the scheduled date in order to show notifications that would have been delivered while device was off.
- long newDateTime = new Date().getTime() + 15 * 1000;
- schedule.setAt(new Date(newDateTime));
- notification.setSchedule(schedule);
- updatedNotifications.add(notification);
- }
- }
-
- notifications.add(notification);
- }
-
- if (updatedNotifications.size() > 0) {
- storage.appendNotifications(updatedNotifications);
- }
-
- CapConfig config = new CapConfig(context.getAssets(), null);
- LocalNotificationManager localNotificationManager = new LocalNotificationManager(storage, null, context, config);
-
- localNotificationManager.schedule(null, notifications);
- }
-}
diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/LocalNotificationSchedule.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/LocalNotificationSchedule.java
deleted file mode 100644
index ebe339a149..0000000000
--- a/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/LocalNotificationSchedule.java
+++ /dev/null
@@ -1,159 +0,0 @@
-package com.getcapacitor.plugin.notification;
-
-import android.text.format.DateUtils;
-import com.getcapacitor.JSObject;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.TimeZone;
-
-public class LocalNotificationSchedule {
-
- public static String JS_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
-
- private Date at;
- private Boolean repeats;
- private String every;
- private Integer count;
-
- private DateMatch on;
-
- public LocalNotificationSchedule(JSObject jsonNotification) throws ParseException {
- JSObject schedule = jsonNotification.getJSObject("schedule");
- if (schedule != null) {
- // Every specific unit of time (always constant)
- buildEveryElement(schedule);
- // Count of units of time from every to repeat on
- buildCountElement(schedule);
- // At specific moment of time (with repeating option)
- buildAtElement(schedule);
- // Build on - recurring times. For e.g. every 1st day of the month at 8:30.
- buildOnElement(schedule);
- }
- }
-
- public LocalNotificationSchedule() {}
-
- private void buildEveryElement(JSObject schedule) {
- // 'year'|'month'|'two-weeks'|'week'|'day'|'hour'|'minute'|'second';
- this.every = schedule.getString("every");
- }
-
- private void buildCountElement(JSObject schedule) {
- this.count = schedule.getInteger("count", 1);
- }
-
- private void buildAtElement(JSObject schedule) throws ParseException {
- this.repeats = schedule.getBool("repeats");
- String dateString = schedule.getString("at");
- if (dateString != null) {
- SimpleDateFormat sdf = new SimpleDateFormat(JS_DATE_FORMAT);
- sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
- this.at = sdf.parse(dateString);
- }
- }
-
- private void buildOnElement(JSObject schedule) {
- JSObject onJson = schedule.getJSObject("on");
- if (onJson != null) {
- this.on = new DateMatch();
- on.setYear(onJson.getInteger("year"));
- on.setMonth(onJson.getInteger("month"));
- on.setDay(onJson.getInteger("day"));
- on.setHour(onJson.getInteger("hour"));
- on.setMinute(onJson.getInteger("minute"));
- }
- }
-
- public DateMatch getOn() {
- return on;
- }
-
- public void setOn(DateMatch on) {
- this.on = on;
- }
-
- public Date getAt() {
- return at;
- }
-
- public void setAt(Date at) {
- this.at = at;
- }
-
- public Boolean getRepeats() {
- return repeats;
- }
-
- public void setRepeats(Boolean repeats) {
- this.repeats = repeats;
- }
-
- public String getEvery() {
- return every;
- }
-
- public void setEvery(String every) {
- this.every = every;
- }
-
- public int getCount() {
- return count;
- }
-
- public void setCount(int count) {
- this.count = count;
- }
-
- public boolean isRepeating() {
- return Boolean.TRUE.equals(this.repeats);
- }
-
- public boolean isRemovable() {
- if (every == null && on == null) {
- if (at != null) {
- return !isRepeating();
- } else {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Get constant long value representing specific interval of time (weeks, days etc.)
- */
- public Long getEveryInterval() {
- switch (every) {
- case "year":
- return count * DateUtils.YEAR_IN_MILLIS;
- case "month":
- // This case is just approximation as months have different number of days
- return count * 30 * DateUtils.DAY_IN_MILLIS;
- case "two-weeks":
- return count * 2 * DateUtils.WEEK_IN_MILLIS;
- case "week":
- return count * DateUtils.WEEK_IN_MILLIS;
- case "day":
- return count * DateUtils.DAY_IN_MILLIS;
- case "hour":
- return count * DateUtils.HOUR_IN_MILLIS;
- case "minute":
- return count * DateUtils.MINUTE_IN_MILLIS;
- case "second":
- return count * DateUtils.SECOND_IN_MILLIS;
- default:
- return null;
- }
- }
-
- /**
- * Get next trigger time based on calendar and current time
- *
- * @param currentTime - current time that will be used to calculate next trigger
- * @return millisecond trigger
- */
- public Long getNextOnSchedule(Date currentTime) {
- return this.on.nextTrigger(currentTime);
- }
-}
diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/NotificationAction.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/NotificationAction.java
deleted file mode 100644
index 624012fac0..0000000000
--- a/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/NotificationAction.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package com.getcapacitor.plugin.notification;
-
-import com.getcapacitor.JSArray;
-import com.getcapacitor.JSObject;
-import com.getcapacitor.Logger;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.json.JSONArray;
-import org.json.JSONObject;
-
-/**
- * Action types that will be registered for the notifications
- */
-public class NotificationAction {
-
- private String id;
- private String title;
- private Boolean input;
-
- public NotificationAction() {}
-
- public NotificationAction(String id, String title, Boolean input) {
- this.id = id;
- this.title = title;
- this.input = input;
- }
-
- public static Map buildTypes(JSArray types) {
- Map actionTypeMap = new HashMap<>();
- try {
- List objects = types.toList();
- for (JSONObject obj : objects) {
- JSObject jsObject = JSObject.fromJSONObject(obj);
- String actionGroupId = jsObject.getString("id");
- if (actionGroupId == null) {
- return null;
- }
- JSONArray actions = jsObject.getJSONArray("actions");
- if (actions != null) {
- NotificationAction[] typesArray = new NotificationAction[actions.length()];
- for (int i = 0; i < typesArray.length; i++) {
- NotificationAction notificationAction = new NotificationAction();
- JSObject action = JSObject.fromJSONObject(actions.getJSONObject(i));
- notificationAction.setId(action.getString("id"));
- notificationAction.setTitle(action.getString("title"));
- notificationAction.setInput(action.getBool("input"));
- typesArray[i] = notificationAction;
- }
- actionTypeMap.put(actionGroupId, typesArray);
- }
- }
- } catch (Exception e) {
- Logger.error(Logger.tags("LN"), "Error when building action types", e);
- }
- return actionTypeMap;
- }
-
- public String getId() {
- return id;
- }
-
- public void setId(String id) {
- this.id = id;
- }
-
- public String getTitle() {
- return title;
- }
-
- public void setTitle(String title) {
- this.title = title;
- }
-
- public boolean isInput() {
- return Boolean.TRUE.equals(input);
- }
-
- public void setInput(Boolean input) {
- this.input = input;
- }
-}
diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/NotificationChannelManager.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/NotificationChannelManager.java
deleted file mode 100644
index e85f4cb4ef..0000000000
--- a/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/NotificationChannelManager.java
+++ /dev/null
@@ -1,132 +0,0 @@
-package com.getcapacitor.plugin.notification;
-
-import android.app.NotificationChannel;
-import android.app.NotificationManager;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.graphics.Color;
-import android.media.AudioAttributes;
-import android.net.Uri;
-import androidx.core.app.NotificationCompat;
-import com.getcapacitor.JSArray;
-import com.getcapacitor.JSObject;
-import com.getcapacitor.Logger;
-import com.getcapacitor.PluginCall;
-import java.util.List;
-
-public class NotificationChannelManager {
-
- private Context context;
- private NotificationManager notificationManager;
-
- public NotificationChannelManager(Context context) {
- this.context = context;
- this.notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
- }
-
- public NotificationChannelManager(Context context, NotificationManager manager) {
- this.context = context;
- this.notificationManager = manager;
- }
-
- private static String CHANNEL_ID = "id";
- private static String CHANNEL_NAME = "name";
- private static String CHANNEL_DESCRIPTION = "description";
- private static String CHANNEL_IMPORTANCE = "importance";
- private static String CHANNEL_VISIBILITY = "visibility";
- private static String CHANNEL_SOUND = "sound";
- private static String CHANNEL_VIBRATE = "vibration";
- private static String CHANNEL_USE_LIGHTS = "lights";
- private static String CHANNEL_LIGHT_COLOR = "lightColor";
-
- public void createChannel(PluginCall call) {
- if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
- JSObject channel = new JSObject();
- channel.put(CHANNEL_ID, call.getString(CHANNEL_ID));
- channel.put(CHANNEL_NAME, call.getString(CHANNEL_NAME));
- channel.put(CHANNEL_DESCRIPTION, call.getString(CHANNEL_DESCRIPTION, ""));
- channel.put(CHANNEL_VISIBILITY, call.getInt(CHANNEL_VISIBILITY, NotificationCompat.VISIBILITY_PUBLIC));
- channel.put(CHANNEL_IMPORTANCE, call.getInt(CHANNEL_IMPORTANCE));
- channel.put(CHANNEL_SOUND, call.getString(CHANNEL_SOUND, null));
- channel.put(CHANNEL_VIBRATE, call.getBoolean(CHANNEL_VIBRATE, false));
- channel.put(CHANNEL_USE_LIGHTS, call.getBoolean(CHANNEL_USE_LIGHTS, false));
- channel.put(CHANNEL_LIGHT_COLOR, call.getString(CHANNEL_LIGHT_COLOR, null));
- createChannel(channel);
- call.success();
- } else {
- call.unavailable();
- }
- }
-
- public void createChannel(JSObject channel) {
- if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
- NotificationChannel notificationChannel = new NotificationChannel(
- channel.getString(CHANNEL_ID),
- channel.getString(CHANNEL_NAME),
- channel.getInteger(CHANNEL_IMPORTANCE)
- );
- notificationChannel.setDescription(channel.getString(CHANNEL_DESCRIPTION));
- notificationChannel.setLockscreenVisibility(channel.getInteger(CHANNEL_VISIBILITY));
- notificationChannel.enableVibration(channel.getBool(CHANNEL_VIBRATE));
- notificationChannel.enableLights(channel.getBool(CHANNEL_USE_LIGHTS));
- String lightColor = channel.getString(CHANNEL_LIGHT_COLOR);
- if (lightColor != null) {
- try {
- notificationChannel.setLightColor(Color.parseColor(lightColor));
- } catch (IllegalArgumentException ex) {
- Logger.error(Logger.tags("NotificationChannel"), "Invalid color provided for light color.", null);
- }
- }
- String sound = channel.getString(CHANNEL_SOUND, null);
- if (sound != null && !sound.isEmpty()) {
- if (sound.contains(".")) {
- sound = sound.substring(0, sound.lastIndexOf('.'));
- }
- AudioAttributes audioAttributes = new AudioAttributes.Builder()
- .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
- .setUsage(AudioAttributes.USAGE_NOTIFICATION)
- .build();
- Uri soundUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + context.getPackageName() + "/raw/" + sound);
- notificationChannel.setSound(soundUri, audioAttributes);
- }
- notificationManager.createNotificationChannel(notificationChannel);
- }
- }
-
- public void deleteChannel(PluginCall call) {
- if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
- String channelId = call.getString("id");
- notificationManager.deleteNotificationChannel(channelId);
- call.success();
- } else {
- call.unavailable();
- }
- }
-
- public void listChannels(PluginCall call) {
- if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
- List notificationChannels = notificationManager.getNotificationChannels();
- JSArray channels = new JSArray();
- for (NotificationChannel notificationChannel : notificationChannels) {
- JSObject channel = new JSObject();
- channel.put(CHANNEL_ID, notificationChannel.getId());
- channel.put(CHANNEL_NAME, notificationChannel.getName());
- channel.put(CHANNEL_DESCRIPTION, notificationChannel.getDescription());
- channel.put(CHANNEL_IMPORTANCE, notificationChannel.getImportance());
- channel.put(CHANNEL_VISIBILITY, notificationChannel.getLockscreenVisibility());
- channel.put(CHANNEL_SOUND, notificationChannel.getSound());
- channel.put(CHANNEL_VIBRATE, notificationChannel.shouldVibrate());
- channel.put(CHANNEL_USE_LIGHTS, notificationChannel.shouldShowLights());
- channel.put(CHANNEL_LIGHT_COLOR, String.format("#%06X", (0xFFFFFF & notificationChannel.getLightColor())));
- Logger.debug(Logger.tags("NotificationChannel"), "visibility " + notificationChannel.getLockscreenVisibility());
- Logger.debug(Logger.tags("NotificationChannel"), "importance " + notificationChannel.getImportance());
- channels.put(channel);
- }
- JSObject result = new JSObject();
- result.put("channels", channels);
- call.success(result);
- } else {
- call.unavailable();
- }
- }
-}
diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/NotificationDismissReceiver.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/NotificationDismissReceiver.java
deleted file mode 100644
index ad79b217c8..0000000000
--- a/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/NotificationDismissReceiver.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.getcapacitor.plugin.notification;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import com.getcapacitor.Logger;
-
-/**
- * Receiver called when notification is dismissed by user
- */
-public class NotificationDismissReceiver extends BroadcastReceiver {
-
- @Override
- public void onReceive(Context context, Intent intent) {
- int intExtra = intent.getIntExtra(LocalNotificationManager.NOTIFICATION_INTENT_KEY, Integer.MIN_VALUE);
- if (intExtra == Integer.MIN_VALUE) {
- Logger.error(Logger.tags("LN"), "Invalid notification dismiss operation", null);
- return;
- }
- boolean isRemovable = intent.getBooleanExtra(LocalNotificationManager.NOTIFICATION_IS_REMOVABLE_KEY, true);
- if (isRemovable) {
- NotificationStorage notificationStorage = new NotificationStorage(context);
- notificationStorage.deleteNotification(Integer.toString(intExtra));
- }
- }
-}
diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/NotificationStorage.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/NotificationStorage.java
deleted file mode 100644
index ed38c3a4ed..0000000000
--- a/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/NotificationStorage.java
+++ /dev/null
@@ -1,146 +0,0 @@
-package com.getcapacitor.plugin.notification;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import com.getcapacitor.JSObject;
-import java.text.ParseException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-/**
- * Class used to abstract storage for notification data
- */
-public class NotificationStorage {
-
- // Key for private preferences
- private static final String NOTIFICATION_STORE_ID = "NOTIFICATION_STORE";
-
- // Key used to save action types
- private static final String ACTION_TYPES_ID = "ACTION_TYPE_STORE";
-
- private static final String ID_KEY = "notificationIds";
-
- private Context context;
-
- public NotificationStorage(Context context) {
- this.context = context;
- }
-
- /**
- * Persist the id of currently scheduled notification
- */
- public void appendNotifications(List localNotifications) {
- SharedPreferences storage = getStorage(NOTIFICATION_STORE_ID);
- SharedPreferences.Editor editor = storage.edit();
- for (LocalNotification request : localNotifications) {
- String key = request.getId().toString();
- editor.putString(key, request.getSource());
- }
- editor.apply();
- }
-
- public List getSavedNotificationIds() {
- SharedPreferences storage = getStorage(NOTIFICATION_STORE_ID);
- Map all = storage.getAll();
- if (all != null) {
- return new ArrayList<>(all.keySet());
- }
- return new ArrayList<>();
- }
-
- public JSObject getSavedNotificationAsJSObject(String key) {
- SharedPreferences storage = getStorage(NOTIFICATION_STORE_ID);
- String notificationString = storage.getString(key, null);
-
- if (notificationString == null) {
- return null;
- }
-
- JSObject jsNotification;
- try {
- jsNotification = new JSObject(notificationString);
- } catch (JSONException ex) {
- return null;
- }
-
- return jsNotification;
- }
-
- public LocalNotification getSavedNotification(String key) {
- JSObject jsNotification = getSavedNotificationAsJSObject(key);
- if (jsNotification == null) {
- return null;
- }
-
- LocalNotification notification;
- try {
- notification = LocalNotification.buildNotificationFromJSObject(jsNotification);
- } catch (ParseException ex) {
- return null;
- }
-
- return notification;
- }
-
- /**
- * Remove the stored notifications
- */
- public void deleteNotification(String id) {
- SharedPreferences.Editor editor = getStorage(NOTIFICATION_STORE_ID).edit();
- editor.remove(id);
- editor.apply();
- }
-
- /**
- * Shared private preferences for the application.
- */
- private SharedPreferences getStorage(String key) {
- return context.getSharedPreferences(key, Context.MODE_PRIVATE);
- }
-
- /**
- * Writes new action types (actions that being displayed in notification) to storage.
- * Write will override previous data.
- *
- * @param typesMap - map with groupId and actionArray assigned to group
- */
- public void writeActionGroup(Map typesMap) {
- Set typesIds = typesMap.keySet();
- for (String id : typesIds) {
- SharedPreferences.Editor editor = getStorage(ACTION_TYPES_ID + id).edit();
- editor.clear();
- NotificationAction[] notificationActions = typesMap.get(id);
- editor.putInt("count", notificationActions.length);
- for (int i = 0; i < notificationActions.length; i++) {
- editor.putString("id" + i, notificationActions[i].getId());
- editor.putString("title" + i, notificationActions[i].getTitle());
- editor.putBoolean("input" + i, notificationActions[i].isInput());
- }
- editor.apply();
- }
- }
-
- /**
- * Retrieve array of notification actions per ActionTypeId
- *
- * @param forId - id of the group
- */
- public NotificationAction[] getActionGroup(String forId) {
- SharedPreferences storage = getStorage(ACTION_TYPES_ID + forId);
- int count = storage.getInt("count", 0);
- NotificationAction[] actions = new NotificationAction[count];
- for (int i = 0; i < count; i++) {
- String id = storage.getString("id" + i, "");
- String title = storage.getString("title" + i, "");
- Boolean input = storage.getBoolean("input" + i, false);
- actions[i] = new NotificationAction(id, title, input);
- }
- return actions;
- }
-}
diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/TimedNotificationPublisher.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/TimedNotificationPublisher.java
deleted file mode 100644
index 5706e8c588..0000000000
--- a/android/capacitor/src/main/java/com/getcapacitor/plugin/notification/TimedNotificationPublisher.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.getcapacitor.plugin.notification;
-
-import android.app.AlarmManager;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import com.getcapacitor.Logger;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-/**
- * Class used to create notification from timer event
- * Note: Class is being registered in Android manifest as broadcast receiver
- */
-public class TimedNotificationPublisher extends BroadcastReceiver {
-
- public static String NOTIFICATION_KEY = "NotificationPublisher.notification";
- public static String CRON_KEY = "NotificationPublisher.cron";
-
- /**
- * Restore and present notification
- */
- @Override
- public void onReceive(Context context, Intent intent) {
- NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
- Notification notification = intent.getParcelableExtra(NOTIFICATION_KEY);
- int id = intent.getIntExtra(LocalNotificationManager.NOTIFICATION_INTENT_KEY, Integer.MIN_VALUE);
- if (id == Integer.MIN_VALUE) {
- Logger.error(Logger.tags("LN"), "No valid id supplied", null);
- }
- notificationManager.notify(id, notification);
- rescheduleNotificationIfNeeded(context, intent, id);
- }
-
- private void rescheduleNotificationIfNeeded(Context context, Intent intent, int id) {
- String dateString = intent.getStringExtra(CRON_KEY);
- if (dateString != null) {
- DateMatch date = DateMatch.fromMatchString(dateString);
- AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
- long trigger = date.nextTrigger(new Date());
- Intent clone = (Intent) intent.clone();
- PendingIntent pendingIntent = PendingIntent.getBroadcast(context, id, clone, PendingIntent.FLAG_CANCEL_CURRENT);
- alarmManager.setExact(AlarmManager.RTC, trigger, pendingIntent);
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
- Logger.debug(Logger.tags("LN"), "notification " + id + " will next fire at " + sdf.format(new Date(trigger)));
- }
- }
-}
diff --git a/core/src/core-plugin-definitions.ts b/core/src/core-plugin-definitions.ts
index 9b0396d999..5c24204316 100644
--- a/core/src/core-plugin-definitions.ts
+++ b/core/src/core-plugin-definitions.ts
@@ -1,9 +1,7 @@
/* eslint-disable */
-import { Plugin, PluginListenerHandle } from './definitions';
+import { Plugin } from './definitions';
export interface PluginRegistry {
- LocalNotifications: LocalNotificationsPlugin;
- PushNotifications: PushNotificationsPlugin;
SplashScreen: SplashScreenPlugin;
WebView: WebViewPlugin;
@@ -29,323 +27,6 @@ export interface CancellableCallback {
//
-export interface LocalNotificationRequest {
- id: string;
-}
-
-export interface LocalNotificationPendingList {
- notifications: LocalNotificationRequest[];
-}
-
-export type LocalNotificationScheduleResult = LocalNotificationPendingList;
-
-export interface LocalNotificationActionType {
- id: string;
- actions?: LocalNotificationAction[];
- iosHiddenPreviewsBodyPlaceholder?: string; // >= iOS 11 only
- iosCustomDismissAction?: boolean;
- iosAllowInCarPlay?: boolean;
- iosHiddenPreviewsShowTitle?: boolean; // >= iOS 11 only
- iosHiddenPreviewsShowSubtitle?: boolean; // >= iOS 11 only
-}
-
-export interface LocalNotificationAction {
- id: string;
- title: string;
- requiresAuthentication?: boolean;
- foreground?: boolean;
- destructive?: boolean;
- input?: boolean;
- inputButtonTitle?: string;
- inputPlaceholder?: string;
-}
-
-export interface LocalNotificationAttachment {
- id: string;
- url: string;
- options?: LocalNotificationAttachmentOptions;
-}
-
-export interface LocalNotificationAttachmentOptions {
- iosUNNotificationAttachmentOptionsTypeHintKey?: string;
- iosUNNotificationAttachmentOptionsThumbnailHiddenKey?: string;
- iosUNNotificationAttachmentOptionsThumbnailClippingRectKey?: string;
- iosUNNotificationAttachmentOptionsThumbnailTimeKey?: string;
-}
-
-export interface LocalNotification {
- title: string;
- body: string;
- id: number;
- schedule?: LocalNotificationSchedule;
- /**
- * Name of the audio file with extension.
- * On iOS the file should be in the app bundle.
- * On Android the file should be on res/raw folder.
- * Doesn't work on Android version 26+ (Android O and newer), for
- * Recommended format is .wav because is supported by both platforms.
- */
- sound?: string;
- /**
- * Android-only: set a custom statusbar icon.
- * If set, it overrides default icon from capacitor.config.json
- */
- smallIcon?: string;
- /**
- * Android only: set the color of the notification icon
- */
- iconColor?: string;
- attachments?: LocalNotificationAttachment[];
- actionTypeId?: string;
- extra?: any;
- /**
- * iOS only: set the thread identifier for notification grouping
- */
- threadIdentifier?: string;
- /**
- * iOS 12+ only: set the summary argument for notification grouping
- */
- summaryArgument?: string;
- /**
- * Android only: set the group identifier for notification grouping, like
- * threadIdentifier on iOS.
- */
- group?: string;
- /**
- * Android only: designate this notification as the summary for a group
- * (should be used with the `group` property).
- */
- groupSummary?: boolean;
- /**
- * Android only: set the notification channel on which local notification
- * will generate. If channel with the given name does not exist then the
- * notification will not fire. If not provided, it will use the default channel.
- */
- channelId?: string;
- /**
- * Android only: set the notification ongoing.
- * If set to true the notification can't be swiped away.
- */
- ongoing?: boolean;
- /**
- * Android only: set the notification to be removed automatically when the user clicks on it
- */
- autoCancel?: boolean;
-}
-
-export interface LocalNotificationSchedule {
- at?: Date;
- repeats?: boolean;
- every?:
- | 'year'
- | 'month'
- | 'two-weeks'
- | 'week'
- | 'day'
- | 'hour'
- | 'minute'
- | 'second';
- count?: number;
- on?: {
- year?: number;
- month?: number;
- day?: number;
- hour?: number;
- minute?: number;
- };
-}
-
-export interface LocalNotificationActionPerformed {
- actionId: string;
- inputValue?: string;
- notification: LocalNotification;
-}
-
-export interface LocalNotificationEnabledResult {
- /**
- * Whether the device has Local Notifications enabled or not
- */
- value: boolean;
-}
-
-export interface NotificationPermissionResponse {
- granted: boolean;
-}
-
-export interface LocalNotificationsPlugin extends Plugin {
- schedule(options: {
- notifications: LocalNotification[];
- }): Promise;
- getPending(): Promise;
- registerActionTypes(options: {
- types: LocalNotificationActionType[];
- }): Promise;
- cancel(pending: LocalNotificationPendingList): Promise;
- areEnabled(): Promise;
- createChannel(channel: NotificationChannel): Promise;
- deleteChannel(channel: NotificationChannel): Promise;
- listChannels(): Promise;
- requestPermission(): Promise;
- addListener(
- eventName: 'localNotificationReceived',
- listenerFunc: (notification: LocalNotification) => void,
- ): PluginListenerHandle;
- addListener(
- eventName: 'localNotificationActionPerformed',
- listenerFunc: (
- notificationAction: LocalNotificationActionPerformed,
- ) => void,
- ): PluginListenerHandle;
-
- /**
- * Remove all native listeners for this plugin
- */
- removeAllListeners(): void;
-}
-
-//
-
-export interface PushNotification {
- title?: string;
- subtitle?: string;
- body?: string;
- id: string;
- badge?: number;
- notification?: any;
- data: any;
- click_action?: string;
- link?: string;
- /**
- * Android only: set the group identifier for notification grouping, like
- * threadIdentifier on iOS.
- */
- group?: string;
- /**
- * Android only: designate this notification as the summary for a group
- * (should be used with the `group` property).
- */
- groupSummary?: boolean;
-}
-
-export interface PushNotificationActionPerformed {
- actionId: string;
- inputValue?: string;
- notification: PushNotification;
-}
-
-export interface PushNotificationToken {
- value: string;
-}
-
-export interface PushNotificationDeliveredList {
- notifications: PushNotification[];
-}
-
-export interface NotificationChannel {
- id: string;
- name: string;
- description?: string;
- sound?: string;
- importance: 1 | 2 | 3 | 4 | 5;
- visibility?: -1 | 0 | 1;
- lights?: boolean;
- lightColor?: string;
- vibration?: boolean;
-}
-
-export interface NotificationChannelList {
- channels: NotificationChannel[];
-}
-
-export interface PushNotificationsPlugin extends Plugin {
- /**
- * Register the app to receive push notifications.
- * Will trigger registration event with the push token
- * or registrationError if there was some problem.
- * Doesn't prompt the user for notification permissions, use requestPermission() first.
- */
- register(): Promise;
- /**
- * On iOS it prompts the user to allow displaying notifications
- * and return if the permission was granted or not.
- * On Android there is no such prompt, so just return as granted.
- */
- requestPermission(): Promise;
- /**
- * Returns the notifications that are visible on the notifications screen.
- */
- getDeliveredNotifications(): Promise;
- /**
- * Removes the specified notifications from the notifications screen.
- * @param delivered list of delivered notifications.
- */
- removeDeliveredNotifications(
- delivered: PushNotificationDeliveredList,
- ): Promise;
- /**
- * Removes all the notifications from the notifications screen.
- */
- removeAllDeliveredNotifications(): Promise;
- /**
- * On Android O or newer (SDK 26+) creates a notification channel.
- * @param channel to create.
- */
- createChannel(channel: NotificationChannel): Promise;
- /**
- * On Android O or newer (SDK 26+) deletes a notification channel.
- * @param channel to delete.
- */
- deleteChannel(channel: NotificationChannel): Promise;
- /**
- * On Android O or newer (SDK 26+) list the available notification channels.
- */
- listChannels(): Promise;
- /**
- * Event called when the push notification registration finished without problems.
- * Provides the push notification token.
- * @param eventName registration.
- * @param listenerFunc callback with the push token.
- */
- addListener(
- eventName: 'registration',
- listenerFunc: (token: PushNotificationToken) => void,
- ): PluginListenerHandle;
- /**
- * Event called when the push notification registration finished with problems.
- * Provides an error with the registration problem.
- * @param eventName registrationError.
- * @param listenerFunc callback with the registration error.
- */
- addListener(
- eventName: 'registrationError',
- listenerFunc: (error: any) => void,
- ): PluginListenerHandle;
- /**
- * Event called when the device receives a push notification.
- * @param eventName pushNotificationReceived.
- * @param listenerFunc callback with the received notification.
- */
- addListener(
- eventName: 'pushNotificationReceived',
- listenerFunc: (notification: PushNotification) => void,
- ): PluginListenerHandle;
- /**
- * Event called when an action is performed on a push notification.
- * @param eventName pushNotificationActionPerformed.
- * @param listenerFunc callback with the notification action.
- */
- addListener(
- eventName: 'pushNotificationActionPerformed',
- listenerFunc: (notification: PushNotificationActionPerformed) => void,
- ): PluginListenerHandle;
- /**
- * Remove all native listeners for this plugin.
- */
- removeAllListeners(): void;
-}
-
-//
-
export interface SplashScreenPlugin extends Plugin {
/**
* Show the splash screen
diff --git a/core/src/web-plugins.ts b/core/src/web-plugins.ts
index 5dd60ba148..a5d7631708 100644
--- a/core/src/web-plugins.ts
+++ b/core/src/web-plugins.ts
@@ -1,9 +1,6 @@
import { mergeWebPlugin } from './plugins';
-import { LocalNotifications } from './web/local-notifications';
import { SplashScreen } from './web/splash-screen';
-export * from './web/local-notifications';
export * from './web/splash-screen';
-mergeWebPlugin(LocalNotifications);
mergeWebPlugin(SplashScreen);
diff --git a/core/src/web/local-notifications.ts b/core/src/web/local-notifications.ts
deleted file mode 100644
index e581500a39..0000000000
--- a/core/src/web/local-notifications.ts
+++ /dev/null
@@ -1,153 +0,0 @@
-/* eslint-disable */
-import {
- LocalNotificationsPlugin,
- LocalNotificationEnabledResult,
- LocalNotificationPendingList,
- LocalNotificationActionType,
- LocalNotification,
- LocalNotificationScheduleResult,
- NotificationPermissionResponse,
- NotificationChannel,
- NotificationChannelList,
-} from '../core-plugin-definitions';
-import { PermissionsRequestResult } from '../definitions';
-
-import { WebPlugin } from './index';
-
-export class LocalNotificationsPluginWeb
- extends WebPlugin
- implements LocalNotificationsPlugin {
- private pending: LocalNotification[] = [];
-
- constructor() {
- super({ name: 'LocalNotifications' });
- }
-
- createChannel(channel: NotificationChannel): Promise {
- throw new Error('Feature not available in the browser. ' + channel.id);
- }
-
- deleteChannel(channel: NotificationChannel): Promise {
- throw new Error('Feature not available in the browser. ' + channel.id);
- }
-
- listChannels(): Promise {
- throw new Error('Feature not available in the browser');
- }
-
- sendPending() {
- const toRemove: LocalNotification[] = [];
- const now = +new Date();
- this.pending.forEach(localNotification => {
- if (localNotification.schedule && localNotification.schedule.at) {
- if (+localNotification.schedule.at <= now) {
- this.buildNotification(localNotification);
- toRemove.push(localNotification);
- }
- }
- });
- console.log('Sent pending, removing', toRemove);
-
- this.pending = this.pending.filter(
- localNotification => !toRemove.find(ln => ln === localNotification),
- );
- }
-
- sendNotification(localNotification: LocalNotification): Notification {
- const l = localNotification;
-
- if (localNotification.schedule && localNotification.schedule.at) {
- const diff = +localNotification.schedule.at - +new Date();
- this.pending.push(l);
- setTimeout(() => {
- this.sendPending();
- }, diff);
- return;
- }
-
- this.buildNotification(localNotification);
- }
-
- buildNotification(localNotification: LocalNotification) {
- const l = localNotification;
- return new Notification(l.title, {
- body: l.body,
- });
- }
-
- schedule(options: {
- notifications: LocalNotification[];
- }): Promise {
- const notifications: Notification[] = [];
- options.notifications.forEach(notification => {
- notifications.push(this.sendNotification(notification));
- });
-
- return Promise.resolve({
- notifications: options.notifications.map(notification => {
- return { id: '' + notification.id };
- }),
- });
- }
-
- getPending(): Promise {
- return Promise.resolve({
- notifications: this.pending.map(localNotification => {
- return {
- id: '' + localNotification.id,
- };
- }),
- });
- }
-
- registerActionTypes(_options: {
- types: LocalNotificationActionType[];
- }): Promise {
- throw new Error('Method not implemented.');
- }
-
- cancel(pending: LocalNotificationPendingList): Promise {
- console.log('Cancel these', pending);
- this.pending = this.pending.filter(
- localNotification =>
- !pending.notifications.find(ln => ln.id === '' + localNotification.id),
- );
- return Promise.resolve();
- }
-
- areEnabled(): Promise {
- return Promise.resolve({
- value: Notification.permission === 'granted',
- });
- }
-
- requestPermission(): Promise {
- return new Promise(resolve => {
- Notification.requestPermission(result => {
- let granted = true;
- if (result === 'denied' || result === 'default') {
- granted = false;
- }
- resolve({ granted });
- });
- });
- }
-
- requestPermissions(): Promise {
- return new Promise((resolve, reject) => {
- Notification.requestPermission(result => {
- if (result === 'denied' || result === 'default') {
- reject(result);
- return;
- }
- resolve({
- results: [result],
- });
- });
- });
- }
-}
-
-const LocalNotifications = new LocalNotificationsPluginWeb();
-
-export { LocalNotifications };
diff --git a/ios/Capacitor/Capacitor.xcodeproj/project.pbxproj b/ios/Capacitor/Capacitor.xcodeproj/project.pbxproj
index ee508d803c..601fb45e62 100644
--- a/ios/Capacitor/Capacitor.xcodeproj/project.pbxproj
+++ b/ios/Capacitor/Capacitor.xcodeproj/project.pbxproj
@@ -24,15 +24,12 @@
62959B1C2524DA7800A3D7F1 /* CAPPluginMethod.m in Sources */ = {isa = PBXBuildFile; fileRef = 62959AE82524DA7700A3D7F1 /* CAPPluginMethod.m */; };
62959B1D2524DA7800A3D7F1 /* UIColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62959AE92524DA7700A3D7F1 /* UIColor.swift */; };
62959B222524DA7800A3D7F1 /* Console.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62959AEF2524DA7700A3D7F1 /* Console.swift */; };
- 62959B252524DA7800A3D7F1 /* PushNotifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62959AF22524DA7700A3D7F1 /* PushNotifications.swift */; };
62959B262524DA7800A3D7F1 /* WebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62959AF32524DA7700A3D7F1 /* WebView.swift */; };
62959B292524DA7800A3D7F1 /* SplashScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62959AF62524DA7700A3D7F1 /* SplashScreen.swift */; };
- 62959B2C2524DA7800A3D7F1 /* LocalNotifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62959AFA2524DA7700A3D7F1 /* LocalNotifications.swift */; };
62959B2F2524DA7800A3D7F1 /* DefaultPlugins.m in Sources */ = {isa = PBXBuildFile; fileRef = 62959AFD2524DA7700A3D7F1 /* DefaultPlugins.m */; };
62959B302524DA7800A3D7F1 /* UIStatusBarManager+CAPHandleTapAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 62959AFE2524DA7700A3D7F1 /* UIStatusBarManager+CAPHandleTapAction.m */; };
62959B312524DA7800A3D7F1 /* JS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62959AFF2524DA7700A3D7F1 /* JS.swift */; };
62959B332524DA7800A3D7F1 /* CAPPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 62959B012524DA7700A3D7F1 /* CAPPlugin.m */; };
- 62959B342524DA7800A3D7F1 /* CAPUNUserNotificationCenterDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62959B022524DA7700A3D7F1 /* CAPUNUserNotificationCenterDelegate.swift */; };
62959B362524DA7800A3D7F1 /* CAPBridgeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62959B042524DA7700A3D7F1 /* CAPBridgeViewController.swift */; };
62959B372524DA7800A3D7F1 /* CAPConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62959B052524DA7700A3D7F1 /* CAPConfig.swift */; };
62959B382524DA7800A3D7F1 /* CAPPluginCall.m in Sources */ = {isa = PBXBuildFile; fileRef = 62959B062524DA7700A3D7F1 /* CAPPluginCall.m */; };
@@ -127,15 +124,12 @@
62959AE82524DA7700A3D7F1 /* CAPPluginMethod.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CAPPluginMethod.m; sourceTree = ""; };
62959AE92524DA7700A3D7F1 /* UIColor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIColor.swift; sourceTree = ""; };
62959AEF2524DA7700A3D7F1 /* Console.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Console.swift; sourceTree = ""; };
- 62959AF22524DA7700A3D7F1 /* PushNotifications.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PushNotifications.swift; sourceTree = ""; };
62959AF32524DA7700A3D7F1 /* WebView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebView.swift; sourceTree = ""; };
62959AF62524DA7700A3D7F1 /* SplashScreen.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SplashScreen.swift; sourceTree = ""; };
- 62959AFA2524DA7700A3D7F1 /* LocalNotifications.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocalNotifications.swift; sourceTree = ""; };
62959AFD2524DA7700A3D7F1 /* DefaultPlugins.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DefaultPlugins.m; sourceTree = ""; };
62959AFE2524DA7700A3D7F1 /* UIStatusBarManager+CAPHandleTapAction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIStatusBarManager+CAPHandleTapAction.m"; sourceTree = ""; };
62959AFF2524DA7700A3D7F1 /* JS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JS.swift; sourceTree = ""; };
62959B012524DA7700A3D7F1 /* CAPPlugin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CAPPlugin.m; sourceTree = ""; };
- 62959B022524DA7700A3D7F1 /* CAPUNUserNotificationCenterDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CAPUNUserNotificationCenterDelegate.swift; sourceTree = ""; };
62959B042524DA7700A3D7F1 /* CAPBridgeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CAPBridgeViewController.swift; sourceTree = ""; };
62959B052524DA7700A3D7F1 /* CAPConfig.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CAPConfig.swift; sourceTree = ""; };
62959B062524DA7700A3D7F1 /* CAPPluginCall.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CAPPluginCall.m; sourceTree = ""; };
@@ -258,7 +252,6 @@
62959AFE2524DA7700A3D7F1 /* UIStatusBarManager+CAPHandleTapAction.m */,
62959AFF2524DA7700A3D7F1 /* JS.swift */,
62959B012524DA7700A3D7F1 /* CAPPlugin.m */,
- 62959B022524DA7700A3D7F1 /* CAPUNUserNotificationCenterDelegate.swift */,
62959B042524DA7700A3D7F1 /* CAPBridgeViewController.swift */,
62959B052524DA7700A3D7F1 /* CAPConfig.swift */,
62959B062524DA7700A3D7F1 /* CAPPluginCall.m */,
@@ -283,8 +276,6 @@
children = (
62959AEF2524DA7700A3D7F1 /* Console.swift */,
62959AFD2524DA7700A3D7F1 /* DefaultPlugins.m */,
- 62959AFA2524DA7700A3D7F1 /* LocalNotifications.swift */,
- 62959AF22524DA7700A3D7F1 /* PushNotifications.swift */,
62959AF62524DA7700A3D7F1 /* SplashScreen.swift */,
62959AF32524DA7700A3D7F1 /* WebView.swift */,
);
@@ -495,10 +486,8 @@
62959B1D2524DA7800A3D7F1 /* UIColor.swift in Sources */,
62959B332524DA7800A3D7F1 /* CAPPlugin.m in Sources */,
62959B1C2524DA7800A3D7F1 /* CAPPluginMethod.m in Sources */,
- 62959B342524DA7800A3D7F1 /* CAPUNUserNotificationCenterDelegate.swift in Sources */,
62959B472524DA7800A3D7F1 /* CAPNotifications.swift in Sources */,
62959B312524DA7800A3D7F1 /* JS.swift in Sources */,
- 62959B252524DA7800A3D7F1 /* PushNotifications.swift in Sources */,
62959B292524DA7800A3D7F1 /* SplashScreen.swift in Sources */,
62959B1A2524DA7800A3D7F1 /* CAPPluginCall.swift in Sources */,
62959B302524DA7800A3D7F1 /* UIStatusBarManager+CAPHandleTapAction.m in Sources */,
@@ -508,7 +497,6 @@
62959B172524DA7800A3D7F1 /* JSExport.swift in Sources */,
62959B3F2524DA7800A3D7F1 /* CAPAssetHandler.swift in Sources */,
62959B3C2524DA7800A3D7F1 /* CAPBridgeDelegate.swift in Sources */,
- 62959B2C2524DA7800A3D7F1 /* LocalNotifications.swift in Sources */,
62959B2F2524DA7800A3D7F1 /* DefaultPlugins.m in Sources */,
62959B222524DA7800A3D7F1 /* Console.swift in Sources */,
62959B3A2524DA7800A3D7F1 /* CAPLog.swift in Sources */,
diff --git a/ios/Capacitor/Capacitor/CAPBridge.swift b/ios/Capacitor/Capacitor/CAPBridge.swift
index b68ff3dc3e..505ccce7bc 100644
--- a/ios/Capacitor/Capacitor/CAPBridge.swift
+++ b/ios/Capacitor/Capacitor/CAPBridge.swift
@@ -46,19 +46,15 @@ enum BridgeError: Error {
// Background dispatch queue for plugin calls
public var dispatchQueue = DispatchQueue(label: "bridge")
- public var notificationDelegationHandler: CAPUNUserNotificationCenterDelegate
-
public init(_ bridgeDelegate: CAPBridgeDelegate, _ messageHandlerWrapper: CAPMessageHandlerWrapper, _ config: CAPConfig, _ scheme: String) {
self.bridgeDelegate = bridgeDelegate
self.messageHandlerWrapper = messageHandlerWrapper
- self.notificationDelegationHandler = CAPUNUserNotificationCenterDelegate()
self.config = config
self.scheme = scheme
super.init()
self.messageHandlerWrapper.bridge = self
- self.notificationDelegationHandler.bridge = self
localUrl = "\(self.scheme)://\(config.getString("server.hostname") ?? "localhost")"
exportCoreJS(localUrl: localUrl!)
registerPlugins()
diff --git a/ios/Capacitor/Capacitor/CAPUNUserNotificationCenterDelegate.swift b/ios/Capacitor/Capacitor/CAPUNUserNotificationCenterDelegate.swift
deleted file mode 100644
index 7a86509fa4..0000000000
--- a/ios/Capacitor/Capacitor/CAPUNUserNotificationCenterDelegate.swift
+++ /dev/null
@@ -1,168 +0,0 @@
-import UserNotifications
-
-public class CAPUNUserNotificationCenterDelegate: NSObject, UNUserNotificationCenterDelegate {
-
- public weak var bridge: CAPBridge?
- // Local list of notification id -> JSObject for storing options
- // between notification requets
- var notificationRequestLookup = [String: JSObject]()
-
- override public init() {
- super.init()
- let center = UNUserNotificationCenter.current()
- if center.delegate == nil {
- center.delegate = self
- }
- }
-
- public func setBridge(bridge: CAPBridge) {
- self.bridge = bridge
- }
- /**
- * Request permissions to send notifications
- */
- public func requestPermissions(with completion: ((Bool, Error?) -> Void)? = nil) {
- let center = UNUserNotificationCenter.current()
- center.requestAuthorization(options: [.badge, .alert, .sound]) { (granted, error) in
- completion?(granted, error)
- }
- }
-
- /**
- * Handle delegate willPresent action when the app is in the foreground.
- * This controls how a notification is presented when the app is running, such as
- * whether it should stay silent, display a badge, play a sound, or show an alert.
- */
- public func userNotificationCenter(_ center: UNUserNotificationCenter,
- willPresent notification: UNNotification,
- withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
- let request = notification.request
- var plugin: CAPPlugin
- var action = "localNotificationReceived"
- var presentationOptions: UNNotificationPresentationOptions = []
-
- var notificationData = makeNotificationRequestJSObject(request)
- if request.trigger?.isKind(of: UNPushNotificationTrigger.self) ?? false {
- plugin = (self.bridge?.getOrLoadPlugin(pluginName: "PushNotifications"))!
- let options = plugin.getConfigValue("presentationOptions") as? [String] ?? ["badge"]
-
- action = "pushNotificationReceived"
- if options.contains("alert") {
- presentationOptions.update(with: .alert)
- }
- if options.contains("badge") {
- presentationOptions.update(with: .badge)
- }
- if options.contains("sound") {
- presentationOptions.update(with: .sound)
- }
- notificationData = makePushNotificationRequestJSObject(request)
-
- } else {
- plugin = (self.bridge?.getOrLoadPlugin(pluginName: "LocalNotifications"))!
- presentationOptions = [
- .badge,
- .sound,
- .alert
- ]
- }
-
- plugin.notifyListeners(action, data: notificationData)
-
- if let options = notificationRequestLookup[request.identifier] {
- let silent = options["silent"] as? Bool ?? false
- if silent {
- completionHandler(.init(rawValue:0))
- return
- }
- }
-
- completionHandler(presentationOptions)
- }
-
- /**
- * Handle didReceive action, called when a notification opens or activates
- * the app based on an action.
- */
- public func userNotificationCenter(_ center: UNUserNotificationCenter,
- didReceive response: UNNotificationResponse,
- withCompletionHandler completionHandler: @escaping () -> Void) {
- completionHandler()
-
- var data = JSObject()
-
- // Get the info for the original notification request
- let originalNotificationRequest = response.notification.request
-
- let actionId = response.actionIdentifier
-
- // We turn the two default actions (open/dismiss) into generic strings
- if actionId == UNNotificationDefaultActionIdentifier {
- data["actionId"] = "tap"
- } else if actionId == UNNotificationDismissActionIdentifier {
- data["actionId"] = "dismiss"
- } else {
- data["actionId"] = actionId
- }
-
- // If the type of action was for an input type, get the value
- if let inputType = response as? UNTextInputNotificationResponse {
- data["inputValue"] = inputType.userText
- }
-
- var plugin: CAPPlugin
- var action = "localNotificationActionPerformed"
-
- if originalNotificationRequest.trigger?.isKind(of: UNPushNotificationTrigger.self) ?? false {
- plugin = (self.bridge?.getOrLoadPlugin(pluginName: "PushNotifications"))!
- data["notification"] = makePushNotificationRequestJSObject(originalNotificationRequest)
- action = "pushNotificationActionPerformed"
- } else {
- data["notification"] = makeNotificationRequestJSObject(originalNotificationRequest)
- plugin = (self.bridge?.getOrLoadPlugin(pluginName: "LocalNotifications"))!
- }
-
- plugin.notifyListeners(action, data: data, retainUntilConsumed: true)
- }
-
- /**
- * Make a JSObject of pending notifications.
- */
- func makePendingNotificationRequestJSObject(_ request: UNNotificationRequest) -> JSObject {
- return [
- "id": request.identifier
- ]
- }
-
- /**
- * Turn a UNNotificationRequest into a JSObject to return back to the client.
- */
- func makeNotificationRequestJSObject(_ request: UNNotificationRequest) -> JSObject {
- let notificationRequest = notificationRequestLookup[request.identifier] ?? [:]
- return [
- "id": request.identifier,
- "title": request.content.title,
- "sound": notificationRequest["sound"] ?? "",
- "body": request.content.body,
- "extra": request.content.userInfo as? JSObject ?? [:],
- "actionTypeId": request.content.categoryIdentifier,
- "attachments": notificationRequest["attachments"] ?? []
- ]
- }
-
- /**
- * Turn a UNNotificationRequest into a JSObject to return back to the client.
- */
- func makePushNotificationRequestJSObject(_ request: UNNotificationRequest) -> JSObject {
- let content = request.content
- return [
- "id": request.identifier,
- "title": content.title,
- "subtitle": content.subtitle,
- "body": content.body,
- "badge": content.badge ?? 1,
- "data": content.userInfo as? JSObject ?? [:]
- ]
- }
-
-}
diff --git a/ios/Capacitor/Capacitor/Plugins/DefaultPlugins.m b/ios/Capacitor/Capacitor/Plugins/DefaultPlugins.m
index ce2664bbe6..28fcf4c06e 100644
--- a/ios/Capacitor/Capacitor/Plugins/DefaultPlugins.m
+++ b/ios/Capacitor/Capacitor/Plugins/DefaultPlugins.m
@@ -6,31 +6,6 @@
CAP_PLUGIN_METHOD(log, CAPPluginReturnNone);
)
-CAP_PLUGIN(CAPLocalNotificationsPlugin, "LocalNotifications",
- CAP_PLUGIN_METHOD(schedule, CAPPluginReturnPromise);
- CAP_PLUGIN_METHOD(requestPermission, CAPPluginReturnPromise);
- CAP_PLUGIN_METHOD(cancel, CAPPluginReturnPromise);
- CAP_PLUGIN_METHOD(getPending, CAPPluginReturnPromise);
- CAP_PLUGIN_METHOD(registerActionTypes, CAPPluginReturnPromise);
- CAP_PLUGIN_METHOD(areEnabled, CAPPluginReturnPromise);
- CAP_PLUGIN_METHOD(createChannel, CAPPluginReturnPromise);
- CAP_PLUGIN_METHOD(deleteChannel, CAPPluginReturnPromise);
- CAP_PLUGIN_METHOD(listChannels, CAPPluginReturnPromise);
- CAP_PLUGIN_METHOD(removeAllListeners, CAPPluginReturnNone);
-)
-
-CAP_PLUGIN(CAPPushNotificationsPlugin, "PushNotifications",
- CAP_PLUGIN_METHOD(register, CAPPluginReturnPromise);
- CAP_PLUGIN_METHOD(requestPermission, CAPPluginReturnPromise);
- CAP_PLUGIN_METHOD(getDeliveredNotifications, CAPPluginReturnPromise);
- CAP_PLUGIN_METHOD(removeDeliveredNotifications, CAPPluginReturnPromise);
- CAP_PLUGIN_METHOD(removeAllDeliveredNotifications, CAPPluginReturnPromise);
- CAP_PLUGIN_METHOD(createChannel, CAPPluginReturnPromise);
- CAP_PLUGIN_METHOD(deleteChannel, CAPPluginReturnPromise);
- CAP_PLUGIN_METHOD(listChannels, CAPPluginReturnPromise);
- CAP_PLUGIN_METHOD(removeAllListeners, CAPPluginReturnNone);
-)
-
CAP_PLUGIN(CAPSplashScreenPlugin, "SplashScreen",
CAP_PLUGIN_METHOD(show, CAPPluginReturnPromise);
CAP_PLUGIN_METHOD(hide, CAPPluginReturnPromise);
diff --git a/ios/Capacitor/Capacitor/Plugins/LocalNotifications.swift b/ios/Capacitor/Capacitor/Plugins/LocalNotifications.swift
deleted file mode 100644
index f950f390a7..0000000000
--- a/ios/Capacitor/Capacitor/Plugins/LocalNotifications.swift
+++ /dev/null
@@ -1,520 +0,0 @@
-import Foundation
-import UserNotifications
-
-enum LocalNotificationError: LocalizedError {
- case contentNoId
- case contentNoTitle
- case contentNoBody
- case triggerConstructionFailed
- case triggerRepeatIntervalTooShort
- case attachmentNoId
- case attachmentNoUrl
- case attachmentFileNotFound(path: String)
- case attachmentUnableToCreate(String)
-
- var errorDescription: String? {
- switch self {
- case .attachmentFileNotFound(path: let path):
- return "Unable to find file \(path) for attachment"
- default:
- return ""
- }
- }
-}
-
-/**
- * Implement Local Notifications
- */
-@objc(CAPLocalNotificationsPlugin)
-public class CAPLocalNotificationsPlugin: CAPPlugin {
-
- /**
- * Schedule a notification.
- */
- @objc func schedule(_ call: CAPPluginCall) {
- guard let notifications = call.getArray("notifications", JSObject.self) else {
- call.error("Must provide notifications array as notifications option")
- return
- }
- var ids = [String]()
-
- for notification in notifications {
- guard let identifier = notification["id"] as? Int else {
- call.error("Notification missing identifier")
- return
- }
-
- // let extra = notification["options"] as? JSObject ?? [:]
-
- var content: UNNotificationContent
- do {
- content = try makeNotificationContent(notification)
- } catch {
- CAPLog.print(error.localizedDescription)
- call.error("Unable to make notification", error)
- return
- }
-
- var trigger: UNNotificationTrigger?
-
- do {
- if let schedule = notification["schedule"] as? JSObject {
- try trigger = handleScheduledNotification(call, schedule)
- }
- } catch {
- call.error("Unable to create notification, trigger failed", error)
- return
- }
-
- // Schedule the request.
- let request = UNNotificationRequest(identifier: "\(identifier)", content: content, trigger: trigger)
-
- self.bridge?.notificationDelegationHandler.notificationRequestLookup[request.identifier] = notification
-
- let center = UNUserNotificationCenter.current()
- center.add(request) { (error: Error?) in
- if let theError = error {
- CAPLog.print(theError.localizedDescription)
- call.error(theError.localizedDescription)
- }
- }
-
- ids.append(request.identifier)
- }
-
- let ret = ids.map({ (id) -> JSObject in
- return [
- "id": id
- ]
- })
- call.success([
- "notifications": ret
- ])
- }
-
- /**
- * Request notification permission
- */
- @objc func requestPermission(_ call: CAPPluginCall) {
- self.bridge?.notificationDelegationHandler.requestPermissions { granted, error in
- guard error == nil else {
- call.error(error!.localizedDescription)
- return
- }
- call.success(["granted": granted])
- }
- }
-
- /**
- * Cancel notifications by id
- */
- @objc func cancel(_ call: CAPPluginCall) {
- guard let notifications = call.getArray("notifications", JSObject.self), notifications.count > 0 else {
- call.error("Must supply notifications to cancel")
- return
- }
-
- let ids = notifications.map { $0["id"] as? String ?? "" }
-
- UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: ids)
- call.success()
- }
-
- /**
- * Get all pending notifications.
- */
- @objc func getPending(_ call: CAPPluginCall) {
- UNUserNotificationCenter.current().getPendingNotificationRequests(completionHandler: { (notifications) in
- CAPLog.print("num of pending notifications \(notifications.count)")
- CAPLog.print(notifications)
-
- let ret = notifications.compactMap({ [weak self] (notification) -> JSObject? in
- return self?.bridge?.notificationDelegationHandler.makePendingNotificationRequestJSObject(notification)
- })
- call.success([
- "notifications": ret
- ])
- })
- }
-
- /**
- * Register allowed action types that a notification may present.
- */
- @objc func registerActionTypes(_ call: CAPPluginCall) {
- guard let types = call.getArray("types", JSObject.self) else {
- return
- }
-
- makeActionTypes(types)
-
- call.success()
- }
-
- /**
- * Check if Local Notifications are authorized and enabled
- */
- @objc func areEnabled(_ call: CAPPluginCall) {
- let center = UNUserNotificationCenter.current()
- center.getNotificationSettings { (settings) in
- let authorized = settings.authorizationStatus == UNAuthorizationStatus.authorized
- let enabled = settings.notificationCenterSetting == UNNotificationSetting.enabled
- call.success([
- "value": enabled && authorized
- ])
- }
- }
-
- /**
- * Build the content for a notification.
- */
- func makeNotificationContent(_ notification: JSObject) throws -> UNNotificationContent {
- guard let title = notification["title"] as? String else {
- throw LocalNotificationError.contentNoTitle
- }
- guard let body = notification["body"] as? String else {
- throw LocalNotificationError.contentNoBody
- }
-
- let extra = notification["extra"] as? JSObject ?? [:]
- let content = UNMutableNotificationContent()
- content.title = NSString.localizedUserNotificationString(forKey: title, arguments: nil)
- content.body = NSString.localizedUserNotificationString(forKey: body,
- arguments: nil)
-
- content.userInfo = extra
- if let actionTypeId = notification["actionTypeId"] as? String {
- content.categoryIdentifier = actionTypeId
- }
-
- if let threadIdentifier = notification["threadIdentifier"] as? String {
- content.threadIdentifier = threadIdentifier
- }
-
- if #available(iOS 12, *), let summaryArgument = notification["summaryArgument"] as? String {
- content.summaryArgument = summaryArgument
- }
-
- if let sound = notification["sound"] as? String {
- content.sound = UNNotificationSound(named: UNNotificationSoundName(sound))
- }
-
- if let attachments = notification["attachments"] as? [JSObject] {
- content.attachments = try makeAttachments(attachments)
- }
-
- return content
- }
-
- /**
- * Build a notification trigger, such as triggering each N seconds, or
- * on a certain date "shape" (such as every first of the month)
- */
- func handleScheduledNotification(_ call: CAPPluginCall, _ schedule: JSObject) throws -> UNNotificationTrigger? {
- var at: Date?
- if let dateString = schedule["at"] as? String, let date = CAPPluginCall.jsDateFormatter.date(from: dateString) {
- at = date
- }
- let every = schedule["every"] as? String
- let count = schedule["count"] as? Int ?? 1
- let on = schedule["on"] as? JSObject
- let repeats = schedule["repeats"] as? Bool ?? false
-
- // If there's a specific date for this notificiation
- if let at = at {
- let dateInfo = Calendar.current.dateComponents(in: TimeZone.current, from: at)
-
- if dateInfo.date! < Date() {
- call.error("Scheduled time must be *after* current time")
- return nil
- }
-
- let dateInterval = DateInterval(start: Date(), end: dateInfo.date!)
-
- // Notifications that repeat have to be at least a minute between each other
- if repeats && dateInterval.duration < 60 {
- throw LocalNotificationError.triggerRepeatIntervalTooShort
- }
-
- return UNTimeIntervalNotificationTrigger(timeInterval: dateInterval.duration, repeats: repeats)
- }
-
- // If this notification should repeat every count of day/month/week/etc. or on a certain
- // matching set of date components
- if let on = on {
- let dateComponents = getDateComponents(on)
- return UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
- }
-
- if let every = every {
- if let repeatDateInterval = getRepeatDateInterval(every, count) {
- return UNTimeIntervalNotificationTrigger(timeInterval: repeatDateInterval.duration, repeats: true)
- }
- }
-
- return nil
- }
-
- /**
- * Given our schedule format, return a DateComponents object
- * that only contains the components passed in.
- */
- func getDateComponents(_ at: JSObject) -> DateComponents {
- //var dateInfo = Calendar.current.dateComponents(in: TimeZone.current, from: Date())
- //dateInfo.calendar = Calendar.current
- var dateInfo = DateComponents()
-
- if let year = at["year"] as? Int {
- dateInfo.year = year
- }
- if let month = at["month"] as? Int {
- dateInfo.month = month
- }
- if let day = at["day"] as? Int {
- dateInfo.day = day
- }
- if let hour = at["hour"] as? Int {
- dateInfo.hour = hour
- }
- if let minute = at["minute"] as? Int {
- dateInfo.minute = minute
- }
- if let second = at["second"] as? Int {
- dateInfo.second = second
- }
- return dateInfo
- }
-
- /**
- * Compute the difference between the string representation of a date
- * interval and today. For example, if every is "month", then we
- * return the interval between today and a month from today.
- */
- func getRepeatDateInterval(_ every: String, _ count: Int) -> DateInterval? {
- let cal = Calendar.current
- let now = Date()
- switch every {
- case "year":
- let newDate = cal.date(byAdding: .year, value: count, to: now)!
- return DateInterval(start: now, end: newDate)
- case "month":
- let newDate = cal.date(byAdding: .month, value: count, to: now)!
- return DateInterval(start: now, end: newDate)
- case "two-weeks":
- let newDate = cal.date(byAdding: .weekOfYear, value: 2 * count, to: now)!
- return DateInterval(start: now, end: newDate)
- case "week":
- let newDate = cal.date(byAdding: .weekOfYear, value: count, to: now)!
- return DateInterval(start: now, end: newDate)
- case "day":
- let newDate = cal.date(byAdding: .day, value: count, to: now)!
- return DateInterval(start: now, end: newDate)
- case "hour":
- let newDate = cal.date(byAdding: .hour, value: count, to: now)!
- return DateInterval(start: now, end: newDate)
- case "minute":
- let newDate = cal.date(byAdding: .minute, value: count, to: now)!
- return DateInterval(start: now, end: newDate)
- case "second":
- let newDate = cal.date(byAdding: .second, value: count, to: now)!
- return DateInterval(start: now, end: newDate)
- default:
- return nil
- }
- }
-
- /**
- * Make required UNNotificationCategory entries for action types
- */
- func makeActionTypes(_ actionTypes: [JSObject]) {
- var createdCategories = [UNNotificationCategory]()
-
- let generalCategory = UNNotificationCategory(identifier: "GENERAL",
- actions: [],
- intentIdentifiers: [],
- options: .customDismissAction)
-
- createdCategories.append(generalCategory)
- for type in actionTypes {
- guard let id = type["id"] as? String else {
- bridge?.modulePrint(self, "Action type must have an id field")
- continue
- }
- let hiddenBodyPlaceholder = type["iosHiddenPreviewsBodyPlaceholder"] as? String ?? ""
- let actions = type["actions"] as? [JSObject] ?? []
-
- let newActions = makeActions(actions)
-
- // Create the custom actions for the TIMER_EXPIRED category.
- var newCategory: UNNotificationCategory?
-
- newCategory = UNNotificationCategory(identifier: id,
- actions: newActions,
- intentIdentifiers: [],
- hiddenPreviewsBodyPlaceholder: hiddenBodyPlaceholder,
- options: makeCategoryOptions(type))
-
- createdCategories.append(newCategory!)
- }
-
- let center = UNUserNotificationCenter.current()
- center.setNotificationCategories(Set(createdCategories))
- }
-
- /**
- * Build the required UNNotificationAction objects for each action type registered.
- */
- func makeActions(_ actions: [JSObject]) -> [UNNotificationAction] {
- var createdActions = [UNNotificationAction]()
-
- for action in actions {
- guard let id = action["id"] as? String else {
- bridge?.modulePrint(self, "Action must have an id field")
- continue
- }
- let title = action["title"] as? String ?? ""
- let input = action["input"] as? Bool ?? false
-
- var newAction: UNNotificationAction
- if input {
- let inputButtonTitle = action["inputButtonTitle"] as? String
- let inputPlaceholder = action["inputPlaceholder"] as? String ?? ""
-
- if inputButtonTitle != nil {
- newAction = UNTextInputNotificationAction(identifier: id,
- title: title,
- options: makeActionOptions(action),
- textInputButtonTitle: inputButtonTitle!,
- textInputPlaceholder: inputPlaceholder)
- } else {
- newAction = UNTextInputNotificationAction(identifier: id, title: title, options: makeActionOptions(action))
- }
- } else {
- // Create the custom actions for the TIMER_EXPIRED category.
- newAction = UNNotificationAction(identifier: id,
- title: title,
- options: makeActionOptions(action))
- }
- createdActions.append(newAction)
- }
-
- return createdActions
- }
-
- /**
- * Make options for UNNotificationActions
- */
- func makeActionOptions(_ action: JSObject) -> UNNotificationActionOptions {
- let foreground = action["foreground"] as? Bool ?? false
- let destructive = action["destructive"] as? Bool ?? false
- let requiresAuthentication = action["requiresAuthentication"] as? Bool ?? false
-
- if foreground {
- return .foreground
- }
- if destructive {
- return .destructive
- }
- if requiresAuthentication {
- return .authenticationRequired
- }
- return UNNotificationActionOptions(rawValue: 0)
- }
-
- /**
- * Make options for UNNotificationCategoryActions
- */
- func makeCategoryOptions(_ type: JSObject) -> UNNotificationCategoryOptions {
- let customDismiss = type["iosCustomDismissAction"] as? Bool ?? false
- let carPlay = type["iosAllowInCarPlay"] as? Bool ?? false
- let hiddenPreviewsShowTitle = type["iosHiddenPreviewsShowTitle"] as? Bool ?? false
- let hiddenPreviewsShowSubtitle = type["iosHiddenPreviewsShowSubtitle"] as? Bool ?? false
-
- if customDismiss {
- return .customDismissAction
- }
- if carPlay {
- return .allowInCarPlay
- }
-
- if hiddenPreviewsShowTitle {
- return .hiddenPreviewsShowTitle
- }
- if hiddenPreviewsShowSubtitle {
- return .hiddenPreviewsShowSubtitle
- }
-
- return UNNotificationCategoryOptions(rawValue: 0)
- }
-
- /**
- * Build the UNNotificationAttachment object for each attachment supplied.
- */
- func makeAttachments(_ attachments: [JSObject]) throws -> [UNNotificationAttachment] {
- var createdAttachments = [UNNotificationAttachment]()
-
- for attachment in attachments {
- guard let id = attachment["id"] as? String else {
- throw LocalNotificationError.attachmentNoId
- }
- guard let url = attachment["url"] as? String else {
- throw LocalNotificationError.attachmentNoUrl
- }
- guard let urlObject = makeAttachmentUrl(url) else {
- throw LocalNotificationError.attachmentFileNotFound(path: url)
- }
-
- let options = attachment["options"] as? JSObject ?? [:]
-
- do {
- let newAttachment = try UNNotificationAttachment(identifier: id, url: urlObject, options: makeAttachmentOptions(options))
- createdAttachments.append(newAttachment)
- } catch {
- throw LocalNotificationError.attachmentUnableToCreate(error.localizedDescription)
- }
- }
-
- return createdAttachments
- }
-
- /**
- * Get the internal URL for the attachment URL
- */
- func makeAttachmentUrl(_ path: String) -> URL? {
- let file = CAPFileManager.get(path: path)
- return file?.url
- }
-
- /**
- * Build the options for the attachment, if any. (For example: the clipping rectangle to use
- * for image attachments)
- */
- func makeAttachmentOptions(_ options: JSObject) -> JSObject {
- var opts: JSObject = [:]
-
- if let iosUNNotificationAttachmentOptionsTypeHintKey = options["iosUNNotificationAttachmentOptionsTypeHintKey"] as? String {
- opts[UNNotificationAttachmentOptionsTypeHintKey] = iosUNNotificationAttachmentOptionsTypeHintKey
- }
- if let iosUNNotificationAttachmentOptionsThumbnailHiddenKey = options["iosUNNotificationAttachmentOptionsThumbnailHiddenKey"] as? String {
- opts[UNNotificationAttachmentOptionsThumbnailHiddenKey] = iosUNNotificationAttachmentOptionsThumbnailHiddenKey
- }
- if let iosUNNotificationAttachmentOptionsThumbnailClippingRectKey = options["iosUNNotificationAttachmentOptionsThumbnailClippingRectKey"] as? String {
- opts[UNNotificationAttachmentOptionsThumbnailClippingRectKey] = iosUNNotificationAttachmentOptionsThumbnailClippingRectKey
- }
- if let iosUNNotificationAttachmentOptionsThumbnailTimeKey = options["iosUNNotificationAttachmentOptionsThumbnailTimeKey"] as? String {
- opts[UNNotificationAttachmentOptionsThumbnailTimeKey] = iosUNNotificationAttachmentOptionsThumbnailTimeKey
- }
- return opts
- }
-
- @objc func createChannel(_ call: CAPPluginCall) {
- call.unimplemented()
- }
-
- @objc func deleteChannel(_ call: CAPPluginCall) {
- call.unimplemented()
- }
-
- @objc func listChannels(_ call: CAPPluginCall) {
- call.unimplemented()
- }
-}
diff --git a/ios/Capacitor/Capacitor/Plugins/PushNotifications.swift b/ios/Capacitor/Capacitor/Plugins/PushNotifications.swift
deleted file mode 100644
index 43aca31238..0000000000
--- a/ios/Capacitor/Capacitor/Plugins/PushNotifications.swift
+++ /dev/null
@@ -1,129 +0,0 @@
-import Foundation
-import UserNotifications
-
-enum PushNotificationError: Error {
- case tokenParsingFailed
-}
-
-/**
- * Implement Push Notifications
- */
-@objc(CAPPushNotificationsPlugin)
-public class CAPPushNotificationsPlugin: CAPPlugin {
- // Local list of notification id -> JSObject for storing options
- // between notification requets
- var notificationRequestLookup = [String: JSObject]()
-
- override public func load() {
- NotificationCenter.default.addObserver(self,
- selector: #selector(self.didRegisterForRemoteNotificationsWithDeviceToken(notification:)),
- name: Notification.Name(CAPNotifications.DidRegisterForRemoteNotificationsWithDeviceToken.name()),
- object: nil)
- NotificationCenter.default.addObserver(self,
- selector: #selector(self.didFailToRegisterForRemoteNotificationsWithError(notification:)),
- name: Notification.Name(CAPNotifications.DidFailToRegisterForRemoteNotificationsWithError.name()),
- object: nil)
- }
-
- /**
- * Register for push notifications
- */
- @objc func register(_ call: CAPPluginCall) {
- DispatchQueue.main.async {
- UIApplication.shared.registerForRemoteNotifications()
- }
- call.success()
- }
-
- /**
- * Request notification permission
- */
- @objc func requestPermission(_ call: CAPPluginCall) {
- self.bridge?.notificationDelegationHandler.requestPermissions { granted, error in
- guard error == nil else {
- call.error(error!.localizedDescription)
- return
- }
- call.success(["granted": granted])
- }
- }
-
- /**
- * Get notifications in Notification Center
- */
- @objc func getDeliveredNotifications(_ call: CAPPluginCall) {
- UNUserNotificationCenter.current().getDeliveredNotifications(completionHandler: { [weak self] (notifications) in
- let ret = notifications.compactMap({ (notification) -> [String: Any]? in
- return self?.bridge?.notificationDelegationHandler.makePushNotificationRequestJSObject(notification.request)
- })
- call.success([
- "notifications": ret
- ])
- })
- }
-
- /**
- * Remove specified notifications from Notification Center
- */
- @objc func removeDeliveredNotifications(_ call: CAPPluginCall) {
- guard let notifications = call.getArray("notifications", JSObject.self) else {
- call.error("Must supply notifications to remove")
- return
- }
-
- let ids = notifications.map { $0["id"] as? String ?? "" }
-
- UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: ids)
- call.success()
- }
-
- /**
- * Remove all notifications from Notification Center
- */
- @objc func removeAllDeliveredNotifications(_ call: CAPPluginCall) {
- UNUserNotificationCenter.current().removeAllDeliveredNotifications()
- DispatchQueue.main.async(execute: {
- UIApplication.shared.applicationIconBadgeNumber = 0
- })
- call.success()
- }
-
- @objc func createChannel(_ call: CAPPluginCall) {
- call.unimplemented()
- }
-
- @objc func deleteChannel(_ call: CAPPluginCall) {
- call.unimplemented()
- }
-
- @objc func listChannels(_ call: CAPPluginCall) {
- call.unimplemented()
- }
-
- @objc public func didRegisterForRemoteNotificationsWithDeviceToken(notification: NSNotification) {
- if let deviceToken = notification.object as? Data {
- let deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
- notifyListeners("registration", data: [
- "value": deviceTokenString
- ])
- } else if let stringToken = notification.object as? String {
- notifyListeners("registration", data: [
- "value": stringToken
- ])
- } else {
- notifyListeners("registrationError", data: [
- "error": PushNotificationError.tokenParsingFailed.localizedDescription
- ])
- }
- }
-
- @objc public func didFailToRegisterForRemoteNotificationsWithError(notification: NSNotification) {
- guard let error = notification.object as? Error else {
- return
- }
- notifyListeners("registrationError", data: [
- "error": error.localizedDescription
- ])
- }
-
-}