diff --git a/flutter_local_notifications/CHANGELOG.md b/flutter_local_notifications/CHANGELOG.md index ca89de9ce..95188665c 100644 --- a/flutter_local_notifications/CHANGELOG.md +++ b/flutter_local_notifications/CHANGELOG.md @@ -1,3 +1,7 @@ +## [18.0.0-dev.2] + +* [iOS] **Breaking change** Removed `onDidReceiveLocalNotification` callback as this was only relevant on iOS versions older than 10 + ## [18.0.0-dev.1] * **Breaking changes** Bumped minimum Flutter SDK requirement to 3.13. Consequently the minimum OS requirements for each platform has been updated as well diff --git a/flutter_local_notifications/README.md b/flutter_local_notifications/README.md index 32c32e54d..c27d778ea 100644 --- a/flutter_local_notifications/README.md +++ b/flutter_local_notifications/README.md @@ -349,57 +349,6 @@ By design, iOS applications *do not* display notifications while the app is in t For iOS 10+, use the presentation options to control the behaviour for when a notification is triggered while the app is in the foreground. The default settings of the plugin will configure these such that a notification will be displayed when the app is in the foreground. -For older versions of iOS, you need to handle the callback as part of specifying the method that should be fired to the `onDidReceiveLocalNotification` argument when creating an instance `DarwinInitializationSettings` object that is passed to the function for initializing the plugin. - -Here is an example: - -```dart -// initialise the plugin. app_icon needs to be a added as a drawable resource to the Android head project -const AndroidInitializationSettings initializationSettingsAndroid = - AndroidInitializationSettings('app_icon'); -final DarwinInitializationSettings initializationSettingsDarwin = - DarwinInitializationSettings( - onDidReceiveLocalNotification: onDidReceiveLocalNotification); -final LinuxInitializationSettings initializationSettingsLinux = - LinuxInitializationSettings( - defaultActionName: 'Open notification'); -final InitializationSettings initializationSettings = InitializationSettings( - android: initializationSettingsAndroid, - iOS: initializationSettingsDarwin, - linux: initializationSettingsLinux); -flutterLocalNotificationsPlugin.initialize(initializationSettings, - onDidReceiveNotificationResponse: onDidReceiveNotificationResponse); - -... - -void onDidReceiveLocalNotification( - int id, String? title, String? body, String? payload) async { - // display a dialog with the notification details, tap ok to go to another page - showDialog( - context: context, - builder: (BuildContext context) => CupertinoAlertDialog( - title: Text(title??''), - content: Text(body??''), - actions: [ - CupertinoDialogAction( - isDefaultAction: true, - child: Text('Ok'), - onPressed: () async { - Navigator.of(context, rootNavigator: true).pop(); - await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => SecondScreen(payload), - ), - ); - }, - ) - ], - ), - ); -} -``` - ## ❓ Usage Before going on to copy-paste the code snippets in this section, double-check you have configured your application correctly. @@ -576,8 +525,7 @@ FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = const AndroidInitializationSettings initializationSettingsAndroid = AndroidInitializationSettings('app_icon'); final DarwinInitializationSettings initializationSettingsDarwin = - DarwinInitializationSettings( - onDidReceiveLocalNotification: onDidReceiveLocalNotification); + DarwinInitializationSettings(); final LinuxInitializationSettings initializationSettingsLinux = LinuxInitializationSettings( defaultActionName: 'Open notification'); @@ -615,8 +563,6 @@ The `LinuxInitializationSettings` class requires a name for the default action t On iOS and macOS, initialisation may show a prompt to requires users to give the application permission to display notifications (note: permissions don't need to be requested on Android). Depending on when this happens, this may not be the ideal user experience for your application. If so, please refer to the next section on how to work around this. -For an explanation of the `onDidReceiveLocalNotification` callback associated with the `DarwinInitializationSettings` class, please read [this](https://github.com/MaikuB/flutter_local_notifications/tree/master/flutter_local_notifications#handling-notifications-whilst-the-app-is-in-the-foreground). - ### [iOS (all supported versions) and macOS 10.14+] Requesting notification permissions The constructor for the `DarwinInitializationSettings` class has three named parameters (`requestSoundPermission`, `requestBadgePermission` and `requestAlertPermission`) that controls which permissions are being requested. If you want to request permissions at a later point in your application on iOS, set all of the above to false when initialising the plugin. @@ -631,7 +577,6 @@ The constructor for the `DarwinInitializationSettings` class has three named pa requestSoundPermission: false, requestBadgePermission: false, requestAlertPermission: false, - onDidReceiveLocalNotification: onDidReceiveLocalNotification, ); final MacOSInitializationSettings initializationSettingsMacOS = MacOSInitializationSettings( diff --git a/flutter_local_notifications/example/lib/main.dart b/flutter_local_notifications/example/lib/main.dart index 8b9256f2a..b80c04fc2 100644 --- a/flutter_local_notifications/example/lib/main.dart +++ b/flutter_local_notifications/example/lib/main.dart @@ -5,7 +5,6 @@ import 'dart:io'; import 'dart:typed_data'; import 'package:device_info_plus/device_info_plus.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -22,11 +21,6 @@ int id = 0; final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); -/// Streams are created so that app can respond to notification-related events -/// since the plugin is initialised in the `main` function -final StreamController didReceiveLocalNotificationStream = - StreamController.broadcast(); - final StreamController selectNotificationStream = StreamController.broadcast(); @@ -153,17 +147,6 @@ Future main() async { requestAlertPermission: false, requestBadgePermission: false, requestSoundPermission: false, - onDidReceiveLocalNotification: - (int id, String? title, String? body, String? payload) async { - didReceiveLocalNotificationStream.add( - ReceivedNotification( - id: id, - title: title, - body: body, - payload: payload, - ), - ); - }, notificationCategories: darwinNotificationCategories, ); final LinuxInitializationSettings initializationSettingsLinux = @@ -262,7 +245,6 @@ class _HomePageState extends State { super.initState(); _isAndroidPermissionGranted(); _requestPermissions(); - _configureDidReceiveLocalNotificationSubject(); _configureSelectNotificationSubject(); } @@ -311,38 +293,6 @@ class _HomePageState extends State { } } - void _configureDidReceiveLocalNotificationSubject() { - didReceiveLocalNotificationStream.stream - .listen((ReceivedNotification receivedNotification) async { - await showDialog( - context: context, - builder: (BuildContext context) => CupertinoAlertDialog( - title: receivedNotification.title != null - ? Text(receivedNotification.title!) - : null, - content: receivedNotification.body != null - ? Text(receivedNotification.body!) - : null, - actions: [ - CupertinoDialogAction( - isDefaultAction: true, - onPressed: () async { - Navigator.of(context, rootNavigator: true).pop(); - await Navigator.of(context).push( - MaterialPageRoute( - builder: (BuildContext context) => - SecondPage(receivedNotification.payload), - ), - ); - }, - child: const Text('Ok'), - ) - ], - ), - ); - }); - } - void _configureSelectNotificationSubject() { selectNotificationStream.stream.listen((String? payload) async { await Navigator.of(context).push(MaterialPageRoute( @@ -353,7 +303,6 @@ class _HomePageState extends State { @override void dispose() { - didReceiveLocalNotificationStream.close(); selectNotificationStream.close(); super.dispose(); } diff --git a/flutter_local_notifications/ios/Classes/FlutterLocalNotificationsPlugin.h b/flutter_local_notifications/ios/Classes/FlutterLocalNotificationsPlugin.h index a8ab2546d..10689d416 100644 --- a/flutter_local_notifications/ios/Classes/FlutterLocalNotificationsPlugin.h +++ b/flutter_local_notifications/ios/Classes/FlutterLocalNotificationsPlugin.h @@ -2,5 +2,4 @@ #import @interface FlutterLocalNotificationsPlugin : NSObject -+ (void)setRegisterPlugins:(FlutterPluginRegistrantCallback *)callback; @end diff --git a/flutter_local_notifications/ios/Classes/FlutterLocalNotificationsPlugin.m b/flutter_local_notifications/ios/Classes/FlutterLocalNotificationsPlugin.m index e669a3284..237e13de3 100644 --- a/flutter_local_notifications/ios/Classes/FlutterLocalNotificationsPlugin.m +++ b/flutter_local_notifications/ios/Classes/FlutterLocalNotificationsPlugin.m @@ -210,8 +210,8 @@ - (void)handleMethodCall:(FlutterMethodCall *)call } } -- (void)pendingUserNotificationRequests:(FlutterResult _Nonnull)result - NS_AVAILABLE_IOS(10.0) { +- (void)pendingNotificationRequests:(FlutterResult _Nonnull)result + API_AVAILABLE(ios(10.0)) { UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; [center getPendingNotificationRequestsWithCompletionHandler:^( @@ -239,8 +239,77 @@ - (void)pendingUserNotificationRequests:(FlutterResult _Nonnull)result }]; } -- (void)activeUserNotificationRequests:(FlutterResult _Nonnull)result - NS_AVAILABLE_IOS(10.0) { +/// Extracts notification categories from [arguments] and configures them as +/// appropriate. +- (void)configureNotificationCategories:(NSDictionary *_Nonnull)arguments + withCompletionHandler:(void (^)(void))completionHandler + API_AVAILABLE(ios(10.0)) { + if ([self containsKey:@"notificationCategories" forDictionary:arguments]) { + NSMutableSet *notificationCategories = + [NSMutableSet set]; + + NSArray *categories = arguments[@"notificationCategories"]; + NSMutableArray *foregroundActionIdentifiers = + [[NSMutableArray alloc] init]; + + for (NSDictionary *category in categories) { + NSMutableArray *newActions = + [NSMutableArray array]; + + NSArray *actions = category[@"actions"]; + for (NSDictionary *action in actions) { + NSString *type = action[@"type"]; + NSString *identifier = action[@"identifier"]; + NSString *title = action[@"title"]; + UNNotificationActionOptions options = + [Converters parseNotificationActionOptions:action[@"options"]]; + + if ((options & UNNotificationActionOptionForeground) != 0) { + [foregroundActionIdentifiers addObject:identifier]; + } + + if ([type isEqualToString:@"plain"]) { + [newActions + addObject:[UNNotificationAction actionWithIdentifier:identifier + title:title + options:options]]; + } else if ([type isEqualToString:@"text"]) { + NSString *buttonTitle = action[@"buttonTitle"]; + NSString *placeholder = action[@"placeholder"]; + [newActions addObject:[UNTextInputNotificationAction + actionWithIdentifier:identifier + title:title + options:options + textInputButtonTitle:buttonTitle + textInputPlaceholder:placeholder]]; + } + } + + UNNotificationCategory *notificationCategory = [UNNotificationCategory + categoryWithIdentifier:category[@"identifier"] + actions:newActions + intentIdentifiers:@[] + options:[Converters parseNotificationCategoryOptions: + category[@"options"]]]; + + [notificationCategories addObject:notificationCategory]; + } + + if (notificationCategories.count > 0) { + UNUserNotificationCenter *center = + [UNUserNotificationCenter currentNotificationCenter]; + [center setNotificationCategories:notificationCategories]; + [[NSUserDefaults standardUserDefaults] + setObject:foregroundActionIdentifiers + forKey:FOREGROUND_ACTION_IDENTIFIERS]; + } + + completionHandler(); + } +} + +- (void)getActiveNotifications:(FlutterResult _Nonnull)result + API_AVAILABLE(ios(10.0)) { UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; [center getDeliveredNotificationsWithCompletionHandler:^( @@ -269,129 +338,6 @@ - (void)activeUserNotificationRequests:(FlutterResult _Nonnull)result }]; } -- (void)pendingLocalNotificationRequests:(FlutterResult _Nonnull)result { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - NSArray *notifications = - [UIApplication sharedApplication].scheduledLocalNotifications; - NSMutableArray *> - *pendingNotificationRequests = - [[NSMutableArray alloc] initWithCapacity:[notifications count]]; - for (int i = 0; i < [notifications count]; i++) { - UILocalNotification *localNotification = [notifications objectAtIndex:i]; -#pragma clang diagnostic pop - NSMutableDictionary *pendingNotificationRequest = - [[NSMutableDictionary alloc] init]; - pendingNotificationRequest[ID] = - localNotification.userInfo[NOTIFICATION_ID]; - if (localNotification.userInfo[TITLE] != [NSNull null]) { - pendingNotificationRequest[TITLE] = localNotification.userInfo[TITLE]; - } - if (localNotification.alertBody) { - pendingNotificationRequest[BODY] = localNotification.alertBody; - } - if (localNotification.userInfo[PAYLOAD] != [NSNull null]) { - pendingNotificationRequest[PAYLOAD] = localNotification.userInfo[PAYLOAD]; - } - [pendingNotificationRequests addObject:pendingNotificationRequest]; - } - result(pendingNotificationRequests); -} - -- (void)pendingNotificationRequests:(FlutterResult _Nonnull)result { - if (@available(iOS 10.0, *)) { - [self pendingUserNotificationRequests:result]; - } else { - [self pendingLocalNotificationRequests:result]; - } -} - -/// Extracts notification categories from [arguments] and configures them as -/// appropriate. -/// -/// This code will simply return the `completionHandler` if not running on a -/// compatible iOS version or when no categories were specified in [arguments]. -- (void)configureNotificationCategories:(NSDictionary *_Nonnull)arguments - withCompletionHandler:(void (^)(void))completionHandler { - if (@available(iOS 10.0, *)) { - if ([self containsKey:@"notificationCategories" forDictionary:arguments]) { - NSMutableSet *notificationCategories = - [NSMutableSet set]; - - NSArray *categories = arguments[@"notificationCategories"]; - NSMutableArray *foregroundActionIdentifiers = - [[NSMutableArray alloc] init]; - - for (NSDictionary *category in categories) { - NSMutableArray *newActions = - [NSMutableArray array]; - - NSArray *actions = category[@"actions"]; - for (NSDictionary *action in actions) { - NSString *type = action[@"type"]; - NSString *identifier = action[@"identifier"]; - NSString *title = action[@"title"]; - UNNotificationActionOptions options = - [Converters parseNotificationActionOptions:action[@"options"]]; - - if ((options & UNNotificationActionOptionForeground) != 0) { - [foregroundActionIdentifiers addObject:identifier]; - } - - if ([type isEqualToString:@"plain"]) { - [newActions - addObject:[UNNotificationAction actionWithIdentifier:identifier - title:title - options:options]]; - } else if ([type isEqualToString:@"text"]) { - NSString *buttonTitle = action[@"buttonTitle"]; - NSString *placeholder = action[@"placeholder"]; - [newActions addObject:[UNTextInputNotificationAction - actionWithIdentifier:identifier - title:title - options:options - textInputButtonTitle:buttonTitle - textInputPlaceholder:placeholder]]; - } - } - - UNNotificationCategory *notificationCategory = [UNNotificationCategory - categoryWithIdentifier:category[@"identifier"] - actions:newActions - intentIdentifiers:@[] - options:[Converters parseNotificationCategoryOptions: - category[@"options"]]]; - - [notificationCategories addObject:notificationCategory]; - } - - if (notificationCategories.count > 0) { - UNUserNotificationCenter *center = - [UNUserNotificationCenter currentNotificationCenter]; - [center setNotificationCategories:notificationCategories]; - [[NSUserDefaults standardUserDefaults] - setObject:foregroundActionIdentifiers - forKey:FOREGROUND_ACTION_IDENTIFIERS]; - completionHandler(); - } else { - completionHandler(); - } - } - } else { - completionHandler(); - } -} - -- (void)getActiveNotifications:(FlutterResult _Nonnull)result { - if (@available(iOS 10.0, *)) { - [self activeUserNotificationRequests:result]; - } else { - result([FlutterError errorWithCode:UNSUPPORTED_OS_VERSION_ERROR_CODE - message:GET_ACTIVE_NOTIFICATIONS_ERROR_MESSAGE - details:nil]); - } -} - - (void)initialize:(NSDictionary *_Nonnull)arguments result:(FlutterResult _Nonnull)result { bool requestedSoundPermission = false; @@ -511,212 +457,68 @@ - (void)requestPermissionsImpl:(bool)soundPermission result(@NO); return; } - if (@available(iOS 10.0, *)) { - UNUserNotificationCenter *center = - [UNUserNotificationCenter currentNotificationCenter]; + UNUserNotificationCenter *center = + [UNUserNotificationCenter currentNotificationCenter]; - UNAuthorizationOptions authorizationOptions = 0; - if (soundPermission) { - authorizationOptions += UNAuthorizationOptionSound; - } - if (alertPermission) { - authorizationOptions += UNAuthorizationOptionAlert; - } - if (badgePermission) { - authorizationOptions += UNAuthorizationOptionBadge; - } - if (@available(iOS 12.0, *)) { - if (provisionalPermission) { - authorizationOptions += UNAuthorizationOptionProvisional; - } - if (criticalPermission) { - authorizationOptions += UNAuthorizationOptionCriticalAlert; - } - } - [center requestAuthorizationWithOptions:(authorizationOptions) - completionHandler:^(BOOL granted, - NSError *_Nullable error) { - result(@(granted)); - }]; - } else { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - UIUserNotificationType notificationTypes = 0; - if (soundPermission) { - notificationTypes |= UIUserNotificationTypeSound; - } - if (alertPermission) { - notificationTypes |= UIUserNotificationTypeAlert; + UNAuthorizationOptions authorizationOptions = 0; + if (soundPermission) { + authorizationOptions += UNAuthorizationOptionSound; + } + if (alertPermission) { + authorizationOptions += UNAuthorizationOptionAlert; + } + if (badgePermission) { + authorizationOptions += UNAuthorizationOptionBadge; + } + if (@available(iOS 12.0, *)) { + if (provisionalPermission) { + authorizationOptions += UNAuthorizationOptionProvisional; } - if (badgePermission) { - notificationTypes |= UIUserNotificationTypeBadge; + if (criticalPermission) { + authorizationOptions += UNAuthorizationOptionCriticalAlert; } - UIUserNotificationSettings *settings = - [UIUserNotificationSettings settingsForTypes:notificationTypes - categories:nil]; - [[UIApplication sharedApplication] - registerUserNotificationSettings:settings]; -#pragma clang diagnostic pop - result(@YES); } + [center requestAuthorizationWithOptions:(authorizationOptions) + completionHandler:^(BOOL granted, + NSError *_Nullable error) { + result(@(granted)); + }]; } - (void)checkPermissions:(NSDictionary *_Nonnull)arguments + result:(FlutterResult _Nonnull)result + API_AVAILABLE(ios(10.0)) { + UNUserNotificationCenter *center = + [UNUserNotificationCenter currentNotificationCenter]; - result:(FlutterResult _Nonnull)result { - if (@available(iOS 10.0, *)) { - UNUserNotificationCenter *center = - [UNUserNotificationCenter currentNotificationCenter]; - - [center getNotificationSettingsWithCompletionHandler:^( - UNNotificationSettings *_Nonnull settings) { - BOOL isEnabled = - settings.authorizationStatus == UNAuthorizationStatusAuthorized; - BOOL isSoundEnabled = - settings.soundSetting == UNNotificationSettingEnabled; - BOOL isAlertEnabled = - settings.alertSetting == UNNotificationSettingEnabled; - BOOL isBadgeEnabled = - settings.badgeSetting == UNNotificationSettingEnabled; - BOOL isProvisionalEnabled = false; - BOOL isCriticalEnabled = false; - - if (@available(iOS 12.0, *)) { - isProvisionalEnabled = - settings.authorizationStatus == UNAuthorizationStatusProvisional; - isCriticalEnabled = - settings.criticalAlertSetting == UNNotificationSettingEnabled; - } + [center getNotificationSettingsWithCompletionHandler:^( + UNNotificationSettings *_Nonnull settings) { + BOOL isEnabled = + settings.authorizationStatus == UNAuthorizationStatusAuthorized; + BOOL isSoundEnabled = settings.soundSetting == UNNotificationSettingEnabled; + BOOL isAlertEnabled = settings.alertSetting == UNNotificationSettingEnabled; + BOOL isBadgeEnabled = settings.badgeSetting == UNNotificationSettingEnabled; + BOOL isProvisionalEnabled = false; + BOOL isCriticalEnabled = false; - NSDictionary *dict = @{ - IS_NOTIFICATIONS_ENABLED : @(isEnabled), - IS_SOUND_ENABLED : @(isSoundEnabled), - IS_ALERT_ENABLED : @(isAlertEnabled), - IS_BADGE_ENABLED : @(isBadgeEnabled), - IS_PROVISIONAL_ENABLED : @(isProvisionalEnabled), - IS_CRITICAL_ENABLED : @(isCriticalEnabled), - }; - - result(dict); - }]; - } else { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - UIUserNotificationSettings *settings = - UIApplication.sharedApplication.currentUserNotificationSettings; - - if (settings == nil) { - result(@{ - IS_NOTIFICATIONS_ENABLED : @NO, - IS_SOUND_ENABLED : @NO, - IS_ALERT_ENABLED : @NO, - IS_BADGE_ENABLED : @NO, - IS_PROVISIONAL_ENABLED : @NO, - IS_CRITICAL_ENABLED : @NO, - }); - return; + if (@available(iOS 12.0, *)) { + isProvisionalEnabled = + settings.authorizationStatus == UNAuthorizationStatusProvisional; + isCriticalEnabled = + settings.criticalAlertSetting == UNNotificationSettingEnabled; } - UIUserNotificationType types = settings.types; - - BOOL isEnabled = types != UIUserNotificationTypeNone; - BOOL isSoundEnabled = types & UIUserNotificationTypeSound; - BOOL isAlertEnabled = types & UIUserNotificationTypeAlert; - BOOL isBadgeEnabled = types & UIUserNotificationTypeBadge; - NSDictionary *dict = @{ IS_NOTIFICATIONS_ENABLED : @(isEnabled), IS_SOUND_ENABLED : @(isSoundEnabled), IS_ALERT_ENABLED : @(isAlertEnabled), IS_BADGE_ENABLED : @(isBadgeEnabled), - IS_PROVISIONAL_ENABLED : @NO, - IS_CRITICAL_ENABLED : @NO, + IS_PROVISIONAL_ENABLED : @(isProvisionalEnabled), + IS_CRITICAL_ENABLED : @(isCriticalEnabled), }; result(dict); -#pragma clang diagnostic pop - } -} - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" -- (UILocalNotification *)buildStandardUILocalNotification: - (NSDictionary *)arguments { - UILocalNotification *notification = [[UILocalNotification alloc] init]; -#pragma clang diagnostic pop - if ([self containsKey:BODY forDictionary:arguments]) { - notification.alertBody = arguments[BODY]; - } - - NSString *title; - if ([self containsKey:TITLE forDictionary:arguments]) { - title = arguments[TITLE]; - if (@available(iOS 8.2, *)) { - notification.alertTitle = title; - } - } - - NSDictionary *persistedPresentationOptions = - [[NSUserDefaults standardUserDefaults] - dictionaryForKey:PRESENTATION_OPTIONS_USER_DEFAULTS]; - bool presentAlert = false; - bool presentSound = false; - bool presentBadge = false; - bool presentBanner = false; - bool presentList = false; - if (persistedPresentationOptions != nil) { - presentAlert = [persistedPresentationOptions[PRESENT_ALERT] isEqual:@YES]; - presentSound = [persistedPresentationOptions[PRESENT_SOUND] isEqual:@YES]; - presentBadge = [persistedPresentationOptions[PRESENT_BADGE] isEqual:@YES]; - presentBanner = [persistedPresentationOptions[PRESENT_BANNER] isEqual:@YES]; - presentList = [persistedPresentationOptions[PRESENT_LIST] isEqual:@YES]; - } - if (arguments[PLATFORM_SPECIFICS] != [NSNull null]) { - NSDictionary *platformSpecifics = arguments[PLATFORM_SPECIFICS]; - - if ([self containsKey:PRESENT_ALERT forDictionary:platformSpecifics]) { - presentAlert = [[platformSpecifics objectForKey:PRESENT_ALERT] boolValue]; - } - if ([self containsKey:PRESENT_SOUND forDictionary:platformSpecifics]) { - presentSound = [[platformSpecifics objectForKey:PRESENT_SOUND] boolValue]; - } - if ([self containsKey:PRESENT_BADGE forDictionary:platformSpecifics]) { - presentBadge = [[platformSpecifics objectForKey:PRESENT_BADGE] boolValue]; - } - if ([self containsKey:PRESENT_BANNER forDictionary:platformSpecifics]) { - presentBanner = - [[platformSpecifics objectForKey:PRESENT_BANNER] boolValue]; - } - if ([self containsKey:PRESENT_LIST forDictionary:platformSpecifics]) { - presentList = [[platformSpecifics objectForKey:PRESENT_LIST] boolValue]; - } - - if ([self containsKey:BADGE_NUMBER forDictionary:platformSpecifics]) { - notification.applicationIconBadgeNumber = - [platformSpecifics[BADGE_NUMBER] integerValue]; - } - - if ([self containsKey:SOUND forDictionary:platformSpecifics]) { - notification.soundName = [platformSpecifics[SOUND] stringValue]; - } - } - - if (presentSound && notification.soundName == nil) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - notification.soundName = UILocalNotificationDefaultSoundName; -#pragma clang diagnostic pop - } - - notification.userInfo = [self buildUserDict:arguments[ID] - title:title - presentAlert:presentAlert - presentSound:presentSound - presentBadge:presentBadge - presentBanner:presentBanner - presentList:presentList - payload:arguments[PAYLOAD]]; - return notification; + }]; } - (NSString *)getIdentifier:(id)arguments { @@ -724,183 +526,56 @@ - (NSString *)getIdentifier:(id)arguments { } - (void)show:(NSDictionary *_Nonnull)arguments - result:(FlutterResult _Nonnull)result { - if (@available(iOS 10.0, *)) { - UNMutableNotificationContent *content = - [self buildStandardNotificationContent:arguments result:result]; - [self addNotificationRequest:[self getIdentifier:arguments] - content:content - result:result - trigger:nil]; - } else { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - UILocalNotification *notification = - [self buildStandardUILocalNotification:arguments]; - [[UIApplication sharedApplication] - presentLocalNotificationNow:notification]; -#pragma clang diagnostic pop - result(nil); - } + result:(FlutterResult _Nonnull)result API_AVAILABLE(ios(10.0)) { + UNMutableNotificationContent *content = + [self buildStandardNotificationContent:arguments result:result]; + [self addNotificationRequest:[self getIdentifier:arguments] + content:content + result:result + trigger:nil]; } - (void)zonedSchedule:(NSDictionary *_Nonnull)arguments - result:(FlutterResult _Nonnull)result { - if (@available(iOS 10.0, *)) { - UNMutableNotificationContent *content = - [self buildStandardNotificationContent:arguments result:result]; - UNCalendarNotificationTrigger *trigger = - [self buildUserNotificationCalendarTrigger:arguments]; - [self addNotificationRequest:[self getIdentifier:arguments] - content:content - result:result - trigger:trigger]; - - } else { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - UILocalNotification *notification = - [self buildStandardUILocalNotification:arguments]; -#pragma clang diagnostic pop - NSString *scheduledDateTime = arguments[SCHEDULED_DATE_TIME]; - NSString *timeZoneName = arguments[TIME_ZONE_NAME]; - NSNumber *matchDateComponents = arguments[MATCH_DATE_TIME_COMPONENTS]; - NSNumber *uiLocalNotificationDateInterpretation = - arguments[UILOCALNOTIFICATION_DATE_INTERPRETATION]; - NSTimeZone *timezone = [NSTimeZone timeZoneWithName:timeZoneName]; - NSISO8601DateFormatter *dateFormatter = - [[NSISO8601DateFormatter alloc] init]; - [dateFormatter setTimeZone:timezone]; - dateFormatter.formatOptions = NSISO8601DateFormatWithFractionalSeconds | - NSISO8601DateFormatWithInternetDateTime; - NSDate *date = [dateFormatter dateFromString:scheduledDateTime]; - notification.fireDate = date; - if (uiLocalNotificationDateInterpretation != nil) { - if ([uiLocalNotificationDateInterpretation integerValue] == - AbsoluteGMTTime) { - notification.timeZone = nil; - } else if ([uiLocalNotificationDateInterpretation integerValue] == - WallClockTime) { - notification.timeZone = timezone; - } - } - if (matchDateComponents != nil) { - if ([matchDateComponents integerValue] == Time) { - notification.repeatInterval = NSCalendarUnitDay; - } else if ([matchDateComponents integerValue] == DayOfWeekAndTime) { - notification.repeatInterval = NSCalendarUnitWeekOfYear; - } else if ([matchDateComponents integerValue] == DayOfMonthAndTime) { - notification.repeatInterval = NSCalendarUnitMonth; - } else if ([matchDateComponents integerValue] == DateAndTime) { - notification.repeatInterval = NSCalendarUnitYear; - } - } -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - [[UIApplication sharedApplication] scheduleLocalNotification:notification]; -#pragma clang diagnostic pop - result(nil); - } + result:(FlutterResult _Nonnull)result API_AVAILABLE(ios(10.0)) { + UNMutableNotificationContent *content = + [self buildStandardNotificationContent:arguments result:result]; + UNCalendarNotificationTrigger *trigger = + [self buildUserNotificationCalendarTrigger:arguments]; + [self addNotificationRequest:[self getIdentifier:arguments] + content:content + result:result + trigger:trigger]; } - (void)periodicallyShow:(NSDictionary *_Nonnull)arguments - result:(FlutterResult _Nonnull)result { - if (@available(iOS 10.0, *)) { - UNMutableNotificationContent *content = - [self buildStandardNotificationContent:arguments result:result]; - UNTimeIntervalNotificationTrigger *trigger = - [self buildUserNotificationTimeIntervalTrigger:arguments]; - [self addNotificationRequest:[self getIdentifier:arguments] - content:content - result:result - trigger:trigger]; - } else { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - UILocalNotification *notification = - [self buildStandardUILocalNotification:arguments]; -#pragma clang diagnostic pop - NSTimeInterval timeInterval = 0; - if ([self containsKey:REPEAT_INTERVAL_MILLISECODNS - forDictionary:arguments]) { - NSInteger repeatIntervalMilliseconds = - [arguments[REPEAT_INTERVAL_MILLISECODNS] integerValue]; - timeInterval = repeatIntervalMilliseconds / 1000.0; - notification.repeatInterval = NSCalendarUnitSecond; - } - switch ([arguments[REPEAT_INTERVAL] integerValue]) { - case EveryMinute: - timeInterval = 60; - notification.repeatInterval = NSCalendarUnitMinute; - break; - case Hourly: - timeInterval = 60 * 60; - notification.repeatInterval = NSCalendarUnitHour; - break; - case Daily: - timeInterval = 60 * 60 * 24; - notification.repeatInterval = NSCalendarUnitDay; - break; - case Weekly: - timeInterval = 60 * 60 * 24 * 7; - notification.repeatInterval = NSCalendarUnitWeekOfYear; - break; - } - notification.fireDate = [NSDate dateWithTimeIntervalSinceNow:timeInterval]; -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - [[UIApplication sharedApplication] scheduleLocalNotification:notification]; -#pragma clang diagnostic pop - result(nil); - } + result:(FlutterResult _Nonnull)result + API_AVAILABLE(ios(10.0)) { + UNMutableNotificationContent *content = + [self buildStandardNotificationContent:arguments result:result]; + UNTimeIntervalNotificationTrigger *trigger = + [self buildUserNotificationTimeIntervalTrigger:arguments]; + [self addNotificationRequest:[self getIdentifier:arguments] + content:content + result:result + trigger:trigger]; } -- (void)cancel:(NSNumber *)id result:(FlutterResult _Nonnull)result { - if (@available(iOS 10.0, *)) { - UNUserNotificationCenter *center = - [UNUserNotificationCenter currentNotificationCenter]; - NSArray *idsToRemove = - [[NSArray alloc] initWithObjects:[id stringValue], nil]; - [center removePendingNotificationRequestsWithIdentifiers:idsToRemove]; - [center removeDeliveredNotificationsWithIdentifiers:idsToRemove]; - } else { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - NSArray *notifications = - [UIApplication sharedApplication].scheduledLocalNotifications; -#pragma clang diagnostic pop - for (int i = 0; i < [notifications count]; i++) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - UILocalNotification *localNotification = [notifications objectAtIndex:i]; -#pragma clang diagnostic pop - NSNumber *userInfoNotificationId = - localNotification.userInfo[NOTIFICATION_ID]; - if ([userInfoNotificationId longValue] == [id longValue]) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - [[UIApplication sharedApplication] - cancelLocalNotification:localNotification]; -#pragma clang diagnostic pop - break; - } - } - } +- (void)cancel:(NSNumber *)id + result:(FlutterResult _Nonnull)result API_AVAILABLE(ios(10.0)) { + UNUserNotificationCenter *center = + [UNUserNotificationCenter currentNotificationCenter]; + NSArray *idsToRemove = + [[NSArray alloc] initWithObjects:[id stringValue], nil]; + [center removePendingNotificationRequestsWithIdentifiers:idsToRemove]; + [center removeDeliveredNotificationsWithIdentifiers:idsToRemove]; result(nil); } -- (void)cancelAll:(FlutterResult _Nonnull)result { - if (@available(iOS 10.0, *)) { - UNUserNotificationCenter *center = - [UNUserNotificationCenter currentNotificationCenter]; - [center removeAllPendingNotificationRequests]; - [center removeAllDeliveredNotifications]; - } else { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - [[UIApplication sharedApplication] cancelAllLocalNotifications]; -#pragma clang diagnostic pop - } +- (void)cancelAll:(FlutterResult _Nonnull)result API_AVAILABLE(ios(10.0)) { + UNUserNotificationCenter *center = + [UNUserNotificationCenter currentNotificationCenter]; + [center removeAllPendingNotificationRequests]; + [center removeAllDeliveredNotifications]; result(nil); } @@ -1043,7 +718,7 @@ - (void)cancelAll:(FlutterResult _Nonnull)result { } - (UNCalendarNotificationTrigger *)buildUserNotificationCalendarTrigger: - (id)arguments NS_AVAILABLE_IOS(10.0) { + (id)arguments API_AVAILABLE(ios(10.0)) { NSString *scheduledDateTime = arguments[SCHEDULED_DATE_TIME]; NSString *timeZoneName = arguments[TIME_ZONE_NAME]; @@ -1205,7 +880,7 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler: (void (^)(UNNotificationPresentationOptions))completionHandler - NS_AVAILABLE_IOS(10.0) { + API_AVAILABLE(ios(10.0)) { if (![self isAFlutterLocalNotification:notification.request.content.userInfo]) { return; @@ -1248,7 +923,7 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center } - (NSMutableDictionary *)extractNotificationResponseDict: - (UNNotificationResponse *_Nonnull)response NS_AVAILABLE_IOS(10.0) { + (UNNotificationResponse *_Nonnull)response API_AVAILABLE(ios(10.0)) { NSMutableDictionary *notitificationResponseDict = [[NSMutableDictionary alloc] init]; NSInteger notificationId = @@ -1280,7 +955,7 @@ - (NSMutableDictionary *)extractNotificationResponseDict: - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler - NS_AVAILABLE_IOS(10.0) { + API_AVAILABLE(ios(10.0)) { if (![self isAFlutterLocalNotification:response.notification.request.content .userInfo]) { return; @@ -1330,58 +1005,4 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center } } -#pragma mark - AppDelegate -- (BOOL)application:(UIApplication *)application - didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - if (launchOptions != nil) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - UILocalNotification *launchNotification = - (UILocalNotification *)[launchOptions - objectForKey:UIApplicationLaunchOptionsLocalNotificationKey]; -#pragma clang diagnostic pop - _launchingAppFromNotification = - launchNotification != nil && - [self isAFlutterLocalNotification:launchNotification.userInfo]; - if (_launchingAppFromNotification) { - _launchNotificationResponseDict = [[NSMutableDictionary alloc] init]; - _launchNotificationResponseDict[@"notificationId"] = - launchNotification.userInfo[NOTIFICATION_ID]; - _launchNotificationResponseDict[PAYLOAD] = - launchNotification.userInfo[PAYLOAD]; - _launchNotificationResponseDict[NOTIFICATION_RESPONSE_TYPE] = - [NSNumber numberWithInteger:0]; - } - } - - return YES; -} - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-implementations" -#pragma clang diagnostic ignored "-Wdeprecated-declarations" -- (void)application:(UIApplication *)application - didReceiveLocalNotification:(UILocalNotification *)notification { -#pragma clang diagnostic pop - if (@available(iOS 10.0, *)) { - return; - } - if (![self isAFlutterLocalNotification:notification.userInfo]) { - return; - } - - NSMutableDictionary *arguments = [[NSMutableDictionary alloc] init]; - arguments[ID] = notification.userInfo[NOTIFICATION_ID]; - if (notification.userInfo[TITLE] != [NSNull null]) { - arguments[TITLE] = notification.userInfo[TITLE]; - } - if (notification.alertBody != nil) { - arguments[BODY] = notification.alertBody; - } - if (notification.userInfo[PAYLOAD] != [NSNull null]) { - arguments[PAYLOAD] = notification.userInfo[PAYLOAD]; - } - [_channel invokeMethod:DID_RECEIVE_LOCAL_NOTIFICATION arguments:arguments]; -} - @end diff --git a/flutter_local_notifications/lib/src/platform_flutter_local_notifications.dart b/flutter_local_notifications/lib/src/platform_flutter_local_notifications.dart index 11835eddf..fcc059825 100644 --- a/flutter_local_notifications/lib/src/platform_flutter_local_notifications.dart +++ b/flutter_local_notifications/lib/src/platform_flutter_local_notifications.dart @@ -25,7 +25,6 @@ import 'platform_specifics/darwin/mappers.dart'; import 'platform_specifics/darwin/notification_details.dart'; import 'platform_specifics/darwin/notification_enabled_options.dart'; import 'platform_specifics/ios/enums.dart'; -import 'typedefs.dart'; import 'types.dart'; import 'tz_datetime_mapper.dart'; @@ -609,7 +608,6 @@ class IOSFlutterLocalNotificationsPlugin } DidReceiveNotificationResponseCallback? _onDidReceiveNotificationResponse; - DidReceiveLocalNotificationCallback? _onDidReceiveLocalNotification; /// Initializes the plugin. /// @@ -645,8 +643,6 @@ class IOSFlutterLocalNotificationsPlugin onDidReceiveBackgroundNotificationResponse, }) async { _onDidReceiveNotificationResponse = onDidReceiveNotificationResponse; - _onDidReceiveLocalNotification = - initializationSettings.onDidReceiveLocalNotification; _channel.setMethodCallHandler(_handleMethod); final Map arguments = initializationSettings.toMap(); @@ -823,13 +819,6 @@ class IOSFlutterLocalNotificationsPlugin ), ); break; - case 'didReceiveLocalNotification': - _onDidReceiveLocalNotification!( - call.arguments['id'], - call.arguments['title'], - call.arguments['body'], - call.arguments['payload']); - break; default: return await Future.error('Method not defined'); } diff --git a/flutter_local_notifications/lib/src/platform_specifics/darwin/initialization_settings.dart b/flutter_local_notifications/lib/src/platform_specifics/darwin/initialization_settings.dart index 362bba288..cdfa6239c 100644 --- a/flutter_local_notifications/lib/src/platform_specifics/darwin/initialization_settings.dart +++ b/flutter_local_notifications/lib/src/platform_specifics/darwin/initialization_settings.dart @@ -1,4 +1,3 @@ -import '../../typedefs.dart'; import 'notification_category.dart'; /// Plugin initialization settings for Darwin-based operating systems @@ -16,7 +15,6 @@ class DarwinInitializationSettings { this.defaultPresentBadge = true, this.defaultPresentBanner = true, this.defaultPresentList = true, - this.onDidReceiveLocalNotification, this.notificationCategories = const [], }); @@ -125,12 +123,6 @@ class DarwinInitializationSettings { /// On macOS, this property is only applicable to macOS 11 or newer. final bool defaultPresentList; - /// Callback for handling when a notification is triggered while the app is - /// in the foreground. - /// - /// This property is only applicable to iOS versions older than 10. - final DidReceiveLocalNotificationCallback? onDidReceiveLocalNotification; - /// Configure the notification categories ([DarwinNotificationCategory]) /// available. This allows for fine-tuning of preview display. /// diff --git a/flutter_local_notifications/pubspec.yaml b/flutter_local_notifications/pubspec.yaml index 4f825539d..9bf3f5418 100644 --- a/flutter_local_notifications/pubspec.yaml +++ b/flutter_local_notifications/pubspec.yaml @@ -2,7 +2,7 @@ name: flutter_local_notifications description: A cross platform plugin for displaying and scheduling local notifications for Flutter applications with the ability to customise for each platform. -version: 18.0.0-dev.1 +version: 18.0.0-dev.2 homepage: https://github.com/MaikuB/flutter_local_notifications/tree/master/flutter_local_notifications issue_tracker: https://github.com/MaikuB/flutter_local_notifications/issues