How to display a message on top? - ios

I'm new to WatchKit development. I would like to display a message regardless of what app is currently being used or whether the watch is active or not, like how the built-in Timer app shows the label "Timer Done". The user should then be able to click an "OK" button and dismiss the message.
I have tried using both alerts and modal views, but showing them programmatically still requires my app to be active. Using the notifications system is not a viable solution because that would rely on an iPhone.
I've been stuck on this for many hours, any insight would be helpful, thanks.

You need to ask permission in your iOS App first:
UNUserNotificationCenter.current().requestAuthorization(options: [.alert,.badge,.sound])
{ (granted, error) in
if !granted
{
print("User did not give permissions to send notitications...")
}
}
Then in your watchOS App you can create a notification for some time in the future, make sure you give it a UUID (this may be a bug in watchOS3):
let content: UNMutableNotificationContent = UNMutableNotificationContent()
content.title = "Title"
content.subtitle = "Subtitle"
content.body = "message"
content.sound = UNNotificationSound.default()
content.categoryIdentifier = "aCategory"
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: duration, repeats: false)
let id: String = WatchNotify.getUUID()
let request = UNNotificationRequest.init(identifier: id,
content: content,
trigger: trigger)
UNUserNotificationCenter.current().add(request)
{
(error) in // ...
}
....
class func getUUID() -> String
{
let uuidObj = CFUUIDCreate(nil)
let uuidString = CFUUIDCreateString(nil, uuidObj)!
return uuidString as String
}

Related

How to keep UNUserNotificationCenter sound playing until user stops it

There are a few articles that address this same problem, but (from what I've seen) they're all from 4 years ago and in Objective-C. I'm working with Swift 4.2.
I'm making a countdown timer app. While the app is in the background and a timer expires, I want the notification sound to keep playing until the user stops it by tapping on the notification.
So far, what I have only plays an alert sound once from the background/lockscreen.
Here is the method I am working with.
func notifications(title: String, message: String){
center.delegate = self
let restartAction = UNNotificationAction(identifier: "RESTART_ACTION", title: "Restart timer", options: UNNotificationActionOptions(rawValue: 0))
let stopAction = UNNotificationAction(identifier: "STOP_ACTION", title: "Stop", options: UNNotificationActionOptions(rawValue: 0))
let expiredCategory = UNNotificationCategory(identifier: "TIMER_EXPIRED", actions: [restartAction, stopAction], intentIdentifiers: [], options: UNNotificationCategoryOptions(rawValue: 0))
// Register the notification categories.
center.setNotificationCategories([expiredCategory])
let content = UNMutableNotificationContent()
content.title = title
content.body = message
content.categoryIdentifier = "TIMER_EXPIRED"
content.sound = UNNotificationSound(named:UNNotificationSoundName(rawValue: _currentTimer.getSoundEffect+".mp3"))
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: TimeInterval(_currentTimer.endTime), repeats: false)
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
center.add(request) { (error : Error?) in
if let theError = error {
print(theError.localizedDescription)
}
}
}
So, the answer I'm going settling on with this question is that there is no answer. Apple does not want third party developers playing notification sounds for longer than 30 seconds in any circumstance, even if it is to build a timer app. Their timer in the Clock app will go off until you silence it, but third party developers aren't allowed to do that.

How Do I Remove The Notification From The Screen After Being Clicked On

For a few months, I have been working on an app which uses local UNNotifications to achieve the grand goal. I coded this app using Swift 4, therefore aiming it towards distribution on the iOS App Store. As I was testing my app out, I noticed that after I clicked on one of the notification actions (which was not "cancel"), or if I just tapped on the notification in general, the app would open up (which is intended), but the notification would remain on the screen. Is there any possible way to remove the notification from the screen after already tapping on one of the actions programmatically? Below is the code where I schedule the notification:
let action1 = UNNotificationAction(identifier: "go", title: "Go", options: [.foreground])
let action2 = UNNotificationAction(identifier: "cancel", title: "Cancel", options: [.destructive])
let actionsCategory = UNNotificationCategory(identifier: "actions.category", actions: [action1, action2], intentIdentifiers: [], options: [])
UNUserNotificationCenter.current().setNotificationCategories([actionsCategory])
//Queue the notification alert
let content = UNMutableNotificationContent()
content.body = "Interesting day notification!"
content.sound = UNNotificationSound.default()
content.setValue(true, forKey: "shouldAlwaysAlertWhileAppIsForeground")
content.categoryIdentifier = "actions.category"
// if (pinNumber.text) != nil{
// }
content.userInfo = ["Name": namePerson.text ?? "", "Pin": Int(pinNumber.text ?? "") != nil ? pinNumber.text! : ""]
//trigger
let triggerDate = Calendar.current.dateComponents([.year,.month,.day,.hour,.minute], from: datePicker.date)
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDate, repeats: false)
//scheduling
let identifier = id // set same id as task
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
center.add(request, withCompletionHandler: {(error) in
if let error = error{
print(error)
}else{
print("saved alert")
}
})
I don't see anything in your code that would cause that behavior. This sounds to me like either an iOS bug, or there is something weird about the notification permissions/settings of the particular device (or simulator) for your app. Go into the notifications sections of the Settings app and see what the settings are for your app.

Is UNUserNotification have option to show notification only on apple watch?

