Schedule Number of Local Notifications

Schedule number of Local Notifications

I've created app with local notifications and in this case user was notified every 20/40/60 minutes in given time interval (eg. 8:00-20:00). The solution was to generate up to 64 notification through whole day and set repeatInterval of UILocalNotification to NSCalendarUnitDay. Of course if you need to use more sophisticated notification pattern, this is not the way to go.

Also It's worth to mention, that since iOS7 I had to, due to client requirements, implement rescheduling of notifications in background app refresh.

How to schedule multiple time specific local notifications in flutter

After hours of research I have solved this problem.
The full code is below.

import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:flutter_native_timezone/flutter_native_timezone.dart';
import 'package:timezone/data/latest.dart' as tz;
import 'package:timezone/timezone.dart' as tz;

class NotificationHelper {
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();

/// Initialize notification
initializeNotification() async {
_configureLocalTimeZone();
const IOSInitializationSettings initializationSettingsIOS = IOSInitializationSettings();

const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings("ic_launcher");

const InitializationSettings initializationSettings = InitializationSettings(
iOS: initializationSettingsIOS,
android: initializationSettingsAndroid,
);
await flutterLocalNotificationsPlugin.initialize(initializationSettings);
}

/// Set right date and time for notifications
tz.TZDateTime _convertTime(int hour, int minutes) {
final tz.TZDateTime now = tz.TZDateTime.now(tz.local);
tz.TZDateTime scheduleDate = tz.TZDateTime(
tz.local,
now.year,
now.month,
now.day,
hour,
minutes,
);
if (scheduleDate.isBefore(now)) {
scheduleDate = scheduleDate.add(const Duration(days: 1));
}
return scheduleDate;
}

Future<void> _configureLocalTimeZone() async {
tz.initializeTimeZones();
final String timeZone = await FlutterNativeTimezone.getLocalTimezone();
tz.setLocalLocation(tz.getLocation(timeZone));
}

/// Scheduled Notification
scheduledNotification({
required int hour,
required int minutes,
required int id,
required String sound,
}) async {
await flutterLocalNotificationsPlugin.zonedSchedule(
id,
'It\'s time to drink water!',
'After drinking, touch the cup to confirm',
_convertTime(hour, minutes),
NotificationDetails(
android: AndroidNotificationDetails(
'your channel id $sound',
'your channel name',
channelDescription: 'your channel description',
importance: Importance.max,
priority: Priority.high,
sound: RawResourceAndroidNotificationSound(sound),
),
iOS: IOSNotificationDetails(sound: '$sound.mp3'),
),
androidAllowWhileIdle: true,
uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime,
matchDateTimeComponents: DateTimeComponents.time,
payload: 'It could be anything you pass',
);
}

/// Request IOS permissions
void requestIOSPermissions() {
flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<IOSFlutterLocalNotificationsPlugin>()
?.requestPermissions(
alert: true,
badge: true,
sound: true,
);
}

cancelAll() async => await flutterLocalNotificationsPlugin.cancelAll();
cancel(id) async => await flutterLocalNotificationsPlugin.cancel(id);
}

add your custom times like this

for (int i = 0; i < _provider.getScheduleRecords.length; i++) {
_notificationHelper.scheduledNotification(
hour: int.parse(_provider.getScheduleRecords[i].time.split(":")[0]),
minutes: int.parse(_provider.getScheduleRecords[i].time.split(":")[1]),
id: _provider.getScheduleRecords[i].id,
sound: 'sound0',
);
}

iOS local notification base on day, time frame and number of times?

If you want to schedule multiple notifications, you need to create multiple notification triggers and register them.

something like:

// Simple extension if you have to create multiple of the same object
extension DateComponents {
static func triggerFor(hour: Int, minute: Int) -> DateComponents {
var component = DateComponents()
component.calendar = Calendar.current
component.hour = hour
component.minute = minute
component.weekday = 1
return component
}
}

// Add each trigger into an array with the correct date component
let triggers = [
UNCalendarNotificationTrigger(dateMatching: DateComponents.triggerFor(hour: 1, minute: 0), repeats: true),
UNCalendarNotificationTrigger(dateMatching: DateComponents.triggerFor(hour: 2, minute: 0), repeats: true),
UNCalendarNotificationTrigger(dateMatching: DateComponents.triggerFor(hour: 3, minute: 0), repeats: true),
UNCalendarNotificationTrigger(dateMatching: DateComponents.triggerFor(hour: 4, minute: 0), repeats: true),
UNCalendarNotificationTrigger(dateMatching: DateComponents.triggerFor(hour: 5, minute: 0), repeats: true)
]

// Iterate through the array and register the notification with the system
for trigger in triggers {
// Create the content of the notification
let content = UNMutableNotificationContent()
content.title = "My Notification Title"
content.body = "Body of Notification"

// Create the request
let uuidString = UUID().uuidString
let request = UNNotificationRequest(identifier: uuidString,
content: content, trigger: trigger)

// Schedule the request with the system.
let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.add(request) { (error) in
if error != nil {
// Handle any errors.
}
}
}

