Merge pull request #1058 from dgruseck/master
[Android] Add the ability to remove notifications based on the tag
This commit is contained in:
commit
321e4a2909
|
@ -1,20 +1,19 @@
|
||||||
---
|
---
|
||||||
name: ⚠️ Bug/Issue report
|
name: ⚠️ Bug/Issue report
|
||||||
about: Please provide as much detail as possible to help us with a bug or issue. Issues
|
about: Please provide as much detail as possible to help us with a bug or issue. Issues
|
||||||
will be closed if they do not follow the template.
|
will be closed if they do not follow the template.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<!---
|
<!---
|
||||||
BEFORE YOU MAKE AN ISSUE
|
BEFORE YOU MAKE AN ISSUE
|
||||||
|
|
||||||
The issue list of this repo is exclusively for bug reports.
|
The issue list of this repo is exclusively for bug reports.
|
||||||
|
|
||||||
1) For feature requests, please use our Canny board: https://react-native-firebase.canny.io/feature-requests
|
1) For feature requests, please use our Canny board: https://react-native-firebase.canny.io/feature-requests
|
||||||
|
|
||||||
2) For questions and support please use our Discord chat: https://discord.gg/C9aK28N or Stack Overflow: https://stackoverflow.com/questions/tagged/react-native-firebase
|
2) For questions and support please use our Discord chat: https://discord.gg/C9aK28N or Stack Overflow: https://stackoverflow.com/questions/tagged/react-native-firebase
|
||||||
|
|
||||||
3) If this is a setup issue then please make sure you've correctly followed the setup guides, most setup issues such as 'duplicate dex files', 'default app has not been initialized' etc are all down to an incorrect setup as the guides haven't been correctly followed.
|
3) If this is a setup issue then please make sure you've correctly followed the setup guides, most setup issues such as 'duplicate dex files', 'default app has not been initialized' etc are all down to an incorrect setup as the guides haven't been correctly followed.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
### Issue
|
### Issue
|
||||||
|
@ -23,7 +22,7 @@ The issue list of this repo is exclusively for bug reports.
|
||||||
|
|
||||||
### Environment
|
### Environment
|
||||||
|
|
||||||
1. Application Target Platform:
|
1. Application Target Platform:
|
||||||
|
|
||||||
<!--- (e.g. iOS, Android, Both) --->
|
<!--- (e.g. iOS, Android, Both) --->
|
||||||
|
|
||||||
|
@ -47,14 +46,14 @@ The issue list of this repo is exclusively for bug reports.
|
||||||
|
|
||||||
<!--- (e.g. database, auth, messaging, analytics etc - or N/A if not applicable) --->
|
<!--- (e.g. database, auth, messaging, analytics etc - or N/A if not applicable) --->
|
||||||
|
|
||||||
7. Are you using `typescript`?
|
7. Are you using `typescript`?
|
||||||
|
|
||||||
<!--- yes/no --->
|
<!--- yes/no --->
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Loving `react-native-firebase`? Please consider supporting them with any of the below:
|
Loving `react-native-firebase`? Please consider supporting them with any of the below:
|
||||||
|
|
||||||
- 👉 Back financially via [Open Collective](https://opencollective.com/react-native-firebase/donate)
|
* 👉 Back financially via [Open Collective](https://opencollective.com/react-native-firebase/donate)
|
||||||
- 👉 Follow [`React Native Firebase`](https://twitter.com/rnfirebase) and [`Invertase`](https://twitter.com/invertaseio) on Twitter
|
* 👉 Follow [`React Native Firebase`](https://twitter.com/rnfirebase) and [`Invertase`](https://twitter.com/invertaseio) on Twitter
|
||||||
- 👉 Star this repo on GitHub ⭐️
|
* 👉 Star this repo on GitHub ⭐️
|
||||||
|
|
12
README.md
12
README.md
|
@ -49,7 +49,7 @@ All in all, RNFirebase provides much faster performance (~2x) over the web SDK a
|
||||||
| **Crashlytics** | ❌ | ✅ | ✅ | ❌ |
|
| **Crashlytics** | ❌ | ✅ | ✅ | ❌ |
|
||||||
| **Crash Reporting** | ✅ | ✅ | ✅ | ❌ |
|
| **Crash Reporting** | ✅ | ✅ | ✅ | ❌ |
|
||||||
| **Dynamic Links** | ❌ | ✅ | ✅ | ❌ |
|
| **Dynamic Links** | ❌ | ✅ | ✅ | ❌ |
|
||||||
| **[Functions Callable](https://firebase.googleblog.com/2018/04/launching-cloud-functions-for-firebase-1-0.html?m=1)** | ❌ | ❌ | ✅ | ✅ |
|
| **[Functions Callable](https://firebase.googleblog.com/2018/04/launching-cloud-functions-for-firebase-1-0.html?m=1)** | ❌ | ❌ | ✅ | ✅ |
|
||||||
| **Invites** | ❌ | ❌ | ✅ | ❌ |
|
| **Invites** | ❌ | ❌ | ✅ | ❌ |
|
||||||
| **Instance ID** | ❌ | ❌ | **?** | ❌ |
|
| **Instance ID** | ❌ | ❌ | **?** | ❌ |
|
||||||
| **Performance Monitoring** | ✅ | ✅ | ✅ | ❌ |
|
| **Performance Monitoring** | ✅ | ✅ | ✅ | ❌ |
|
||||||
|
@ -64,11 +64,11 @@ All in all, RNFirebase provides much faster performance (~2x) over the web SDK a
|
||||||
|
|
||||||
> The table below shows the supported versions of React Native and the Firebase SDKs for different versions of `react-native-firebase`.
|
> The table below shows the supported versions of React Native and the Firebase SDKs for different versions of `react-native-firebase`.
|
||||||
|
|
||||||
| | 2.2.x | 3.3.x | 4.0.x | 4.1.x | 4.2.x |
|
| | 2.2.x | 3.3.x | 4.0.x | 4.1.x | 4.2.x |
|
||||||
| -------------------- | -------- | -------- | -------- | -------- | -------- |
|
| -------------------- | -------- | -------- | -------- | -------- | --------- |
|
||||||
| React Native | 0.47 + | 0.50 + | 0.52 + | 0.52 + | 0.52-55.x |
|
| React Native | 0.47 + | 0.50 + | 0.52 + | 0.52 + | 0.52-55.x |
|
||||||
| Firebase Android SDK | 11.0.0 + | 11.8.0 + | 12.0.0 + | 15.0.0 + | 15.0.0 + |
|
| Firebase Android SDK | 11.0.0 + | 11.8.0 + | 12.0.0 + | 15.0.0 + | 15.0.0 + |
|
||||||
| Firebase iOS SDK | 4.0.0 + | 4.7.0 + | 4.11.0 + | 4.13.0 + | 5.0.0 + |
|
| Firebase iOS SDK | 4.0.0 + | 4.7.0 + | 4.11.0 + | 4.13.0 + | 5.0.0 + |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -279,13 +279,18 @@ public class DisplayNotificationTask extends AsyncTask<Void, Void, Void> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String tag = null;
|
||||||
|
if (android.containsKey("tag")) {
|
||||||
|
tag = android.getString("tag");
|
||||||
|
}
|
||||||
|
|
||||||
// Create the notification intent
|
// Create the notification intent
|
||||||
PendingIntent contentIntent = createIntent(intentClass, notification, android.getString("clickAction"));
|
PendingIntent contentIntent = createIntent(intentClass, notification, android.getString("clickAction"));
|
||||||
nb = nb.setContentIntent(contentIntent);
|
nb = nb.setContentIntent(contentIntent);
|
||||||
|
|
||||||
// Build the notification and send it
|
// Build the notification and send it
|
||||||
Notification builtNotification = nb.build();
|
Notification builtNotification = nb.build();
|
||||||
notificationManager.notify(notificationId.hashCode(), builtNotification);
|
notificationManager.notify(tag, notificationId.hashCode(), builtNotification);
|
||||||
|
|
||||||
if (reactContext != null) {
|
if (reactContext != null) {
|
||||||
Utils.sendEvent(reactContext, "notifications_notification_displayed", Arguments.fromBundle(notification));
|
Utils.sendEvent(reactContext, "notifications_notification_displayed", Arguments.fromBundle(notification));
|
||||||
|
|
|
@ -17,6 +17,7 @@ import android.media.RingtoneManager;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.service.notification.StatusBarNotification;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.app.NotificationCompat;
|
import android.support.v4.app.NotificationCompat;
|
||||||
import android.support.v4.app.RemoteInput;
|
import android.support.v4.app.RemoteInput;
|
||||||
|
@ -153,7 +154,7 @@ public class RNFirebaseNotificationManager {
|
||||||
if (!notification.getBundle("schedule").containsKey("repeated")
|
if (!notification.getBundle("schedule").containsKey("repeated")
|
||||||
|| !notification.getBundle("schedule").getBoolean("repeated")) {
|
|| !notification.getBundle("schedule").getBoolean("repeated")) {
|
||||||
String notificationId = notification.getString("notificationId");
|
String notificationId = notification.getString("notificationId");
|
||||||
preferences.edit().remove(notificationId).apply();;
|
preferences.edit().remove(notificationId).apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Utils.isAppInForeground(context)) {
|
if (Utils.isAppInForeground(context)) {
|
||||||
|
@ -195,6 +196,15 @@ public class RNFirebaseNotificationManager {
|
||||||
promise.resolve(null);
|
promise.resolve(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void removeDeliveredNotificationsByTag(String tag, Promise promise) {
|
||||||
|
StatusBarNotification[] statusBarNotifications = notificationManager.getActiveNotifications();
|
||||||
|
for (StatusBarNotification statusBarNotification : statusBarNotifications) {
|
||||||
|
if (statusBarNotification.getTag() == tag) {
|
||||||
|
notificationManager.cancel(statusBarNotification.getTag(), statusBarNotification.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
promise.resolve(null);
|
||||||
|
}
|
||||||
|
|
||||||
public void rescheduleNotifications() {
|
public void rescheduleNotifications() {
|
||||||
ArrayList<Bundle> bundles = getScheduledNotifications();
|
ArrayList<Bundle> bundles = getScheduledNotifications();
|
||||||
|
|
|
@ -112,6 +112,11 @@ public class RNFirebaseNotifications extends ReactContextBaseJavaModule implemen
|
||||||
notificationManager.removeDeliveredNotification(notificationId, promise);
|
notificationManager.removeDeliveredNotification(notificationId, promise);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ReactMethod
|
||||||
|
public void removeDeliveredNotificationsByTag(String tag, Promise promise) {
|
||||||
|
notificationManager.removeDeliveredNotificationsByTag(tag, promise);
|
||||||
|
}
|
||||||
|
|
||||||
@ReactMethod
|
@ReactMethod
|
||||||
public void setBadge(int badge, Promise promise) {
|
public void setBadge(int badge, Promise promise) {
|
||||||
// Store the badge count for later retrieval
|
// Store the badge count for later retrieval
|
||||||
|
@ -296,6 +301,7 @@ public class RNFirebaseNotifications extends ReactContextBaseJavaModule implemen
|
||||||
}
|
}
|
||||||
if (notification.getTag() != null) {
|
if (notification.getTag() != null) {
|
||||||
androidMap.putString("group", notification.getTag());
|
androidMap.putString("group", notification.getTag());
|
||||||
|
androidMap.putString("tag", notification.getTag());
|
||||||
}
|
}
|
||||||
notificationMap.putMap("android", androidMap);
|
notificationMap.putMap("android", androidMap);
|
||||||
|
|
||||||
|
|
|
@ -372,7 +372,7 @@ RCT_EXPORT_METHOD(setBadge:(NSInteger) number
|
||||||
resolve(nil);
|
resolve(nil);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
RCT_EXPORT_METHOD(jsInitialised:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
|
RCT_EXPORT_METHOD(jsInitialised:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
|
||||||
jsReady = TRUE;
|
jsReady = TRUE;
|
||||||
resolve(nil);
|
resolve(nil);
|
||||||
|
@ -487,11 +487,11 @@ RCT_EXPORT_METHOD(jsInitialised:(RCTPromiseResolveBlock)resolve rejecter:(RCTPro
|
||||||
NSString *identifier = a[@"identifier"];
|
NSString *identifier = a[@"identifier"];
|
||||||
NSURL *url = [NSURL fileURLWithPath:a[@"url"]];
|
NSURL *url = [NSURL fileURLWithPath:a[@"url"]];
|
||||||
NSMutableDictionary *attachmentOptions = nil;
|
NSMutableDictionary *attachmentOptions = nil;
|
||||||
|
|
||||||
if (a[@"options"]) {
|
if (a[@"options"]) {
|
||||||
NSDictionary *options = a[@"options"];
|
NSDictionary *options = a[@"options"];
|
||||||
attachmentOptions = [[NSMutableDictionary alloc] init];
|
attachmentOptions = [[NSMutableDictionary alloc] init];
|
||||||
|
|
||||||
for (id key in options) {
|
for (id key in options) {
|
||||||
if ([key isEqualToString:@"typeHint"]) {
|
if ([key isEqualToString:@"typeHint"]) {
|
||||||
attachmentOptions[UNNotificationAttachmentOptionsTypeHintKey] = options[key];
|
attachmentOptions[UNNotificationAttachmentOptionsTypeHintKey] = options[key];
|
||||||
|
|
|
@ -1213,6 +1213,7 @@ declare module 'react-native-firebase' {
|
||||||
showWhen?: boolean;
|
showWhen?: boolean;
|
||||||
smallIcon?: any;
|
smallIcon?: any;
|
||||||
sortKey?: string;
|
sortKey?: string;
|
||||||
|
tag?: string;
|
||||||
ticker?: string;
|
ticker?: string;
|
||||||
timeoutAfter?: number;
|
timeoutAfter?: number;
|
||||||
usesChronometer?: boolean;
|
usesChronometer?: boolean;
|
||||||
|
@ -1265,6 +1266,7 @@ declare module 'react-native-firebase' {
|
||||||
setShowWhen(showWhen: boolean): Notification;
|
setShowWhen(showWhen: boolean): Notification;
|
||||||
setSmallIcon(icon: string, level?: number): Notification;
|
setSmallIcon(icon: string, level?: number): Notification;
|
||||||
setSortKey(sortKey: string): Notification;
|
setSortKey(sortKey: string): Notification;
|
||||||
|
setTag(tag: string): Notification;
|
||||||
setTicker(ticker: string): Notification;
|
setTicker(ticker: string): Notification;
|
||||||
setTimeoutAfter(timeoutAfter: number): Notification;
|
setTimeoutAfter(timeoutAfter: number): Notification;
|
||||||
setUsesChronometer(usesChronometer: boolean): Notification;
|
setUsesChronometer(usesChronometer: boolean): Notification;
|
||||||
|
|
|
@ -53,6 +53,7 @@ export default class AndroidNotification {
|
||||||
_smallIcon: SmallIcon;
|
_smallIcon: SmallIcon;
|
||||||
_sortKey: string | void;
|
_sortKey: string | void;
|
||||||
// TODO: style: Style; // Need to figure out if this can work
|
// TODO: style: Style; // Need to figure out if this can work
|
||||||
|
_tag: string | void;
|
||||||
_ticker: string | void;
|
_ticker: string | void;
|
||||||
_timeoutAfter: number | void;
|
_timeoutAfter: number | void;
|
||||||
_usesChronometer: boolean | void;
|
_usesChronometer: boolean | void;
|
||||||
|
@ -106,6 +107,7 @@ export default class AndroidNotification {
|
||||||
this._showWhen = data.showWhen;
|
this._showWhen = data.showWhen;
|
||||||
this._smallIcon = data.smallIcon;
|
this._smallIcon = data.smallIcon;
|
||||||
this._sortKey = data.sortKey;
|
this._sortKey = data.sortKey;
|
||||||
|
this._tag = data.tag;
|
||||||
this._ticker = data.ticker;
|
this._ticker = data.ticker;
|
||||||
this._timeoutAfter = data.timeoutAfter;
|
this._timeoutAfter = data.timeoutAfter;
|
||||||
this._usesChronometer = data.usesChronometer;
|
this._usesChronometer = data.usesChronometer;
|
||||||
|
@ -238,6 +240,10 @@ export default class AndroidNotification {
|
||||||
return this._sortKey;
|
return this._sortKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get tag(): ?string {
|
||||||
|
return this._tag;
|
||||||
|
}
|
||||||
|
|
||||||
get ticker(): ?string {
|
get ticker(): ?string {
|
||||||
return this._ticker;
|
return this._ticker;
|
||||||
}
|
}
|
||||||
|
@ -615,6 +621,16 @@ export default class AndroidNotification {
|
||||||
return this._notification;
|
return this._notification;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param tag
|
||||||
|
* @returns {Notification}
|
||||||
|
*/
|
||||||
|
setTag(tag: string): Notification {
|
||||||
|
this._tag = tag;
|
||||||
|
return this._notification;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param ticker
|
* @param ticker
|
||||||
|
@ -719,6 +735,7 @@ export default class AndroidNotification {
|
||||||
smallIcon: this._smallIcon,
|
smallIcon: this._smallIcon,
|
||||||
sortKey: this._sortKey,
|
sortKey: this._sortKey,
|
||||||
// TODO: style: Style,
|
// TODO: style: Style,
|
||||||
|
tag: this._tag,
|
||||||
ticker: this._ticker,
|
ticker: this._ticker,
|
||||||
timeoutAfter: this._timeoutAfter,
|
timeoutAfter: this._timeoutAfter,
|
||||||
usesChronometer: this._usesChronometer,
|
usesChronometer: this._usesChronometer,
|
||||||
|
|
|
@ -92,6 +92,20 @@ export default class AndroidNotifications {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
removeDeliveredNotificationsByTag(tag: string): Promise<void> {
|
||||||
|
if (Platform.OS === 'android') {
|
||||||
|
if (typeof tag !== 'string') {
|
||||||
|
throw new Error(
|
||||||
|
`AndroidNotifications:removeDeliveredNotificationsByTag expects an 'string' but got type ${typeof tag}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return getNativeModule(
|
||||||
|
this._notifications
|
||||||
|
).removeDeliveredNotificationsByTag(tag);
|
||||||
|
}
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
deleteChannelGroup(groupId: string): Promise<void> {
|
deleteChannelGroup(groupId: string): Promise<void> {
|
||||||
if (Platform.OS === 'android') {
|
if (Platform.OS === 'android') {
|
||||||
if (typeof groupId !== 'string') {
|
if (typeof groupId !== 'string') {
|
||||||
|
@ -99,9 +113,7 @@ export default class AndroidNotifications {
|
||||||
`AndroidNotifications:deleteChannelGroup expects an 'string' but got type ${typeof groupId}`
|
`AndroidNotifications:deleteChannelGroup expects an 'string' but got type ${typeof groupId}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return getNativeModule(this._notifications).deleteChannelGroup(
|
return getNativeModule(this._notifications).deleteChannelGroup(groupId);
|
||||||
groupId
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
@ -113,9 +125,7 @@ export default class AndroidNotifications {
|
||||||
`AndroidNotifications:deleteChannel expects an 'string' but got type ${typeof channelId}`
|
`AndroidNotifications:deleteChannel expects an 'string' but got type ${typeof channelId}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return getNativeModule(this._notifications).deleteChannel(
|
return getNativeModule(this._notifications).deleteChannel(channelId);
|
||||||
channelId
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,6 +170,7 @@ export type NativeAndroidNotification = {|
|
||||||
smallIcon: SmallIcon,
|
smallIcon: SmallIcon,
|
||||||
sortKey?: string,
|
sortKey?: string,
|
||||||
// TODO: style: Style,
|
// TODO: style: Style,
|
||||||
|
tag?: string,
|
||||||
ticker?: string,
|
ticker?: string,
|
||||||
timeoutAfter?: number,
|
timeoutAfter?: number,
|
||||||
usesChronometer?: boolean,
|
usesChronometer?: boolean,
|
||||||
|
|
Loading…
Reference in New Issue