App running in the background send local notifications - ios

How can i send Local Notifications while app is running in the background? in Swift 4. My app continuously use an Json file and I want the app to continue running so that it sends the user a Local Notification. I want a if label = label2 in background, App push notification for user.
label.text = myString
if label.text! == label2.text! {
let content = UNMutableNotificationContent()
content.title = "\(label2.text!)Değeri Kaydedildi!"
content.body = "Değer döndüğünde haber verilecek."
content.sound = UNNotificationSound.default()
let trigger = UNTimeIntervalNotificationTrigger.init(timeInterval: 5, repeats: false)
let request = UNNotificationRequest.init(identifier: "deneme", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
}

in AppDelegate, try to find function didReceiveRemoteNotification
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
#if DEBUG
print("Get User Info fetchCompletionHandler \(userInfo)")
#endif
// Your notification is in userInfo, you should cast it first before you show it
// Do what you want
completionHandler(.newData)
}

Related

How to show a local notification in the lock screen on iOS?

In my iOS app, I want to show a local notification that appears in the notification center and in the lock screen. It aims to be a notification for a music player.
So far, here is what I tried, running on iOS 15.3.1:
at app startup:
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool
{
UNUserNotificationCenter.current().requestAuthorization(options: [.alert]) { (granted, error) in
if (granted)
{
let category = UNNotificationCategory(identifier: "streaming", actions: [], intentIdentifiers: [], options: [])
UNUserNotificationCenter.current().setNotificationCategories([category])
UNUserNotificationCenter.current().delegate = self
}
else
{
print("Notifications permission denied because: \(error?.localizedDescription).")
}
}
}
override func userNotificationCenter(
_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void)
{
if #available(iOS 14, *)
{
completionHandler([.list])
}
else
{
completionHandler([.alert])
}
}
when I want to show the local notification:
// content:
let content = UNMutableNotificationContent()
content.categoryIdentifier = "test_category"
content.title = "Title"
content.subtitle = "Subtitle"
content.body = "Notification body"
content.sound = UNNotificationSound.default
// trigger:
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false)
let uuidString = UUID().uuidString
let request = UNNotificationRequest(identifier: uuidString, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
But for some reason, I only see the notification in the notification center, not in the lock screen...
So how can I see the notification in both the notification center and in the lock screen, as it is done for example on the Spotify app?
Thanks.

Display notification with the app in the foreground

I have an iOS flutter app and I want to display a local notification when the app is in the foreground.
The code I'm going to paste works if the app is in the background, but not when it is open.
Create the notification:
// Create notification content
let content = UNMutableNotificationContent()
content.title = title
content.sound = UNNotificationSound.default
// Set trigger
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 2, repeats: false)
// Submit request
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
center.add(request) { (error : Error?) in
if let theError = error {
print(theError.localizedDescription)
}
}
In the method:
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
}
I am adding the following, driven by other responses to this same problem:
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
}
None of the above works. The notification is not displayed if the app is in the foreground.
What should I do to display the local notification even if the app is in the foreground?
On iOS the system does not automatically display notifications that are delivered while your app is running in the foreground.
From the documentation
If your app is in the foreground, the system delivers the notification to your app for handling.
You need to implement the userNotificationCenter(_:willPresent:withCompletionHandler:) delegate function and call the provided completion handler with the desired presentation option, probably .banner
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler(.banner)
}
You will need to establish your Notification Center delegate in an appropriate place, such as didFinishLaunching

Can I make network calls within my iOS background fetch?

I am currently trying to create notifications when a user has new messages. I'm trying to do this with local notifications because I'm very much a beginner and it seems(?) easier than push notifications. My question is, can I check my Firebase database during my background fetch?
What I've experienced is that the background fetch function works- but only before my app memory has been suspended, thus negating the point of the background fetch. I run it, I simulate a background fetch, but unless the app was just open, it does nothing and tells me "Warning: Application delegate received call to -application:performFetchWithCompletionHandler: but the completion handler was never called."
Here's my code if it's useful. I know it probably seems like a funky way to go about this.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
//Firebase
FirebaseApp.configure()
//there was other firebase stuff here that I don't think is relevant to this question
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { (didAllow, error) in
}
UIApplication.shared.setMinimumBackgroundFetchInterval(UIApplicationBackgroundFetchIntervalMinimum)
return true
}
func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
myDatabase.child("users").child(userID!).child("hasNewMessages").observeSingleEvent(of: .value) { (snapshot) in
if snapshot.value as! Bool == true {
let content = UNMutableNotificationContent()
content.title = "You have unread messages"
content.badge = 1
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false)
let request = UNNotificationRequest(identifier: "testing", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
}
}
}
It is probably better to look at using push notifications as then your user's don't have to wait until iOS decides to invoke your background fetch; they can be notified of new messages immediately.
However, your problem is as described by the message you see in the console; you need to invoke the completionHandler that was passed to the background fetch method when you have finished your background operation to let iOS know what happened. It uses this information to tune how often and when your background fetch method is called.
func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
myDatabase.child("users").child(userID!).child("hasNewMessages").observeSingleEvent(of: .value) { (snapshot) in
if snapshot.value as! Bool == true {
let content = UNMutableNotificationContent()
content.title = "You have unread messages"
content.badge = 1
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false)
let request = UNNotificationRequest(identifier: "testing", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
}
completionHandler(.newData)
}
}

