#ios #notifications
#iOS #уведомления
Вопрос:
КРАТКОЕ ОПИСАНИЕ ПРОБЛЕМЫ
Я пишу приложение для iOS, которое отправляет уведомления-напоминания, позволяющие пользователю запускать другие приложения через их x-callback-url. У меня все работает идеально, если приложение находится на переднем плане или в фоновом режиме, но оно не будет работать, когда мое приложение закрыто.
Когда мое приложение закрыто, уведомления также доставляются должным образом, и пользователь может отклонить его или выбрать пользовательские действия для запуска другого приложения через его x-callback-url. Мое приложение запускается просто отлично, когда пользователь выполняет какие-либо действия с уведомлением.
Что не работает, когда приложение запускается непосредственно из закрытого состояния, так это запуск x-callback-url для запуска приложения Shortcuts.
ВОТ КОД
Это код, который находится в моем AppDelegate, связанный с уведомлениями:
// Handle what we need to after the initial application load
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Setup our custom notification options and notification category.
// Note that The table view controller will register to handle the actual notification actions.
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) {(granted, Error) in
if !granted {
os_log("AppDelegate: Notification authorization NOT granted.", log: OSLog.default, type: .info)
} else {
os_log("AppDelegate: Notification authorization granted.", log: OSLog.default, type: .info)
// Define our custom notification actions
let runAction = UNNotificationAction(identifier: "RUN_SHORTCUT", title: "Run Shortcut", options: [.foreground])
let snoozeAction = UNNotificationAction(identifier: "SNOOZE", title: "Snooze 10 Minutes", options: [])
let skipAction = UNNotificationAction(identifier: "SKIP_SHORTCUT", title: "Skip Shortcut", options: [])
// Define our custom notification categories
let shortcutCategory =
UNNotificationCategory(identifier: "SHORTCUT_REMINDER", actions: [snoozeAction, runAction, skipAction], intentIdentifiers: [], options: .customDismissAction)
let noshortcutCategory =
UNNotificationCategory(identifier: "NO_SHORTCUT_REMINDER", actions: [snoozeAction], intentIdentifiers: [], options: .customDismissAction)
// Register the nofication category and actions with iOS
let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.setNotificationCategories([shortcutCategory, noshortcutCategory])
os_log("AppDelegate: Set our custom notification categories and actions.", log: OSLog.default, type: .info)
} //endif
} //endfunc
return true
}
Это код в моем главном контроллере представления таблицы, который является делегатом для получения уведомлений:
// Handle notifications when our app is in the background
// Note that this isn't triggered when the notification is delivered, but rather when the user interacts with the notification
//
// TO-DO: THIS DOESN'T RUN THE SHORTCUT IF THE APP WAS CLOSED WHEN THE NOTIFICATION WAS RESPONDED TO!!!
//
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: () -> Void) {
// Get the user info from the notification
let userInfo = response.notification.request.content.userInfo
// Get the specific record id that triggered this notification
let itemID = userInfo["ITEM_ID"] as? String
let itemTitle = userInfo["ITEM_TITLE"] as? String
let itemShortcut = userInfo["ITEM_SHORTCUT"] as? String
let itemURL = userInfo["ITEM_URL"] as? String
// Handle the notification action
print("RemindersViewController: Received notification. actionIdentifier:", response.actionIdentifier)
switch response.actionIdentifier {
// If user selected the Run Shortcut option or simply tapped the notification, run the associated shortcut
case "RUN_SHORTCUT", "com.apple.UNNotificationDefaultActionIdentifier":
os_log("RemindersViewController: Notification Action Received: RUN_SHORTCUT: %{public}@ for shortcut %{public}@", log: .default, type: .info, String(describing: itemTitle!), String(describing: itemShortcut!))
if (itemShortcut != nil amp;amp; itemShortcut != "") {
if (itemURL != nil) {
print("RemindersViewController: Shortcut URL=", itemURL!)
let launchURL = URL(string: itemURL!)
if UIApplication.shared.canOpenURL(launchURL!) {
UIApplication.shared.open(launchURL!, options: [:], completionHandler: { (success) in
print("RemindersViewController: Notification Action: Run shortcut: Open url : (success)")
})
} else {
let alert = UIAlertController(title: "You don't have the Shortcuts app installed", message: "Please download from the Apple App Store", preferredStyle: .alert)
let action = UIAlertAction(title: "Ok", style: .default, handler: nil)
alert.addAction(action)
self.present(alert, animated: true, completion: nil)
print("RemindersViewController: Notification Action: User doesn't have the Shortcuts app.")
}
} else {
let alert = UIAlertController(title: "You don't have a shortcut name filled in", message: "Please fill in a shortcut name on your reminder", preferredStyle: .alert)
let action = UIAlertAction(title: "Ok", style: .default, handler: nil)
alert.addAction(action)
present(alert, animated: true, completion: nil)
print("RemindersViewController: Notification Action: No shortcut name filled in!")
}
}
break
default:
os_log("RemindersViewController: Default action selected, which is: %{public}@. Doing nothing.", log: .default, type: .info, response.actionIdentifier)
break
}
// Call the completion handler to close out the notification
completionHandler()
}
ОЖИДАЕМЫЕ И ФАКТИЧЕСКИЕ РЕЗУЛЬТАТЫ
Я ожидаю, что при запуске приложения из закрытого состояния из-за взаимодействия пользователя с уведомлением пользовательское действие «Запустить ярлык» должно запустить приложение Shortcuts с его URL-адресом обратного вызова x, сохраненным в пользовательских данных уведомления.
Комментарии:
1. В качестве обновления: теперь я указал действие быстрого запуска с обоими. foreground и .authenticationRequired, чтобы гарантировать, что приложение загрузится, и пользователь должен разблокировать свое устройство. Я подумал, что, возможно, проблема заключалась в том, что приложение не могло запустить другое приложение, пока устройство было заблокировано. Но, увы, это ничего не исправило. По какой-то причине приложение не запустит другое приложение, если мое приложение было закрыто при выполнении действия по уведомлению.
2. Я тоже хочу это сделать. И именно тогда, когда пользователь очищает уведомление, я хочу получить данные userInfo и сохранить их где-нибудь в D.B . Но проблема в том, что когда пользователь очищает уведомление, когда мое приложение закрывается / завершается. Я пропустил информацию в уведомлении, отправленном моим сервером. Итак, как мне исправить эту ситуацию или как я могу проверить действие «Очистить уведомление»?