Skip to content

Commit 6462773

Browse files
#11 Scheduling repeating notifications (daily, weekly, etc)
1 parent d690152 commit 6462773

File tree

9 files changed

+90
-17
lines changed

9 files changed

+90
-17
lines changed

.npmignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
# Exclude the native source code. The native libraries are included in the plugin as compiled resources (i.e. jar & framework)
2-
native-src/
2+
native-src/
3+
platforms/android/README.md

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,16 @@ You can pass several options to this function, everything is optional:
5252
|`at` |A JavaScript Date object indicating when the notification should be shown. Default 'now'.|
5353
|`badge` |On iOS (and some Android devices) you see a number on top of the app icon. On most Android devices you'll see this number in the notification center. Default not set (0).|
5454
|`sound` |Currently this is only used on Android where you can set this to `null` to suppress the sound. Default 'the default notification sound'.|
55+
|`interval` |Set to one of second|minute|hour|day|week|month|quarter|year if you want a recurring notification.|
5556
5657
```js
5758
LocalNotifications.schedule([{
5859
id: 1,
5960
title: 'The title',
60-
body: 'The body',
61+
body: 'Recurs every minute until cancelled',
6162
ticker: 'The ticker',
6263
badge: 1,
64+
interval: 'minute',
6365
sound: null, // suppress the default sound
6466
at: new Date(new Date().getTime() + (10 * 1000)) // 10 seconds from now
6567
}]).then(
@@ -161,6 +163,5 @@ If the `requestPermission` or `schedule` functions previously ran you may want t
161163
Let us know what you need by opening a Github issue.
162164
163165
We're thinking about adding support for things like:
164-
- Scheduling repeating notifications (daily, weekly, etc)
165166
- [Custom Notification sounds](https://github.com/EddyVerbruggen/nativescript-local-notifications/issues/3)
166167
- Interactive Notifications on iOS

local-notifications.android.js

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,15 @@ LocalNotifications.schedule = function (arg) {
8080

8181
// configure when we'll show the event
8282
var alarmManager = utils.ad.getApplicationContext().getSystemService(android.content.Context.ALARM_SERVICE);
83-
alarmManager.set(android.app.AlarmManager.RTC_WAKEUP, options.atTime, pendingIntent);
83+
84+
var repeatInterval = LocalNotifications._getInterval(options.interval);
85+
options.repeatInterval = repeatInterval; // used when restoring the notification after a reboot
86+
87+
if (repeatInterval > 0) {
88+
alarmManager.setRepeating(android.app.AlarmManager.RTC_WAKEUP, options.atTime, repeatInterval, pendingIntent);
89+
} else {
90+
alarmManager.set(android.app.AlarmManager.RTC_WAKEUP, options.atTime, pendingIntent);
91+
}
8492

8593
LocalNotifications._persist(options);
8694
}
@@ -93,11 +101,36 @@ LocalNotifications.schedule = function (arg) {
93101
});
94102
};
95103

104+
LocalNotifications._getInterval = function(interval) {
105+
if (interval === null || interval === "") {
106+
return 0;
107+
} else if (interval === "second") {
108+
return 1000; // it's in ms
109+
} else if (interval === "minute") {
110+
return android.app.AlarmManager.INTERVAL_FIFTEEN_MINUTES / 15;
111+
} else if (interval === "hour") {
112+
return android.app.AlarmManager.INTERVAL_HOUR;
113+
} else if (interval === "day") {
114+
return android.app.AlarmManager.INTERVAL_DAY;
115+
} else if (interval === "week") {
116+
return android.app.AlarmManager.INTERVAL_DAY * 7;
117+
} else if (interval === "month") {
118+
return android.app.AlarmManager.INTERVAL_DAY * 31; // well that's almost accurate
119+
} else if (interval === "quarter") {
120+
return android.app.AlarmManager.INTERVAL_HOUR * 2190;
121+
} else if (interval === "year") {
122+
return android.app.AlarmManager.INTERVAL_DAY * 365; // same here
123+
} else {
124+
return 0;
125+
}
126+
};
127+
96128
/**
97129
* Persist notification info to the Android Shared Preferences.
98130
* This way we can later retrieve it to cancel it, or restore upon reboot.
99131
*/
100132
LocalNotifications._persist = function (options) {
133+
console.log("------------------- persisting: " + JSON.stringify(options));
101134
var sharedPreferences = LocalNotifications._getSharedPreferences();
102135
var sharedPreferencesEditor = sharedPreferences.edit();
103136
sharedPreferencesEditor.putString("" + options.id, JSON.stringify(options));
@@ -208,7 +241,7 @@ LocalNotifications.requestPermission = function (arg) {
208241

209242
LocalNotifications._getSharedPreferences = function () {
210243
var context = application.android.foregroundActivity;
211-
var PREF_KEY = "LocalNotificationsPlugin"; // TODO get constant from native, as the restorereceiver needs it as well
244+
var PREF_KEY = com.telerik.localnotifications.NotificationRestoreReceiver.SHARED_PREFERENCES_KEY;
212245
return context.getSharedPreferences(PREF_KEY, android.content.Context.MODE_PRIVATE);
213246
};
214247

local-notifications.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ declare module "nativescript-local-notifications" {
4545
* Default 'the default notification sound'.
4646
*/
4747
sound?: string;
48+
49+
/**
50+
* One of second|minute|hour|day|week|month|quarter|year
51+
*/
52+
interval?: string; // TODO add better TS support
4853
}
4954

5055
export interface ReceivedNotification {

local-notifications.ios.js

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,18 +101,20 @@ LocalNotifications._schedulePendingNotifications = function () {
101101
notification.applicationIconBadgeNumber = options.badge;
102102

103103
// these are sent back to the plugin when a notification is received
104-
var userInfoDict = NSMutableDictionary.alloc().initWithCapacity(3);
104+
var userInfoDict = NSMutableDictionary.alloc().initWithCapacity(4);
105105
userInfoDict.setObjectForKey(options.id, "id");
106106
userInfoDict.setObjectForKey(options.title, "title");
107107
userInfoDict.setObjectForKey(options.body, "body");
108+
userInfoDict.setObjectForKey(options.interval, "interval");
108109
notification.userInfo = userInfoDict;
109110

110111
if (options.sound === undefined || options.sound === "default") {
111112
notification.soundName = UILocalNotificationDefaultSoundName;
112113
}
113114

115+
notification.repeatInterval = LocalNotifications._getInterval(options.interval);
116+
114117
// TODO add these after v1
115-
// notification.repeatInterval = 1;
116118
// notification.soundName = custom..;
117119
// notification.resumeApplicationInBackground = true;
118120

@@ -193,4 +195,28 @@ LocalNotifications.schedule = function (arg) {
193195
});
194196
};
195197

198+
LocalNotifications._getInterval = function(interval) {
199+
if (interval === null || interval === "") {
200+
return NSCalendarUnitEra;
201+
} else if (interval === "second") {
202+
return NSCalendarUnitSecond;
203+
} else if (interval === "minute") {
204+
return NSCalendarUnitMinute;
205+
} else if (interval === "hour") {
206+
return NSCalendarUnitHour;
207+
} else if (interval === "day") {
208+
return NSCalendarUnitDay;
209+
} else if (interval === "week") {
210+
return NSCalendarUnitWeekOfYear;
211+
} else if (interval === "month") {
212+
return NSCalendarUnitMonth;
213+
} else if (interval === "quarter") {
214+
return NSCalendarUnitQuarter;
215+
} else if (interval === "year") {
216+
return NSCalendarUnitYear;
217+
} else {
218+
return NSCalendarUnitEra;
219+
}
220+
};
221+
196222
module.exports = LocalNotifications;

native-src/android/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ Assuming the plugin is locally cloned next to your app's folder:
1414

1515
#### Install
1616

17-
`tns plugin add ../nativescript-local-notifications`
17+
`tns plugin add ../../nativescript-local-notifications`
1818

1919
#### Reinstall:
2020

21-
`tns plugin remove nativescript-local-notifications && tns plugin add ../nativescript-local-notifications && tns platform remove android && tns platform add android`
21+
`tns plugin remove nativescript-local-notifications && tns plugin add ../../nativescript-local-notifications && tns platform remove android && tns platform add android`
2222

2323

2424
### run

native-src/android/src/com/telerik/localnotifications/NotificationRestoreReceiver.java

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,11 @@ public class NotificationRestoreReceiver extends BroadcastReceiver {
2828

2929
static final String TAG = "NotificationRestoreReceiver";
3030

31+
public static final String SHARED_PREFERENCES_KEY = "LocalNotificationsPlugin";
32+
3133
@Override
3234
public void onReceive(Context context, Intent intent) {
33-
final SharedPreferences sharedPreferences = context.getSharedPreferences("LocalNotificationsPlugin", Context.MODE_PRIVATE);
35+
final SharedPreferences sharedPreferences = context.getSharedPreferences(SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE);
3436
final Set notificationOptions = sharedPreferences.getAll().entrySet();
3537

3638
Iterator<Map.Entry> iterator = notificationOptions.iterator();
@@ -71,21 +73,26 @@ public void onReceive(Context context, Intent intent) {
7173

7274
// configure when we'll show the event
7375
long triggerTime = options.getLong("atTime");
76+
long interval = options.optLong("repeatInterval", 0); // in ms
77+
final boolean isRepeating = interval > 0;
7478
final Date triggerDate = new Date(triggerTime);
7579
final boolean wasInThePast = new Date().after(triggerDate);
7680
final AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
77-
if (wasInThePast) {
78-
Log.d(TAG, "------------------------ cancel notification: " + options);
81+
if (wasInThePast && !isRepeating) {
7982
alarmManager.cancel(pendingIntent);
8083
((NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE)).cancel(options.getInt("id"));
8184
// TODO 'unpersist' would be nice
8285
} else {
8386
// schedule
84-
Log.d(TAG, "------------------------ schedule notification: " + options);
85-
alarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, pendingIntent);
87+
if (isRepeating) {
88+
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, triggerTime, interval, pendingIntent);
89+
} else {
90+
alarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, pendingIntent);
91+
}
8692
}
87-
} catch (JSONException e) {
88-
e.printStackTrace();
93+
} catch (Throwable t) {
94+
Log.e(TAG, "Notification scheduling error: " + t.getMessage());
95+
t.printStackTrace();
8996
}
9097
}
9198
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "nativescript-local-notifications",
3-
"version": "1.0.3",
3+
"version": "1.1.0",
44
"description": "The Local Notifications plugin allows your app to show notifications when the app is not running. Just like remote push notifications, but a few orders of magnitude easier to set up.",
55
"main" : "local-notifications.js",
66
"nativescript": {
143 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)