WKWebView open URL on local notification tap

I have PHP web server that sends data messages through firebase to my iOS WKWebView application and i need to open link received with data message in that WKWebView.
I already have set properly developer account, firebase and iOS application so i am receiving remote notifications like this
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
let body = userInfo["body"] as! String;
let title = userInfo["title"] as! String;
if (UIApplication.shared.applicationState == .inactive || UIApplication.shared.applicationState == .background)
{
localUserNotification(title: title, body: body);
}
completionHandler(UIBackgroundFetchResult.newData)
}
than because my push notification is actually a data message, i need to construct, and i am constructing my local notification.
func localUserNotification(title: String, body: String){
let center = UNUserNotificationCenter.current()
let options: UNAuthorizationOptions = [.alert, .sound];
center.requestAuthorization(options: options) {
(granted, error) in
if !granted {
print("Something went wrong")
}
}
let content = UNMutableNotificationContent()
content.title = title
content.body = body
content.userInfo = ["link": "https://google.com"];
content.sound = UNNotificationSound.default()
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 0.1,
repeats: false)
let identifier = "UYLLocalNotification"
let request = UNNotificationRequest(identifier: identifier,
content: content, trigger: trigger)
center.add(request);
}
because link is not valid parameter of UNMutableNotificationContent i am passing it in userInfo object, at this moment i have working code that shows me local notification when i am receiving data message from my server via firebase, now i need to handle user tapping of this notification what i am trying to do with this method
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
if (UIApplication.shared.applicationState == .inactive || UIApplication.shared.applicationState == .background)
{
print(response);
}
completionHandler();
}
but response have no data about userInfo sent in local notification, all i see is
<UNNotificationResponse: 0x1c42250e0; actionIdentifier: com.apple.UNNotificationDefaultActionIdentifier, notification:
<UNNotification: 0x1c42259a0; date: 2018-03-07 11:30:47 +0000, request:
<UNNotificationRequest: 0x1c403b220; identifier: UYLLocalNotification, content: <UNNotificationContent: 0x1c4112a20; title: This is magic, subtitle: (null), body: Well hello there mister, categoryIdentifier: , launchImageName: , peopleIdentifiers: (
), threadIdentifier: , attachments: (
), badge: (null), sound: <UNNotificationSound: 0x1c40bbd80>, hasDefaultAction: YES, defaultActionTitle: (null), shouldAddToNotificationsList: YES, shouldAlwaysAlertWhileAppIsForeground: NO, shouldLockDevice: NO, shouldPauseMedia: NO, isSnoozeable: NO, fromSnooze: NO, darwinNotificationName: (null), darwinSnoozedNotificationName: (null), trigger: <UNTimeIntervalNotificationTrigger: 0x1c42218c0; repeats: NO, timeInterval: 0.100000>>>>
how i can access my link?
Try
print(response.notification.request.content.userInfo)

Repeating local notification is triggered immediately -- how to defer?

My goal is to set a notification that will occur N seconds in the future for the first time, and then repeat every N seconds.
However, creating a repeating notification seems to trigger the UNUserNotificationCenterDelegate immediately.
App delegate:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
let center = UNUserNotificationCenter.current()
center.delegate = self
return true
}
func startRequest() {
let content = UNMutableNotificationContent()
content.body = bodyText
content.categoryIdentifier = categoryIdentifier
content.sound = UNNotificationSound.default()
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 60, repeats: true)
trigger.nextTriggerDate()
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
let center = UNUserNotificationCenter.current()
center.add(request)
}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
// This callback received right after the request is made
completionHandler([.alert, .sound])
}
I can work around this by creating a non-repeating notification and then starting repeating notifications when it expires. However, I was hoping there was some way to specify a first trigger date -- if memory serves right, the old notification API had this ability, and perhaps I am misunderstanding this new API
Thanks!
The issue may be that you aren't setting the title on the UNMutableNotificationContent().
content.title = "Title goes Here"
Also, to see if there is an error adding the request, you can add the following code.
center.add(request) { (error : Error?) in
if let theError = error {
// Handle any errors
}
}
I got this from Apple's docs - https://developer.apple.com/reference/usernotifications/unmutablenotificationcontent

Resources