Schedule local notification every n days (timezone safe)

You can set them up upfront using UNCalendarNotificationTrigger for an n number of times and using an adjusted calendar for the current timeZone

import SwiftUI

class NotificationManager: NSObject, UNUserNotificationCenterDelegate{
static let shared: NotificationManager = NotificationManager()
let notificationCenter = UNUserNotificationCenter.current()

private override init(){
super.init()
requestNotification()
notificationCenter.delegate = self
getnotifications()
}

func requestNotification() {
print(#function)
notificationCenter.requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in

if let error = error {
// Handle the error here.
print(error)
}

// Enable or disable features based on the authorization.
}
}
/// Uses [.day, .hour, .minute, .second] in current timeZone
func scheduleCalendarNotification(title: String, body: String, date: Date, repeats: Bool = false, identifier: String) {
print(#function)

let content = UNMutableNotificationContent()
content.title = title
content.body = body

let calendar = NSCalendar.current

let components = calendar.dateComponents([.day, .hour, .minute, .second], from: date)

let trigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: repeats)

let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
notificationCenter.add(request) { (error) in
if error != nil {
print(error!)
}
}
}
///Sets up multiple calendar notification based on a date
func recurringNotification(title: String, body: String, date: Date, identifier: String, everyXDays: Int, count: Int){
print(#function)
for n in 0..<count{
print(n)
let newDate = date.addingTimeInterval(TimeInterval(60*60*24*everyXDays*n))
//Idenfier must be unique so I added the n
scheduleCalendarNotification(title: title, body: body, date: newDate, identifier: identifier + n.description)
print(newDate)
}
}
///Prints to console schduled notifications
func getnotifications(){
notificationCenter.getPendingNotificationRequests { request in
for req in request{
if req.trigger is UNCalendarNotificationTrigger{
print((req.trigger as! UNCalendarNotificationTrigger).nextTriggerDate()?.description ?? "invalid next trigger date")
}
}
}
}

func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {

completionHandler(.banner)
}
}
class ZuluNotTriggerViewModel:NSObject, ObservableObject, UNUserNotificationCenterDelegate{
@Published var currentTime: Date = Date()
let notificationMgr = NotificationManager.shared


///Sets up multiple calendar notification based on a date
func recurringNotification(title: String, body: String, date: Date, identifier: String, everyXDays: Int, count: Int){
print(#function)
notificationMgr.recurringNotification(title: title, body: body, date: date, identifier: identifier, everyXDays: everyXDays, count: count)

//just for show now so you can see the current date in ui
self.currentTime = Date()
}
///Prints to console schduled notifications
func getnotifications(){
notificationMgr.getnotifications()
}

}
struct ZuluNotTriggerView: View {
@StateObject var vm: ZuluNotTriggerViewModel = ZuluNotTriggerViewModel()
var body: some View {
VStack{
Button(vm.currentTime.description, action: {
vm.currentTime = Date()
})
Button("schedule-notification", action: {
let twoMinOffset = 120
//first one will be in 120 seconds
//gives time to change settings in simulator
//initial day, hour, minute, second
let initialDate = Date().addingTimeInterval(TimeInterval(twoMinOffset))
//relevant components will be day, hour minutes, seconds
vm.recurringNotification(title: "test", body: "repeat body", date: initialDate, identifier: "test", everyXDays: 2, count: 10)
})

Button("see notification", action: {
vm.getnotifications()
})
}
}
}

struct ZuluNotTriggerView_Previews: PreviewProvider {
static var previews: some View {
ZuluNotTriggerView()
}
}

Schedule Local Notifications at Specific times in the day

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
let settings = UIUserNotificationSettings(forTypes: .Badge, categories: nil)
UIApplication.sharedApplication().registerUserNotificationSettings(settings)

let localNotification1 = UILocalNotification()
localNotification1.alertBody = "Your alert message 111"
localNotification1.timeZone = NSTimeZone.defaultTimeZone()
localNotification1.fireDate = self.getEightAMDate()
UIApplication.sharedApplication().scheduleLocalNotification(localNotification1)

let localNotification2 = UILocalNotification()
localNotification2.alertBody = "Your alert message22"
localNotification2.timeZone = NSTimeZone.defaultTimeZone()
localNotification2.fireDate = self.getSevenPMDate()
UIApplication.sharedApplication().scheduleLocalNotification(localNotification2)
return true
}

func getEightAMDate() -> NSDate? {
let calendar: NSCalendar! = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)
let now: NSDate! = NSDate()

let date10h = calendar.dateBySettingHour(8, minute: 0, second: 0, ofDate: now, options: NSCalendarOptions.MatchFirst)!
return date10h
}

func getSevenPMDate() -> NSDate? {
let calendar: NSCalendar! = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)
let now: NSDate! = NSDate()

let date19h = calendar.dateBySettingHour(19, minute: 0, second: 0, ofDate: now, options: NSCalendarOptions.MatchFirst)!
return date19h
}


Related Topics



Leave a reply



Submit