I am developing apple watch app which have the functionality to show a notification to User after every 2 or 3 or 5 min.
I have achieved this functionality through iOS UNUserNotification and its works perfectly.
But what I want here is User can see all notifications only on Apple watch not on iPhone.
Right now it's showing on both iPhone & Apple watch.
Is it possible to show notifications only on the Apple watch?
I have implemented the below code for UserNotification.
func scheduleNotification(at date: Date) {
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: (1*60), repeats: true)
let content = UNMutableNotificationContent()
content.title = "Test Reminder"
content.body = "Show More detail in Body!"
content.sound = UNNotificationSound.default()
content.categoryIdentifier = "myCategory"
if let path = Bundle.main.path(forResource: "logo", ofType: "png") {
let url = URL(fileURLWithPath: path)
do {
let attachment = try UNNotificationAttachment(identifier: "logo", url: url, options: nil)
content.attachments = [attachment]
} catch {
print("The attachment was not loaded.")
}
}
let request = UNNotificationRequest(identifier: "textNotification", content: content, trigger: trigger)
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
UNUserNotificationCenter.current().add(request) {(error) in
if let error = error {
print("Uh oh! We had an error: \(error)")
}
}
}
Thanks in Advance!
No, this is not possible.
The system decides automatically where to show the notifications, developers have no control over this.
The notification will be displayed on the Apple Watch if the paired iPhone is locked and the Watch is worn by the user. In any other case, the notification will be displayed on the iPhone.
See Notifications on your Apple Watch
Yes, you can make the notification appear only on watch if you will trigger the Local notification from WatchKit Extension.
Please see the corresponding documentation: https://developer.apple.com/documentation/watchkit/notifications/taking_advantage_of_notification_forwarding?changes=__5

Geofence alerts/local notifications not waking up locked phone when triggered

I'm making an app that used circular regions for geofences. When the phone is active or the app is open, the geofence notifications are working fine in both simulator and device (iPhone 6 running 10.3.1).
In the simulator it works fine; When the user enters a region, it wakes up, makes a sound and shows an alert on the lock screen.
On the phone, the "didEnterRegion" delegate calls are made when entering the region (I log some messages) but the phone is not making an alert and waking up. When I push the home button once, I can see the alert on the lock screen, but I want it to wake up and show the alert instantly - like when I get a message. It works in the simulator, so I wonder what could be wrong? It has worked for me a few times, where the alert was shown on both the phone and my watch, but 95% of the time it's not working - the notifications are generated but only visible if I manually wake up the phone.
How to fix this?
Here's the code I use for creating the local notification:
// https://blog.codecentric.de/en/2016/11/setup-ios-10-local-notification/
let location = CLLocation(latitude: item.coordinate.latitude, longitude: item.coordinate.longitude)
GeoTools.decodePosition(location: location) {
(address, city) in
let content = UNMutableNotificationContent()
content.title = "Camera nearby!"
content.subtitle = item.id
content.body = "\(address), \(city)"
content.categoryIdentifier = Constants.notificationCategoryId
content.sound = UNNotificationSound.default()
content.threadIdentifier = item.id
// FIXME make action for clicking notification
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 0.001, repeats: false) // FIXME HACK
let request = UNNotificationRequest(identifier: "camNotification", content: content, trigger: trigger)
let unc = UNUserNotificationCenter.current()
unc.removeAllPendingNotificationRequests()
unc.add(request, withCompletionHandler: { (error) in
if let error = error {
print(error)
}
else {
print("completed")
}
})
}
Here is some code that I just verified wakes the device when notification is presented:
let message = "CLRegion event"
// Show an alert if application is active:
if UIApplication.shared.applicationState == .active {
if let viewController = UIApplication.shared.keyWindow?.rootViewController {
showSimpleAlertWithTitle(nil, message: message, viewController: viewController)
}
}
else {
// Otherwise app is in background, present a local notification:
let content = UNMutableNotificationContent()
content.body = message
content.sound = UNNotificationSound.default()
content.categoryIdentifier = "message"
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1.0, repeats: false)
let request = UNNotificationRequest(identifier: "com.foobar", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
}
Really the only diff is that I don't call removeAllPendingNotifications() so if you must remove notifications I wonder if removePendingNotificationRequests(withIdentifiers identifiers: [String]) might be more precise?

Apple watch local notification not working when the watch isn't worn

We are using the UNUserNotification framework provided by WatchOS 3.0 to create local notification to notify user at a predefined moment. However, the notification is not shown when the watch is not being worn on the wrist. It does work well when someone is wearing it.
We cannot find this description on any documentation. Is that normal? If yes, how to help the user to avoiding missing some notifs ?
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { (granted, error) in
// Enable or disable features based on authorization.
if granted {
let content = UNMutableNotificationContent()
content.title = title
content.body = body
content.sound = UNNotificationSound.default()
content.userInfo = userInfo
let trigger = UNTimeIntervalNotificationTrigger.init(
timeInterval: interval,
repeats: false)
let identifier = stringWithUUID()
let request = UNNotificationRequest.init(
identifier: identifier,
content: content,
trigger: trigger
)
UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
completion?(true, nil)
}
else {
completion?(false, error)
}
}
This is normal, Apple Watch automatically locks when you take it off your wrist and notifications go to your iPhone instead.

Resources