I have an app for Apple Watch as a companion app for an iPhone app. The local notifications on Apple Watch App are delayed. I scheduled a local notification to be fired after 10 seconds. When I press the button on the watch that creates the notification and I exit the app, it doesn't take 10 seconds to display the notification but about 23 seconds.
I created a test stand alone/independent Apple Watch App with the same local notification code, and in this scenario, the local notification fires at the correct time.
I am on watchOS 8.1. Is this a new feature on Apple Watch or a bug? Because on iPhone it works without any delay. Thank you in advance :)
// Configure the notification's payload.
let content = UNMutableNotificationContent()
content.title = "Drink some milk!"
content.subtitle = "you have 10 sec"
content.sound = .default
content.categoryIdentifier = "myCategory"
let category = UNNotificationCategory(identifier: "myCategory", actions: [], intentIdentifiers: [], options: [])
UNUserNotificationCenter.current().setNotificationCategories([category])
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 10, repeats: false)
let request = UNNotificationRequest(identifier: "milk", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) { (error) in
if let error = error{
print(error.localizedDescription)
}else{
print("scheduled successfully")
}
}
There is a feedback here:
https://developer.apple.com/forums/thread/696280
This is correct behaviour.
If you have both a phone and watch app installed we’ll try to coordinate between phone and watch notifications if the phone is unlocked. If the app developer doesn’t send a notification on the phone the watch will timeout after 13 seconds and alert anyway.
The best solution to this would be to send the same notification on both devices ensuring the UNNotificationRequest.identifier matches on a per-instance basis.
This will let us alert and deduce correctly.
If watch app send local notification , I'll send the notification 13 seconds ahead of time. This way the notification appears to be on time
Hope to have a better solution in the future
Related
I want to when user get notification from fcm (Firebase Cloud Messaging) or scheduler local notification like alarm notification like image below :
Here my code :
func onTest() {
let content = UNMutableNotificationContent()
content.title = "Weekly Staff Meeting"
content.body = "Every Tuesday at 2pm"
// Configure the recurring date.
var dateComponents = DateComponents()
dateComponents.calendar = Calendar.current
dateComponents.hour = 16 // 14:00 hours
dateComponents.minute = 11
// Create the trigger as a repeating event.
let trigger = UNCalendarNotificationTrigger(
dateMatching: dateComponents, repeats: true)
// 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.
}
}
}
My code right now just like the usual notification which disappears in 5 seconds I want to make it like an Alarm notification or Whatsapp Calling Notification. Please Help Thanks.
Due to Apple's limitation, app dev can only play notification tone up to 30 seconds. It will play default notification tone if your tone is longer than 30 seconds.
If your notification tone is gone after 5 seconds, try to set your notification presentation options to list, badge and sound.
Once there's no banner for notification, your 30seconds tone will play till the end.
Unfortunately there's no legal way or any workaround to have notification ring continuously such as alarm clock. Hope I was wrong though.
https://developer.apple.com/documentation/usernotifications/unnotificationpresentationoptions
What I think, max you can do is to present a local notification. But yes that would not be exactly like an Apple Alarm notification. In Reality, you don't have permission for this. You can only present the local notifications.
In my app I am scheduling local notifications with the following method:
func addNotificationRequest(fireDate: Date, identifier: String, sound: UNNotificationSound)
{
let notificationCenter = UNUserNotificationCenter.current()
let content = UNMutableNotificationContent()
content.title = "Important"
content.body = notificationMessage
content.sound = sound
content.categoryIdentifier = "UserActions"
let calendar = Calendar(identifier: .gregorian)
let triggerDate = calendar.dateComponents([.hour, .minute, .second], from: fireDate)
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDate, repeats: true)
let notificationRequest = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
notificationCenter.add(notificationRequest) { error in
if let error = error
{
print(error.localizedDescription)
}
}
let myAction = UNNotificationAction(identifier: "MyActionID", title: "Open", options: [.foreground])
let category = UNNotificationCategory(identifier: "UserActions", actions: [myAction], intentIdentifiers: [], options: [])
notificationCenter.setNotificationCategories([category])
}
Notifications are supposed to fire at a given time and should repeat every day at the same time.
On iOS 13 I found a bug that can be reproduced by the following steps:
I go to iOS Settings > Notifications > App Name > Disable "Allow Notifications"
Then I open the app and schedule a local notification for example after 2 minutes
After that I go back to Settings and enable back "Allow Notifications" switch.
After 2 minutes no local notification is shown. Tested it on older iOS versions and notifications are shown as supposed.
Maybe some people found this bug too and have any advice how to fix. Any help is appreciated.
Starsky is correct!
According to Apple's Documentation:
Before trying to schedule local notifications from your app, make sure that your app is authorized to do so, because the user can change your app’s authorization settings at any time. Users can also change the types of interactions that are allowed for your app, which might cause you to change the way you configure your notifications.
You'll either have to "silently fail" at scheduling the notification if permissions are disabled, or notify the user that they need to go into the Settings app to re-enable them:
In my case, I did something like this using SwiftMessages:
static func showNotificationDisabledInfo() {
print("INFO: Notification permissions denied, need to reset in Settings!")
showAlertMessage(withTitle: "Notifications are disabled!",
body: "Go to the Settings app to re-enable notifications.",
type: .info)
}
Im trying to schedule local notification every hour. The problem is that im getting the notification in such irregular time. Sometime in 10 minutes, or in second, or 30 minutes. Sometime i get like 10 notifications in the same second suddenly. I have no idea what is the mistake im doing here. I apologize in advance, i just started learning swift.
This is my code.
#objc func LocalNotificationHour() {
let user = UNUserNotificationCenter.current()
user.requestAuthorization(options: [.alert,.sound]) { (granted, error) in}
let content = UNMutableNotificationContent()
content.title = "Local Notification"
content.body = "Test."
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: (60*60), repeats: true)
let uuid = UUID().uuidString
let request = UNNotificationRequest(identifier: uuid, content: content, trigger: trigger)
user.add(request) { (error) in print("Error")}
}
Is it possible that your function is being run multiple times, and therefore scheduling more than one notification to repeat? That would account for receiving multiple notifications at once/at times when you're not expecting them.
If that is the case, try adding the line user.removeAllPendingNotificationRequests() under let user = UNUserNotificationCenter.current(). This will remove any pending notifications your app may have scheduled before scheduling a new one.
It's because you are running your code once with one hour logic.
And then you are changing logic for two hour logic.
So basically both notification is triggering.
Either delete the app or previously scheduled notifications or change the identifier.
I want to clear remote notifications so they don't add up in the Notification Center (like when you get a video call in WhatsApp or Messenger, only the last notification is displayed).
I tried to call (in didReceiveRemoteNotification):
let center = UNUserNotificationCenter.current()
center.removeDeliveredNotifications(withIdentifiers: ["notification_identifier"])
But it gets called only if the app is active. How can I do this if the app is in another state?
Thanks for your help.
After some research and thanks to Paulw1's answer, I found out there are two ways of doing this:
Remote only
Notifications can be collapsed remotely, you only have to send the notification with apns-collapse-id as a request header. Please note that it's only supported in HTTP/2 though. More information here.
Silent remote + local notification
The other way consists in sending a silent remote notification, with this kind of payload:
{
"type": "notification_type",
"aps" : {
"content-available": 1
}
}
It will call didReceiveRemoteNotification even if the app's state is inactive or background. Then, I create a local notification request (needs using UserNotifications, available from iOS10) :
let content = UNMutableNotificationContent()
content.body = "Notification message"
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 0.25, repeats: false)
let request = UNNotificationRequest(identifier: "identifierToUpdate", content: content, trigger: trigger)
self.center.add(request, withCompletionHandler: nil)
The key to update the previous notification is to use the same request identifier.
In our app, the user will clock-in when he starts his work. If the user forgets to clock-out, we will have to automatically clock him out after 24 hours from the clock-in time. The app might not be in the active/background state for such a long time. It might be terminated. So our idea is to post a local notification through which will execute the code in the background to clock him out. This notification has to be a silent notification. But our understanding from the research is that local notifications cannot be silent. So is there any other way we could achieve this? Or can we actually schedule a silent local notification?
class func generateLocalNotificationWith(timeInterval : TimeInterval, title : String, message : String, mobileTimeClockId: Int)
{
UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
let content = UNMutableNotificationContent()
//adding title, subtitle, body and badge
content.title = title
content.body = message
let userInfoDictionary = ["badge":"0","content-available": "1"]
let dict = ["aps": userInfoDictionary, "MobileTimeClockId": mobileTimeClockId] as [String : Any]
content.userInfo = dict
//getting the notification trigger
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: timeInterval, repeats: false)
//getting the notification request
let request = UNNotificationRequest(identifier: "SimplifiedIOSNotification", content: content, trigger: trigger)
//adding the notification to notification center
UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
}
If you want a notification to be silent and do background work it has to be a push notification. A local notification can't wake your app without some user interaction.
The best way to do what you want is to use Core Location region monitoring to wake your app when the user physically leaves their workplace. Region monitoring can wake your app silently in the background and let you do some work. The problem is that it's not 100% assured that it will be triggered and the user will need to accept background location permissions.