Handle local notification when app is in background - ios

Basiccally I'm scheduling a local notification for ringing my alarm at particular time say 8:00 Am. NOw I want to perform a specific task like play sound of alarm when app is in background but without tapping on the notification banner which I recived in the notification list.
I'm using below code, but it works only when i tap the notification banner and get into the app.
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response:
UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void)
{
print("notification recived in background state")
}
Please help me with the tricky solution to handle my local notification without tapping the banner.
Thanks is Advance.

Setting a sound file which is placed in project bundle
let arrayOfSoundFile = ["water.caf","hello.mp3"]
let content = UNMutableNotificationContent()
content.title = NSString.localizedUserNotificationStringForKey("Title..", arguments: nil)
content.body = NSString.localizedUserNotificationStringForKey("Text Here...", arguments: nil)
//Custom sound file as par user requriment select file UIPickerView add and select file
content.sound = UNNotificationSound(named: arrayOfSoundFile[0])
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 50, repeats: false)
let identifier = "WakeUp"
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
let center = UNUserNotificationCenter.currentNotificationCenter()
center.addNotificationRequest(request, withCompletionHandler: { (error) in
if error != nil {
print("notification created successfully.")
}
})
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void)
{
let userInfo = notification.request.content.userInfo
let dictAps = userInfo["aps"] as! NSDictionary
print(dictAps)
completionHandler([.alert, .badge, .sound])
}

Related

How to identify UNUserNotificationCenter is came(:didReceive)

Here I use UNUserNotificationCenter to trigger notifications repeatedly. I had a problem when the notification was triggered I wanted to call the function without action. can someone tell me how to do that?
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
print(" Foreground Notification IS CALLED ")
completionHandler([.badge, .banner, .sound])
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
print(" Nikan Did recieve calling ")
if response.actionIdentifier == "Okay" {
print(" Notification Clickced ")
}
completionHandler()
}
func createNotification() {
let content = UNMutableNotificationContent()
content.title = "Notification"
content.subtitle = "Wow, Notification"
content.categoryIdentifier = "Actions"
content.sound = UNNotificationSound.defaultRingtone
// show this notification five seconds from now
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 60, repeats: true)
// choose a random identifier
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
// notification actions
let okay = UNNotificationAction(identifier: "Okay", title: "Okay", options: .destructive)
let category = UNNotificationCategory(identifier: "Actions", actions: [okay], intentIdentifiers: [], options: [])
UNUserNotificationCenter.current().setNotificationCategories([category])
// UNUserNotificationCenter.current().add(request)
UNUserNotificationCenter.current().add(request, withCompletionHandler: { error in
if let error = error {
// Something went wrong
print(error)
}
})
}
I want an answer to call a function when UNUserNotificationCenter's notification is triggered.
Question: How to call a function when a notification is received?
Answer:
When you receive notification (:didReceive), post NSNotification and observe it in your UIViewController.
Call the function in observer's #selecteor method.
DidReceive triggers when tap on push notification, in your case app is is in background and if the app is opening by clicking on push notification, then DidReveive will be triggered.
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
let pushInfo = response.notification.request.content.userInfo
// post NSNotification here
// You also have data fetched from push notification (if any) in pushInfo variable
}

userNotificationCenter didReceive is not being called when tapping a notification

I have set the following local notification:
let content = UNMutableNotificationContent()
content.title = "Some Title"
content.body = "Some text"
content.sound = UNNotificationSound.default
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 20, repeats: false)
let request = UNNotificationRequest(identifier: "OneDay", content: content, trigger: trigger)
notificationCenter.add(request)
And I have added the following to AppDelegate
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
print("Notification Tapped")
if response.notification.request.identifier == "OneDay" {
print("OneDay Notification Tapped")
}
completionHandler()
}
notificationCenter has been set as:
let notificationCenter = UNUserNotificationCenter.current()
However, none of the above print statements work. The notification is presented, I tap on it, the app is brought to the foreground but nothing is printed to the console.
Am I missing anything here? I've tested in both the simulator and a device. Same result.
I'm working with XCode 11.5, deploying for 12.0.
I'm not sure what is going as I'd have to see the complete code, so I just made a minimal example for you to understand. It also works perfectly fine in the Simulator.
Please feel free to let me know if you have any questions!
First make sure you're asking for the user permission before setting your delegate or scheduling any local notifications, otherwise your notifications will fail silently.
UNUserNotificationCenter.current().requestAuthorization(options: [.badge, .alert, .sound]) { (isAuthorized, error) in
// ...
}
Once you're done asking authorization (and the status is granted), simply set your delegate:
UNUserNotificationCenter.current().delegate = self
Create your notification:
let content = UNMutableNotificationContent()
content.title = "Title"
content.subtitle = "Subtitle"
content.body = "Body"
content.sound = UNNotificationSound.default
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)
let request = UNNotificationRequest(identifier: "OneDay", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) { error in
guard error == nil else {
return
}
// ...
}
And your delegate methods will get called as expected:
extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
// ...
completionHandler([.alert, .badge, .sound])
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
if response.notification.request.identifier == "OneDay" {
// ...
}
completionHandler()
}
}
Adding onto #user13639548 answer:
Make sure to register the current UNUserNotificationCenter.current().delegate each time the app is restarted.
if UserStorage.shared.pushNotificationsToken == nil {
SettingsHelper.getUserPushNotificationStatus(completion: self.processPushNotificationStatus(status:))
} else {
UIApplication.shared.appDelegate?.setAppDelegateAsPushNotificationDelegate()
}
}
This is the resulting call:
func setAppDelegateAsPushNotificationDelegate() {
UNUserNotificationCenter.current().delegate = self
}
When user app into the background and tap on notification.
then the method 'applicationWillEnterForeground' of life cycle is called.
this code is working for me.
func applicationWillEnterForeground(_ application: UIApplication) {
let center = UNUserNotificationCenter.current()
center.delegate = self
}

