Skip to content
This repository was archived by the owner on Jan 14, 2025. It is now read-only.

Added method getScheduledLocalNotifications() #1466

Merged
merged 16 commits into from
Jun 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

- (Android) Sounds are playing even in Do Not Disturb [#1432](https://github.com/zo0r/react-native-push-notification/issues/1432#issuecomment-633367111)
- (Android) onNotification fires every time when the app goes from background to foreground [#1455](https://github.com/zo0r/react-native-push-notification/issues/1455)
- (Android) Cannot send to notification centre because there is no 'message' field in: Bundle [#1452](https://github.com/zo0r/react-native-push-notification/issues/1452)
- (Android) java.lang.NullPointerException: Attempt to invoke virtual method 'void com.dieam.reactnativepushnotification.modules.d.c(android.os.Bundle)' on a null object reference [#1431](https://github.com/zo0r/react-native-push-notification/issues/1431#issuecomment-633315150)

## [3.5.1] - 2020-05-20

Expand Down
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,32 @@ Removes the specified notifications from Notification Center
| ----------- | ----- | -------- | ---------------------------------- |
| identifiers | array | Yes | Array of notification identifiers. |

### 6) getScheduledLocalNotifications

```javascript
PushNotificationIOS.getScheduledLocalNotifications(callback);
```

Provides you with a list of the app’s scheduled local notifications that are yet to be displayed

**Parameters:**

| Name | Type | Required | Description |
| -------- | -------- | -------- | ----------------------------------------------------------- |
| callback | function | Yes | Function which receive an array of delivered notifications. |

Returns an array of local scheduled notification objects containing:

| Name | Type | Description |
| -------- | -------- | -------- | ----------------------------------------------------------- |
| id | number | The identifier of this notification. |
| date | Date | The fire date of this notification. |
| title | string | The title of this notification. |
| message | string | The message body of this notification. |
| soundName | string | The sound name of this notification. |
| repeatInterval | number | The repeat interval of this notification. |
| number | number | App notification badge count number. |

## Abandon Permissions

`PushNotification.abandonPermissions()` Revokes the current token and unregister for all remote notifications received via APNS or FCM.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,15 @@ public void removeAllDeliveredNotifications() {
* Returns a list of all notifications currently in the Notification Center
*/
public void getDeliveredNotifications(Callback callback) {
callback.invoke(mRNPushNotificationHelper.getDeliveredNotifications());
callback.invoke(mRNPushNotificationHelper.getDeliveredNotifications());
}

@ReactMethod
/**
* Returns a list of all currently scheduled notifications
*/
public void getScheduledLocalNotifications(Callback callback) {
callback.invoke(mRNPushNotificationHelper.getScheduledLocalNotifications());
}

@ReactMethod
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,26 @@ public String getId() {
return id;
}

public String getSound() {
return sound;
}

public String getMessage() {
return message;
}

public String getTitle() {
return title;
}

public String getNumber() {
return number;
}

public String getRepeatType() {
return repeatType;
}

public double getFireDate() {
return fireDate;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import androidx.core.app.NotificationCompat;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableArray;
Expand All @@ -43,6 +42,7 @@
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Map;

import static com.dieam.reactnativepushnotification.modules.RNPushNotification.LOG_TAG;
import static com.dieam.reactnativepushnotification.modules.RNPushNotificationAttributes.fromJson;
Expand Down Expand Up @@ -167,14 +167,14 @@ public void sendNotificationScheduledCore(Bundle bundle) {
// notification to the user
PendingIntent pendingIntent = toScheduleNotificationIntent(bundle);

if(pendingIntent == null) {
if (pendingIntent == null) {
return;
}

Log.d(LOG_TAG, String.format("Setting a notification with id %s at time %s",
bundle.getString("id"), Long.toString(fireDate)));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if(allowWhileIdle && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (allowWhileIdle && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
getAlarmManager().setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, fireDate, pendingIntent);
} else {
getAlarmManager().setExact(AlarmManager.RTC_WAKEUP, fireDate, pendingIntent);
Expand Down Expand Up @@ -294,7 +294,7 @@ public void sendToNotificationCentreWithPicture(Bundle bundle, Bitmap largeIconB
final String visibilityString = bundle.getString("visibility");

if (visibilityString != null) {
switch(visibilityString.toLowerCase()) {
switch (visibilityString.toLowerCase()) {
case "private":
visibility = NotificationCompat.VISIBILITY_PRIVATE;
break;
Expand Down Expand Up @@ -429,9 +429,9 @@ public void sendToNotificationCentreWithPicture(Bundle bundle, Bitmap largeIconB

if (!bundle.containsKey("playSound") || bundle.getBoolean("playSound")) {
soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

String soundName = bundle.getString("soundName");

if (soundName != null) {
if (!"default".equalsIgnoreCase(soundName)) {

Expand Down Expand Up @@ -493,7 +493,7 @@ public void sendToNotificationCentreWithPicture(Bundle bundle, Bitmap largeIconB
long vibration = bundle.containsKey("vibration") ? (long) bundle.getDouble("vibration") : DEFAULT_VIBRATION;
if (vibration == 0)
vibration = DEFAULT_VIBRATION;

channel_id = channel_id + "-" + vibration;

vibratePattern = new long[]{0, vibration};
Expand Down Expand Up @@ -582,7 +582,7 @@ public void sendToNotificationCentreWithPicture(Bundle bundle, Bitmap largeIconB
if (!(this.isApplicationInForeground(context) && bundle.getBoolean("ignoreInForeground"))) {
Notification info = notification.build();
info.defaults |= Notification.DEFAULT_LIGHTS;

if (bundle.containsKey("tag")) {
String tag = bundle.getString("tag");
notificationManager.notify(tag, notificationID, info);
Expand Down Expand Up @@ -726,6 +726,33 @@ public WritableArray getDeliveredNotifications() {

}

public WritableArray getScheduledLocalNotifications() {
WritableArray scheduled = Arguments.createArray();

Map<String, ?> scheduledNotifications = scheduledNotificationsPersistence.getAll();

for (Map.Entry<String, ?> entry : scheduledNotifications.entrySet()) {
try {
RNPushNotificationAttributes notification = fromJson(entry.getValue().toString());
WritableMap notificationMap = Arguments.createMap();

notificationMap.putString("title", notification.getTitle());
notificationMap.putString("message", notification.getMessage());
notificationMap.putString("number", notification.getNumber());
notificationMap.putDouble("date", notification.getFireDate());
notificationMap.putString("id", notification.getId());
notificationMap.putString("repeatInterval", notification.getRepeatType());
notificationMap.putString("soundName", notification.getSound());

scheduled.pushMap(notificationMap);
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage());
}
}

return scheduled;
}

public void cancelAllScheduledNotifications() {
Log.i(LOG_TAG, "Cancelling all notifications");

Expand Down Expand Up @@ -758,7 +785,7 @@ private void cancelScheduledNotification(String notificationIDString) {
b.putString("id", notificationIDString);
PendingIntent pendingIntent = toScheduleNotificationIntent(b);

if(pendingIntent != null) {
if (pendingIntent != null) {
getAlarmManager().cancel(pendingIntent);
}

Expand Down Expand Up @@ -888,8 +915,8 @@ public boolean isApplicationInForeground(Context context) {
if (processInfos != null) {
for (RunningAppProcessInfo processInfo : processInfos) {
if (processInfo.processName.equals(context.getPackageName())
&& processInfo.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND
&& processInfo.pkgList.length > 0) {
&& processInfo.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND
&& processInfo.pkgList.length > 0) {
return true;
}
}
Expand Down
17 changes: 10 additions & 7 deletions component/index.android.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

import { NativeModules, DeviceEventEmitter } from "react-native";

var RNPushNotification = NativeModules.RNPushNotification;
var _notifHandlers = new Map();
let RNPushNotification = NativeModules.RNPushNotification;
let _notifHandlers = new Map();

var DEVICE_NOTIF_EVENT = 'remoteNotificationReceived';
var NOTIF_REGISTER_EVENT = 'remoteNotificationsRegistered';
var NOTIF_ACTION_EVENT = 'notificationActionReceived';
var REMOTE_FETCH_EVENT = 'remoteFetch';

var NotificationsComponent = function() {
let NotificationsComponent = function() {

};

Expand Down Expand Up @@ -64,13 +64,13 @@ NotificationsComponent.prototype.checkPermissions = function(callback) {
};

NotificationsComponent.prototype.addEventListener = function(type, handler) {
var listener;
let listener;
if (type === 'notification') {
listener = DeviceEventEmitter.addListener(
DEVICE_NOTIF_EVENT,
function(notifData) {
if (notifData && notifData.dataJSON) {
var data = JSON.parse(notifData.dataJSON);
let data = JSON.parse(notifData.dataJSON);
handler(data);
}
}
Expand All @@ -87,7 +87,7 @@ NotificationsComponent.prototype.addEventListener = function(type, handler) {
REMOTE_FETCH_EVENT,
function(notifData) {
if (notifData && notifData.dataJSON) {
var notificationData = JSON.parse(notifData.dataJSON)
let notificationData = JSON.parse(notifData.dataJSON)
handler(notificationData);
}
}
Expand All @@ -108,7 +108,7 @@ NotificationsComponent.prototype.addEventListener = function(type, handler) {
};

NotificationsComponent.prototype.removeEventListener = function(type, handler) {
var listener = _notifHandlers.get(type);
let listener = _notifHandlers.get(type);
if (!listener) {
return;
}
Expand All @@ -131,6 +131,9 @@ NotificationsComponent.prototype.removeAllDeliveredNotifications = function() {
NotificationsComponent.prototype.getDeliveredNotifications = function(callback) {
RNPushNotification.getDeliveredNotifications(callback);
}
NotificationsComponent.prototype.getScheduledLocalNotifications = function(callback) {
RNPushNotification.getScheduledLocalNotifications(callback);
}
NotificationsComponent.prototype.removeDeliveredNotifications = function(identifiers) {
RNPushNotification.removeDeliveredNotifications(identifiers);
}
Expand Down
7 changes: 7 additions & 0 deletions example/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,13 @@ export default class App extends Component {
}}>
<Text>Abandon Permissions</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.button}
onPress={() => {
this.notif.getScheduledLocalNotifications(notifs => console.log(notifs));
}}>
<Text>Console.Log Scheduled Local Notifications</Text>
</TouchableOpacity>

<View style={styles.spacer}></View>

Expand Down
4 changes: 4 additions & 0 deletions example/NotifService.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,8 @@ export default class NotifService {
abandonPermissions() {
PushNotification.abandonPermissions();
}

getScheduledLocalNotifications(callback) {
PushNotification.getScheduledLocalNotifications(callback);
}
}
6 changes: 3 additions & 3 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ PODS:
- React-cxxreact (= 0.62.2)
- React-jsi (= 0.62.2)
- ReactCommon/callinvoker (= 0.62.2)
- RNCPushNotificationIOS (1.1.1):
- RNCPushNotificationIOS (1.2.2):
- React
- Yoga (1.14.0)
- YogaKit (1.18.1):
Expand Down Expand Up @@ -453,10 +453,10 @@ SPEC CHECKSUMS:
React-RCTText: fae545b10cfdb3d247c36c56f61a94cfd6dba41d
React-RCTVibration: 4356114dbcba4ce66991096e51a66e61eda51256
ReactCommon: ed4e11d27609d571e7eee8b65548efc191116eb3
RNCPushNotificationIOS: a0b6894f4ad9b93d9dac467fdf4d055660ac8a0d
RNCPushNotificationIOS: 4c97a36dbec42dba411cc35e6dac25e34a805fde
Yoga: 3ebccbdd559724312790e7742142d062476b698e
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a

PODFILE CHECKSUM: 56c2537f71f3f02200d6918c542a8e89a0b422fa

COCOAPODS: 1.9.1
COCOAPODS: 1.9.2
5 changes: 3 additions & 2 deletions example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
"ios": "react-native run-ios",
"start": "react-native start",
"test": "jest",
"lint": "eslint ."
"lint": "eslint .",
"pod-install": "cd ios && pod install"
},
"dependencies": {
"@react-native-community/push-notification-ios": "^1.1.1",
"@react-native-community/push-notification-ios": "^1.2.2",
"react": "16.11.0",
"react-native": "0.62.2",
"react-native-push-notification": "git+https://[email protected]/zo0r/react-native-push-notification.git"
Expand Down
38 changes: 37 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ var RNNotificationsComponent = require( './component' );

var RNNotifications = RNNotificationsComponent.component;

var Platform = require('react-native').Platform;
let Platform = require('react-native').Platform;

var Notifications = {
handler: RNNotifications,
Expand Down Expand Up @@ -439,6 +439,42 @@ Notifications.getDeliveredNotifications = function() {
return this.callNative('getDeliveredNotifications', arguments);
}

Notifications.getScheduledLocalNotifications = function(callback) {
const mapNotifications = (notifications) => {
let mappedNotifications = [];
if(notifications?.length > 0) {
if(Platform.OS === 'ios'){
mappedNotifications = notifications.map(notif => {
return ({
soundName: notif.soundName,
repeatInterval: notif.repeatInterval,
id: notif.userInfo?.id,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit confused about this line,
I totally agree iOS should have the notification ID, but by default, userInfo is set to {}.
Not sure if we need to set a default value on userInfo (notificationId ?) or let this field empty when the developer doesn't set it in userInfo...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's why it's optional chained here. It would result in undefined if it is not set. Currently we're using userInfo.id for cancelling notifications by id, so it makes sense to me.

Copy link
Contributor Author

@lukebars lukebars Jun 9, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But setting the id as default when scheduling the notification would be an awesome feature IMHO.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will look into it, thanks for the PR !

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just added the commit here:
6bcc2a9

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good stuff! 🙏

date: new Date(notif.fireDate),
number: notif?.applicationIconBadgeNumber,
message: notif?.alertBody,
title: notif?.alertTitle,
})
})
} else if(Platform.OS === 'android') {
mappedNotifications = notifications.map(notif => {
return ({
soundName: notif.soundName,
repeatInterval: notif.repeatInterval,
id: notif.id,
date: new Date(notif.date),
number: notif.number,
message: notif.message,
title: notif.title,
})
})
}
}
callback(mappedNotifications);
}

return this.callNative('getScheduledLocalNotifications', [mapNotifications]);
}

Notifications.removeDeliveredNotifications = function() {
return this.callNative('removeDeliveredNotifications', arguments);
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"url": "git+ssh://[email protected]:zo0r/react-native-push-notification.git"
},
"dependencies": {
"@react-native-community/push-notification-ios": "^1.2.0"
"@react-native-community/push-notification-ios": "^1.2.2"
},
"peerDependencies": {
"react-native": ">=0.33"
Expand Down
Loading