Skip to content

Commit b9d6d9a

Browse files
authored
[flutter_local_notifications / flutter_local_notifications_platform_interface] Exposes removeAllPendingNotificationRequests via implementing cancelAllPendingNotifications() (#2639)
* feat(dart): add cancelAllPendingNotifications API to public plugin interface * feat(android): implement cancelAllPendingNotifications via AlarmManager * feat(dart): add cancelAllPendingNotifications API to plugin interface * test(example): add UI to test cancelAllPendingNotifications manually * feat(ios): implement cancelAllPendingNotifications using removeAllPendingNotificationRequests() * feat(macos): implement cancelAllPendingNotifications using removeAllPendingNotificationRequests() * test: add test codes for android, ios, macos * fix: dart analyzer line length exceed issue * fix: add missed symbol * fix: typo * test: github actions workflow(ios integration) * fix: keep consistency of symbol names * docs: update api docs * fix: add if-statement to check supported platforms * fix: remove unnecessary null-check statement
1 parent c1e460b commit b9d6d9a

File tree

10 files changed

+105
-4
lines changed

10 files changed

+105
-4
lines changed

flutter_local_notifications/android/src/main/java/com/dexterous/flutterlocalnotifications/FlutterLocalNotificationsPlugin.java

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,10 @@ public class FlutterLocalNotificationsPlugin
157157
private static final String SHOW_METHOD = "show";
158158
private static final String CANCEL_METHOD = "cancel";
159159
private static final String CANCEL_ALL_METHOD = "cancelAll";
160+
private static final String CANCEL_ALL_PENDING_NOTIFICATIONS_METHOD = "cancelAllPendingNotifications";
160161
private static final String ZONED_SCHEDULE_METHOD = "zonedSchedule";
161162
private static final String PERIODICALLY_SHOW_METHOD = "periodicallyShow";
162-
private static final String PERIODICALLY_SHOW_WITH_DURATION = "periodicallyShowWithDuration";
163+
private static final String PERIODICALLY_SHOW_WITH_DURATION_METHOD = "periodicallyShowWithDuration";
163164
private static final String GET_NOTIFICATION_APP_LAUNCH_DETAILS_METHOD =
164165
"getNotificationAppLaunchDetails";
165166
private static final String REQUEST_NOTIFICATIONS_PERMISSION_METHOD =
@@ -1515,7 +1516,7 @@ public void fail(String message) {
15151516
case PERIODICALLY_SHOW_METHOD:
15161517
repeat(call, result);
15171518
break;
1518-
case PERIODICALLY_SHOW_WITH_DURATION:
1519+
case PERIODICALLY_SHOW_WITH_DURATION_METHOD:
15191520
repeat(call, result);
15201521
break;
15211522
case CANCEL_METHOD:
@@ -1524,6 +1525,9 @@ public void fail(String message) {
15241525
case CANCEL_ALL_METHOD:
15251526
cancelAllNotifications(result);
15261527
break;
1528+
case CANCEL_ALL_PENDING_NOTIFICATIONS_METHOD:
1529+
cancelAllPendingNotifications(result);
1530+
break;
15271531
case PENDING_NOTIFICATION_REQUESTS_METHOD:
15281532
pendingNotificationRequests(result);
15291533
break;
@@ -1839,6 +1843,29 @@ private void cancelAllNotifications(Result result) {
18391843
result.success(null);
18401844
}
18411845

1846+
private void cancelAllPendingNotifications(Result result) {
1847+
ArrayList<NotificationDetails> scheduledNotifications =
1848+
loadScheduledNotifications(applicationContext);
1849+
1850+
if (scheduledNotifications == null || scheduledNotifications.isEmpty()) {
1851+
result.success(null);
1852+
return;
1853+
}
1854+
1855+
AlarmManager alarmManager = getAlarmManager(applicationContext);
1856+
Intent intent = new Intent(applicationContext, ScheduledNotificationReceiver.class);
1857+
1858+
for (NotificationDetails scheduledNotification : scheduledNotifications) {
1859+
PendingIntent pendingIntent =
1860+
getBroadcastPendingIntent(applicationContext, scheduledNotification.id, intent);
1861+
alarmManager.cancel(pendingIntent);
1862+
}
1863+
1864+
saveScheduledNotifications(applicationContext, new ArrayList<>());
1865+
result.success(null);
1866+
}
1867+
1868+
18421869
public void requestNotificationsPermission(@NonNull PermissionRequestListener callback) {
18431870
if (permissionRequestProgress != PermissionRequestProgress.None) {
18441871
callback.fail(PERMISSION_REQUEST_IN_PROGRESS_ERROR_MESSAGE);

flutter_local_notifications/example/lib/main.dart

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,13 @@ class _HomePageState extends State<HomePage> {
442442
await _cancelAllNotifications();
443443
},
444444
),
445+
if (Platform.isAndroid || Platform.isIOS || Platform.isMacOS)
446+
PaddedElevatedButton(
447+
buttonText: 'Cancel all pending notifications',
448+
onPressed: () async {
449+
await _cancelAllPendingNotifications();
450+
},
451+
),
445452
if (!Platform.isWindows) ...repeating.examples(context),
446453
const Divider(),
447454
const Text(
@@ -1891,6 +1898,10 @@ class _HomePageState extends State<HomePage> {
18911898
await flutterLocalNotificationsPlugin.cancelAll();
18921899
}
18931900

1901+
Future<void> _cancelAllPendingNotifications() async {
1902+
await flutterLocalNotificationsPlugin.cancelAllPendingNotifications();
1903+
}
1904+
18941905
Future<void> _showOngoingNotification() async {
18951906
const AndroidNotificationDetails androidNotificationDetails =
18961907
AndroidNotificationDetails('your channel id', 'your channel name',

flutter_local_notifications/ios/flutter_local_notifications/Sources/flutter_local_notifications/FlutterLocalNotificationsPlugin.m

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ @implementation FlutterLocalNotificationsPlugin {
2626
@"periodicallyShowWithDuration";
2727
NSString *const CANCEL_METHOD = @"cancel";
2828
NSString *const CANCEL_ALL_METHOD = @"cancelAll";
29-
NSString *const PENDING_NOTIFICATIONS_REQUESTS_METHOD =
29+
NSString *const CANCEL_ALL_PENDING_NOTIFICATIONS_METHOD = @"cancelAllPendingNotifications";
30+
NSString *const PENDING_NOTIFICATION_REQUESTS_METHOD =
3031
@"pendingNotificationRequests";
3132
NSString *const GET_ACTIVE_NOTIFICATIONS_METHOD = @"getActiveNotifications";
3233
NSString *const GET_NOTIFICATION_APP_LAUNCH_DETAILS_METHOD =
@@ -185,6 +186,8 @@ - (void)handleMethodCall:(FlutterMethodCall *)call
185186
[self cancel:((NSNumber *)call.arguments) result:result];
186187
} else if ([CANCEL_ALL_METHOD isEqualToString:call.method]) {
187188
[self cancelAll:result];
189+
} else if ([CANCEL_ALL_PENDING_NOTIFICATIONS_METHOD isEqualToString:call.method]) {
190+
[self cancelAllPendingNotifications:result];
188191
} else if ([GET_NOTIFICATION_APP_LAUNCH_DETAILS_METHOD
189192
isEqualToString:call.method]) {
190193

@@ -195,7 +198,7 @@ - (void)handleMethodCall:(FlutterMethodCall *)call
195198
notificationAppLaunchDetails[@"notificationResponse"] =
196199
_launchNotificationResponseDict;
197200
result(notificationAppLaunchDetails);
198-
} else if ([PENDING_NOTIFICATIONS_REQUESTS_METHOD
201+
} else if ([PENDING_NOTIFICATION_REQUESTS_METHOD
199202
isEqualToString:call.method]) {
200203
[self pendingNotificationRequests:result];
201204
} else if ([GET_ACTIVE_NOTIFICATIONS_METHOD isEqualToString:call.method]) {
@@ -576,6 +579,13 @@ - (void)cancelAll:(FlutterResult _Nonnull)result API_AVAILABLE(ios(10.0)) {
576579
result(nil);
577580
}
578581

582+
- (void)cancelAllPendingNotifications:(FlutterResult _Nonnull)result API_AVAILABLE(ios(10.0)) {
583+
UNUserNotificationCenter *center =
584+
[UNUserNotificationCenter currentNotificationCenter];
585+
[center removeAllPendingNotificationRequests];
586+
result(nil);
587+
}
588+
579589
- (UNMutableNotificationContent *)
580590
buildStandardNotificationContent:(NSDictionary *)arguments
581591
result:(FlutterResult _Nonnull)result

flutter_local_notifications/lib/src/flutter_local_notifications_plugin.dart

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,17 @@ class FlutterLocalNotificationsPlugin {
302302
await FlutterLocalNotificationsPlatform.instance.cancelAll();
303303
}
304304

305+
/// Cancels/removes all pending notifications.
306+
///
307+
/// This only applies to notifications that have been scheduled.
308+
///
309+
/// The method is supported on Android, iOS and macOS.
310+
/// On other platforms, an [UnimplementedError] will be thrown.
311+
Future<void> cancelAllPendingNotifications() async {
312+
await FlutterLocalNotificationsPlatform.instance
313+
.cancelAllPendingNotifications();
314+
}
315+
305316
/// Schedules a notification to be shown at the specified date and time
306317
/// relative to a specific time zone.
307318
///

flutter_local_notifications/lib/src/platform_flutter_local_notifications.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ class MethodChannelFlutterLocalNotificationsPlugin
4242
@override
4343
Future<void> cancelAll() => _channel.invokeMethod('cancelAll');
4444

45+
@override
46+
Future<void> cancelAllPendingNotifications() async {
47+
await _channel.invokeMethod('cancelAllPendingNotifications');
48+
}
49+
4550
@override
4651
Future<NotificationAppLaunchDetails?>
4752
getNotificationAppLaunchDetails() async {

flutter_local_notifications/macos/flutter_local_notifications/Sources/flutter_local_notifications/FlutterLocalNotificationsPlugin.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,8 @@ public class FlutterLocalNotificationsPlugin: NSObject, FlutterPlugin, UNUserNot
180180
cancel(call, result)
181181
case "cancelAll":
182182
cancelAll(result)
183+
case "cancelAllPendingNotifications":
184+
cancelAllPendingNotifications(result)
183185
case "pendingNotificationRequests":
184186
pendingNotificationRequests(result)
185187
case "getActiveNotifications":
@@ -315,6 +317,12 @@ public class FlutterLocalNotificationsPlugin: NSObject, FlutterPlugin, UNUserNot
315317
result(nil)
316318
}
317319

320+
func cancelAllPendingNotifications(_ result: @escaping FlutterResult) {
321+
let center = UNUserNotificationCenter.current()
322+
center.removeAllPendingNotificationRequests()
323+
result(nil)
324+
}
325+
318326
func pendingNotificationRequests(_ result: @escaping FlutterResult) {
319327
UNUserNotificationCenter.current().getPendingNotificationRequests { (requests) in
320328
var requestDictionaries: [[String: Any?]] = []

flutter_local_notifications/test/android_flutter_local_notifications_test.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2618,6 +2618,13 @@ void main() {
26182618
expect(log, <Matcher>[isMethodCall('cancelAll', arguments: null)]);
26192619
});
26202620

2621+
test('cancelAllPendingNotifications', () async {
2622+
await flutterLocalNotificationsPlugin.cancelAllPendingNotifications();
2623+
expect(log, <Matcher>[
2624+
isMethodCall('cancelAllPendingNotifications', arguments: null)
2625+
]);
2626+
});
2627+
26212628
test('pendingNotificationRequests', () async {
26222629
await flutterLocalNotificationsPlugin.pendingNotificationRequests();
26232630
expect(log, <Matcher>[

flutter_local_notifications/test/ios_flutter_local_notifications_test.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,13 @@ void main() {
748748
expect(log, <Matcher>[isMethodCall('cancelAll', arguments: null)]);
749749
});
750750

751+
test('cancelAllPendingNotifications', () async {
752+
await flutterLocalNotificationsPlugin.cancelAllPendingNotifications();
753+
expect(log, <Matcher>[
754+
isMethodCall('cancelAllPendingNotifications', arguments: null)
755+
]);
756+
});
757+
751758
test('pendingNotificationRequests', () async {
752759
await flutterLocalNotificationsPlugin.pendingNotificationRequests();
753760
expect(log, <Matcher>[

flutter_local_notifications/test/macos_flutter_local_notifications_test.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,13 @@ void main() {
669669
expect(log, <Matcher>[isMethodCall('cancelAll', arguments: null)]);
670670
});
671671

672+
test('cancelAllPendingNotifications', () async {
673+
await flutterLocalNotificationsPlugin.cancelAllPendingNotifications();
674+
expect(log, <Matcher>[
675+
isMethodCall('cancelAllPendingNotifications', arguments: null)
676+
]);
677+
});
678+
672679
test('pendingNotificationRequests', () async {
673680
await flutterLocalNotificationsPlugin.pendingNotificationRequests();
674681
expect(log, <Matcher>[

flutter_local_notifications_platform_interface/lib/flutter_local_notifications_platform_interface.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,14 @@ abstract class FlutterLocalNotificationsPlatform extends PlatformInterface {
7878
throw UnimplementedError('cancelAll() has not been implemented');
7979
}
8080

81+
/// Cancels/removes all pending notifications.
82+
///
83+
/// This only applies to notifications that have been scheduled.
84+
Future<void> cancelAllPendingNotifications() async {
85+
throw UnimplementedError(
86+
'cancelAllPendingNotifications() has not been implemented');
87+
}
88+
8189
/// Returns a list of notifications pending to be delivered/shown
8290
Future<List<PendingNotificationRequest>> pendingNotificationRequests() {
8391
throw UnimplementedError(

0 commit comments

Comments
 (0)