Schedule Local notification on Remote Notification

In our project, we want to changed a title and body of Remote Notification . In that we generate a Local Notification and Display a local notification with changed a title and body and hide push Notification. But in that while App is in Background and kill State it will display a Remote a Notification instead of Local Notification. But we want to display a Local Notification instead of push in Will present Notification. how to do this ?
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Swift.Void) {
if notification.request.identifier != "local_notification1"{
self.isAdded = false
}
let name = (ContactsManager.shared.getContacName(withPhoneNumber:notification.request.content.title) != nil) ? ContactsManager.shared.getContacName(withPhoneNumber:notification.request.content.title) :
notification.request.content.title
let notificationContent = UNMutableNotificationContent()
// notificationContent.userInfo = notification.request.content.userInfo
notificationContent.body = notification.request.content.body
notificationContent.title = name!
debugPrint("name title is %# ", name)
debugPrint("notificationContent title is %# ", notificationContent.title)
notificationContent.sound = .default
let notificationTrigger = UNTimeIntervalNotificationTrigger(timeInterval: 0.1, repeats: false)
let notificationRequest = UNNotificationRequest(identifier: "local_notification1", content: notificationContent, trigger: notificationTrigger)
if !isAdded {
UNUserNotificationCenter.current().add(notificationRequest) { (error) in
if let error = error {
debugPrint("Unable to Add Notification Request (\(error), \(error.localizedDescription))")
}else {
print("is Shown")
}
self.isAdded = true
}
completionHandler([])
}
completionHandler([.alert,.sound])
}
}
You can modify content of remote notification with help of UNNotificationServiceExtension
First override didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: #escaping (UNNotificationContent) -> Void) {
Modify content and.
Return updated content in contentHandler
Note: Required iOS 10+

How do I play music without requiring user action when a notification fires in iOS while the device is locked?

How do I play music without requiring user action when a notification fires in iOS while the device is locked? The music needs to be a significantly long audio -- longer than the 30-second limit placed on the notification tone. Other posts on stackoverflow indicate it can't be done, but I have seen an app that is able to do it. Perhaps it can be done by a roundabout way, though I would like to learn the preferred way.
Here is my code so far:
let content = UNMutableNotificationContent()
content.categoryIdentifier = "HELLO"
content.title = "Hello World!"
content.body = "May the Force be with you."
var dateComponents = DateComponents()
dateComponents.second = 0
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.
center.add(request) { (error) in
if error != nil {
print("error=", error?.localizedDescription as Any)
}
}
// MARK: - UNUserNotificationCenterDelegate
extension ViewController: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
print("willPresent")
completionHandler([.alert, .badge, .sound])
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
print("didReceive")
print(response.actionIdentifier)
completionHandler()
}
}
The delegate callback methods don't fire when the device is locked.

How to detect when a scheduled notification has been fired in Swift 4

I've created a scheduled notification and I'd like to be able to do stuff once it gets delivered. Not once it's clicked on or selected, but when it's actually delivered and shows up on the user's screen.
The code I've used to generate the notification is:
let content = UNMutableNotificationContent()
content.title = NSString.localizedUserNotificationString(forKey: "foo", arguments: nil)
content.body = NSString.localizedUserNotificationString(forKey: "bar", arguments: nil)
var dateInfo = DateComponents()
dateInfo.hour = 7
dateInfo.minute = 0
print(dateInfo.hour!)
print(dateInfo.minute!)
let trigger = UNCalendarNotificationTrigger(dateMatching: dateInfo, repeats: false)
// Create the request object.
let notificationRequest = UNNotificationRequest(identifier: "MorningAlarm", content: content, trigger: trigger)
center.add(notificationRequest)
I'm sure I've got to add something to my AppDelegate that'll respond when the notification is delivered, but I've been looking all over the internet and can't find a way to do it on delivery rather than on select.
When a notification arrives, the system calls the userNotificationCenter(_:willPresent:withCompletionHandler:) method of the UNUserNotificationCenter object’s delegate.
let center = UNUserNotificationCenter.current()
center.delegate = self // What delegation target Here is my AppDelegate
extension AppDelegate : UNUserNotificationCenterDelegate {
// while your app is active in forground
// Handle Notifications While Your App Runs in the Foreground
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
let userInfo = notification.request.content.userInfo
// Change this to your preferred presentation option
// Play a sound.
// completionHandler(UNNotificationPresentationOptions.sound)
}
// While App is inactive in background
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
// While App is inactive in background
print(userInfo)
completionHandler()
}
}

Resources