Получите push-уведомление, пока приложение на переднем плане iOS


192

Я использую сервис push-уведомлений в своем приложении. Когда приложение находится в фоновом режиме, я могу видеть уведомление на экране уведомлений (экран отображается, когда мы проводим вниз с верхней части устройства iOS). Но если приложение находится на переднем плане, метод делегата

- (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary*)userInfo

вызывается, но уведомление не отображается на экране уведомлений.

Я хочу показать уведомление на экране уведомлений независимо от того, находится приложение в фоновом режиме или на переднем плане. Я устал от поиска решения. Любая помощь с благодарностью.


35
Apple говорит : если вы получаете локальные или удаленные уведомления, когда ваше приложение работает на переднем плане, вы несете ответственность за передачу информации своим пользователям в зависимости от приложения.
Лаури Лехмийоки

2
Некоторые современные (16 октября) ссылки на яблоки: здесь , там и там
azmeuk

1
не поддержка переднего плана push-уведомлений для iOS 9.3 и менее?
Анураг Шарма

@ Лаури Лехмийоки ссылка? Я не нашел этого на официальном сайте
Вячеслав Герчиков

1
Я сталкиваюсь с той же проблемой в ионном ...
сказал Мохд Али

Ответы:


208

Для отображения баннера, когда приложение находится на переднем плане, используйте следующий метод.

iOS 10, Swift 3/4 :

// This method will be called when app received push notifications in foreground
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) 
{
    completionHandler([.alert, .badge, .sound])
}

iOS 10, Swift 2.3 :

@available(iOS 10.0, *)
func userNotificationCenter(center: UNUserNotificationCenter, willPresentNotification notification: UNNotification, withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void)
{
    //Handle the notification
    completionHandler(
       [UNNotificationPresentationOptions.Alert,
        UNNotificationPresentationOptions.Sound,
        UNNotificationPresentationOptions.Badge])
}

Вы также должны зарегистрировать своего делегата приложения в качестве делегата для центра уведомлений:

import UserNotifications

// snip!

class AppDelegate : UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate

// snip!

   func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

      // set the delegate in didFinishLaunchingWithOptions
      UNUserNotificationCenter.current().delegate = self
      ...
   }

Когда этот метод вызывается?
Ума Мадхави

Пожалуйста, сообщите мне, я поражен отображением уведомлений сверху, когда мой фон приложения или передний план. С 2 недель я работаю с push-уведомлениями. Я могу получать сообщения от сервера.
Ума Мадхави

@ UmaMadhavi Можете ли вы получать push-уведомления?
Ченгсам

21
Не забудьте установить делегата Центра уведомлений в качестве делегата приложения: UNUserNotificationsCenter.current().delegate = selfв приложении didFinishLaunchingWithOptions
Ashok

2
Для тех, кто все еще борется, его UNUserNotificationCenter не UNUserNotificationsCenter с 's' перед центром
Радж

58

Ниже код будет работать для вас:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo  {
    application.applicationIconBadgeNumber = 0;             
    //self.textView.text = [userInfo description];
    // We can determine whether an application is launched as a result of the user tapping the action
    // button or whether the notification was delivered to the already-running application by examining
    // the application state.

    if (application.applicationState == UIApplicationStateActive) {                
        // Nothing to do if applicationState is Inactive, the iOS already displayed an alert view.                
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Did receive a Remote Notification" message:[NSString stringWithFormat:@"Your App name received this notification while it was running:\n%@",[[userInfo objectForKey:@"aps"] objectForKey:@"alert"]]delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [alertView show];          
    }    
}

Это работает. Немного больше информации о том, что он делает; когда приложение находится на переднем плане, появляется окно оповещения собственного пользовательского интерфейса с текстом уведомления внутри него (текст titleнемного выделен жирным шрифтом, а messageтекст под ним поменьше. Кнопка «ОК» для отклонения находится внизу). Опция applicationIconBadgeNumber, установленная в 0, предназначена для скрытия числа, которое появляется в верхней части значка приложения в Springboard (например, для обозначения количества непрочитанных сообщений в почтовом приложении). В этом примере я не знаю, нужна ли эта опция.
Джвинн

Работает ли это как для уведомления, так и для UILocalNotification?
user6631314

38

Для всех, кого это может заинтересовать, я создал пользовательское представление, которое выглядит как системный push-баннер сверху, но добавляет кнопку закрытия (маленький синий X) и возможность нажать на сообщение для настраиваемого действия. Он также поддерживает случай, когда поступило более одного уведомления до того, как пользователь успел прочитать / отклонить старые (без ограничения на то, сколько может накапливаться ...)

Ссылка на GitHub: AGPushNote

Использование в основном on-liner:

[AGPushNoteView showWithNotificationMessage:@"John Doe sent you a message!"];

И это выглядит на iOS7 (iOS6 выглядит и чувствует iOS6 ...)

введите описание изображения здесь


1
Также теперь переопределено в Swift: github.com/charliewilliams/CWNotificationBanner (мной)
сборка завершена

Хорошо, это должно быть полезно.
无 夜 之 星辰

35

Цель С

введите описание изображения здесь

Для этого iOS 10нам нужно интегрировать willPresentNotificationметод для показа баннера уведомления в foreground.

Если приложение в режиме переднего плана (активно)

- (void)userNotificationCenter:(UNUserNotificationCenter* )center willPresentNotification:(UNNotification* )notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler {
    NSLog( @“Here handle push notification in foreground" ); 
    //For notification Banner - when app in foreground

    completionHandler(UNNotificationPresentationOptionAlert);

    // Print Notification info
    NSLog(@"Userinfo %@",notification.request.content.userInfo);
}

1
Просто скопируйте код и не забудьте использовать протокол UNUserNotificationCenterDelegate.
Ник Ков

если я хочу показать предупреждение вместо этого уведомления тогда?
Михир Оза

@MihirOza Вы хотите UIAlertController?
Ашвини Чугале

Я знаю, но не хочу всплывающее уведомление, когда приложение активно. Я хочу только оповещение в моем приложении.
Михир Оза

я попробовал твою функцию, но я все еще не могу получить толчок на переднем плане
Халед Буссоффара

25

Если приложение работает на переднем плане, iOS не будет показывать баннер / предупреждение. Это по замыслу. Но мы можем достичь этого, используя UILocalNotificationследующие

  • Проверьте, находится ли приложение в активном состоянии при получении удаленного
    уведомления. Если в активном состоянии сработает UILocalNotification.

    if (application.applicationState == UIApplicationStateActive ) {
    
        UILocalNotification *localNotification = [[UILocalNotification alloc] init];
        localNotification.userInfo = userInfo;
        localNotification.soundName = UILocalNotificationDefaultSoundName;
        localNotification.alertBody = message;
        localNotification.fireDate = [NSDate date];
        [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
    }

SWIFT:

if application.applicationState == .active {
    var localNotification = UILocalNotification()
    localNotification.userInfo = userInfo
    localNotification.soundName = UILocalNotificationDefaultSoundName
    localNotification.alertBody = message
    localNotification.fireDate = Date()
    UIApplication.shared.scheduleLocalNotification(localNotification)
}

86
Я не думаю, что это поможет. Локальные и удаленные уведомления обрабатываются одинаково, и в результате при запуске этого локального уведомления и в случае запуска приложения значок / баннер или звук не будут отображаться / воспроизводиться.
RPM

3
Он также оставит запись в Центре уведомлений iOS
Ab'initio

3
Однако я не запускаю локальное уведомление, когда приходит push-уведомление. Вместо этого я запустил бы подобное поведение, как упомянутое @ Rick77: показ предупреждения или тостера. Я думаю, мне не нужно снова проходить через операционную систему для чего-то, что операционная система просит меня обработать.
Фабио Оливейра

3
Это решение работает, поскольку локальное и удаленное обрабатываются одинаково, когда приложение на переднем плане, создание уведомления о местоположении, когда приходит удаленное уведомление, ничего не показывает. Решением является использование оповещения или настраиваемого оповещения
Hammer

19
Это на самом деле не работает. Из документов UILocalNotification:If the app is foremost and visible when the system delivers the notification, the app delegate’s application:didReceiveLocalNotification: is called to process the notification. Use the information in the provided UILocalNotification object to decide what action to take. The system does not display any alerts, badge the app’s icon, or play any sounds when the app is already frontmost.
Крис Морс

15

Если приложение работает на переднем плане, iOS не будет показывать баннер / предупреждение. Это по замыслу. Вы должны написать некоторый код, чтобы справиться с ситуацией, когда ваше приложение получает уведомление, пока оно находится на переднем плане. Вы должны показывать уведомление наиболее подходящим способом (например, добавляя номер значка к UITabBarзначку, имитируя баннер Центра уведомлений и т. Д.).


1
но в почтовом приложении iOS они это сделали, вы получите новый баннер с уведомлением / предупреждением, а почтовое приложение на переднем плане
Ab'initio

3
@ Ab'initio Не знаю точно, но в iOS не все приложения созданы равными. Я полагаю, что стандартное почтовое приложение использует какой-то частный API, который недоступен в общедоступном SDK. Или, возможно, код уведомления делает исключение с идентификатором приложения Apple Mail.
Даниэль Мартин

1
Какой?? Я собираюсь атаковать ярость гарпии.
Джош

@ DanielMartín не могли бы вы сказать мне, как я получу уведомление в состоянии переднего плана в iOS 8.0
Дилип Тивари

10
Имейте в виду, что этот ответ верен только для iOS 9 и ниже . Начиная с iOS 10, Apple представила новый API для обработки уведомлений ( UNUserNotificationCenter API). Наряду с новым API теперь можно показывать уведомления, если приложение находится на переднем плане. Так что, если вы запутались, потому что разные ответы в этом вопросе, это потому, что некоторые ответы слишком стары и описывают только поведение для iOS 9 и ранее, тогда как другие не учитывают, что они UNUserNotificationCenter доступны только из iOS 10.
Tomacco

13

Xcode 10 Swift 4.2

Чтобы показать Push-уведомление, когда ваше приложение находится на переднем плане -

Шаг 1: добавьте делегат UNUserNotificationCenterDelegate в классе AppDelegate.

class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {

Шаг 2. Установите делегата UNUserNotificationCenter

let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.delegate = self

Шаг 3. Этот шаг позволит вашему приложению отображать push-уведомления, даже когда ваше приложение находится на переднем плане

func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        completionHandler([.alert, .sound])

    }

Шаг 4: Этот шаг не является обязательным . Проверьте, находится ли ваше приложение на переднем плане, и если оно на переднем плане, то покажите Local PushNotification.

func application(_ application: UIApplication,didReceiveRemoteNotification userInfo: [AnyHashable: Any],fetchCompletionHandler completionHandler:@escaping (UIBackgroundFetchResult) -> Void) {

        let state : UIApplicationState = application.applicationState
        if (state == .inactive || state == .background) {
            // go to screen relevant to Notification content
            print("background")
        } else {
            // App is in UIApplicationStateActive (running in foreground)
            print("foreground")
            showLocalNotification()
        }
    }

Функция локального оповещения -

fileprivate func showLocalNotification() {

        //creating the notification content
        let content = UNMutableNotificationContent()

        //adding title, subtitle, body and badge
        content.title = "App Update"
        //content.subtitle = "local notification"
        content.body = "New version of app update is available."
        //content.badge = 1
        content.sound = UNNotificationSound.default()

        //getting the notification trigger
        //it will be called after 5 seconds
        let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false)

        //getting the notification request
        let request = UNNotificationRequest(identifier: "SimplifiedIOSNotification", content: content, trigger: trigger)

        //adding the notification to notification center
        notificationCenter.add(request, withCompletionHandler: nil)
    }

1
Это отличный пример необходимости читать все ответы в ветке. Более ранние потоки упоминают метод, чем делегат и, наконец, этот, все три шага, которые вам нужно сделать. СПАСИБО за полный ответ!
user3069232

Приятно знать, что это помогло тебе. Счастливое кодирование
Prashant Gaikwad

11

Согласно документации Apple , да, вы можете отображать уведомления во время работы приложениявведите описание изображения здесь


Где я могу написать эту функцию в приложении делегата или в указанном классе?
iOS разработчик

Что делать, если я хочу написать, что загрузочный метод загружен ??
iOS разработчик

Вы можете написать любое место, но при условии, что оно должно соответствовать UNUserNotificationCenterDelegateпротоколу
SPatel

Вы не можете писать вviewDidLoad
SPatel

1
Я предлагаю вам продлить AppDelegateextension AppDelegate: UNUserNotificationCenterDelegate
SPatel

9

Вы можете создать свое собственное уведомление, которое имитирует предупреждение баннера.

Одним из способов является создание пользовательского интерфейса, который выглядит как баннер и может анимировать и реагировать на прикосновения. Имея это в виду, вы можете создавать еще лучшие баннеры с еще большей функциональностью.

Или вы можете найти API, который сделает это за вас, и добавить их в виде подфайлов в ваш проект.

Вот пара, которую я использовал:

https://github.com/terryworona/TWMessageBarManager

https://github.com/toursprung/TSMessages


1
Хотя эта ссылка может ответить на вопрос, лучше включить сюда основные части ответа и предоставить ссылку для справки. Ответы, содержащие только ссылки, могут стать недействительными, если связанная страница изменится.
Роберт

1
TWMessageBarManagerможет быть легко вызван и использован через appdelegate, поскольку он использует шаблон проектирования Singleton. Спасибо за ссылки.
Джей Маю

8

Вот код для получения Push-уведомлений, когда приложение находится в активном состоянии (передний план или открыт). Документация UNUserNotificationCenter

@available(iOS 10.0, *)
func userNotificationCenter(center: UNUserNotificationCenter, willPresentNotification notification: UNNotification, withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void)
{
     completionHandler([UNNotificationPresentationOptions.Alert,UNNotificationPresentationOptions.Sound,UNNotificationPresentationOptions.Badge])
}

Если вам нужно получить доступ к userInfo уведомления, используйте код: notification.request.content.userInfo


где написать эту функцию ввиду загрузил? или ввиду контроллера класса?
iOS разработчик

что если я могу вызвать его в функции как вложенную функцию, будет ли она вызываться> ??
iOS разработчик

1
поместите это в класс AppDelegate. Вам не нужно вызывать эту функцию.
Милан Jayawardane

4

Добавление строки завершение в метод делегата решило ту же проблему для меня:

//Called when a notification is delivered to a foreground app.
@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {

completionHandler([.alert, .badge, .sound])
} 

3

Для быстрого 5, чтобы разобрать словарь PushNotification

    func application(_ application: UIApplication, didReceiveRemoteNotification data: [AnyHashable : Any]) {
            if application.applicationState == .active {
                if let aps1 = data["aps"] as? NSDictionary {
                    if let dict = aps1["alert"] as? NSDictionary {
                        if let strTitle = dict["title"] as? String , let strBody = dict["body"] as? String {
                            if let topVC = UIApplication.getTopViewController() {
                                //Apply your own logic as per requirement
                                print("strTitle ::\(strTitle) , strBody :: \(strBody)")
                            }
                        }
                    }
                }
            }
        }

Чтобы получить top viewController, на котором мы показываем topBanner

extension UIApplication {

    class func getTopViewController(base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {

        if let nav = base as? UINavigationController {
            return getTopViewController(base: nav.visibleViewController)

        } else if let tab = base as? UITabBarController, let selected = tab.selectedViewController {
            return getTopViewController(base: selected)

        } else if let presented = base?.presentedViewController {
            return getTopViewController(base: presented)
        }
        return base
    }
}

guardУтверждение является вашим другом :-)
Николя Миари

2

В вашем приложении делегат использует приведенный ниже код

import UIKit
import UserNotifications
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
 var currentToken: String?
 var window: UIWindow?
 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        application.registerForRemoteNotifications()
        let center = UNUserNotificationCenter.current()
        center.requestAuthorization(options: [.alert, .sound, .badge]) { (granted, error) in

            // Enable or disable features based on authorization.
            if granted == true
            {
                print("Allow")
                UIApplication.shared.registerForRemoteNotifications()
            }
            else
            {
                print("Don't Allow")
            }
        }
        UNUserNotificationCenter.current().delegate = self

        return true
    }
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data){
        let tokenParts = deviceToken.map { data -> String in
            return String(format: "%02.2hhx", data)
        }
        let token = tokenParts.joined()
        currentToken = token  //get device token to delegate variable

    }
 public class var shared: AppDelegate {
        return UIApplication.shared.delegate as! AppDelegate
    }
 func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
         completionHandler([.alert, .badge, .sound])
    }
}

1

Для Swift 5

1) Подтвердите делегата в AppDelegate с помощью UNUserNotificationCenterDelegate

2) UNUserNotificationCenter.current().delegate = selfвdidFinishLaunch

3) Реализуйте ниже метод в AppDelegate.

func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
     print("Push notification received in foreground.")
     completionHandler([.alert, .sound, .badge])
}

Это оно!


0

Как уже упоминалось выше, вы должны использовать UserNotification.frameworkдля достижения этой цели. Но для моих целей я все равно должен показать это в приложении и хотел иметь iOS 11стиль, поэтому я создал небольшое вспомогательное представление, может быть, кому-то это пригодится.

GitHub iOS 11 Просмотр push-уведомлений .


0

Лучший подход для этого является добавление UNUserNotificationCenterDelegateв AppDelegateс помощью extension AppDelegate: UNUserNotificationCenterDelegate этого добавочного номера рассказывает приложение , чтобы иметь возможность получить уведомление , когда в использовании

И реализовать этот метод

func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        completionHandler(.alert)
    }

Этот метод будет вызываться для делегата, только если приложение находится на переднем плане .

Итак, окончательная реализация:

extension AppDelegate: UNUserNotificationCenterDelegate {
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        completionHandler(.alert)
    }
}

И чтобы вызвать это, вы должны установить делегата в AppDelegate в didFinishLaunchingWithOptionsдобавить эту строку

UNUserNotificationCenter.current().delegate = self

Вы можете изменить

completionHandler(.alert) 

с участием

completionHandler([.alert, .badge, .sound]))

-2

Если ваше приложение находится в состоянии переднего плана, это означает, что вы в настоящее время используете то же приложение. Таким образом, нет необходимости показывать уведомление сверху.

Но, тем не менее, если вы хотите, чтобы в этом случае отображалось уведомление, вам нужно создать свой собственный просмотр предупреждений или пользовательский просмотр, например, Toast или что-то еще, чтобы показать пользователю, что вы получили уведомление.

Вы также можете показать значок сверху, если у вас есть такая функция в вашем приложении.


-3

Как сказал @Danial Martine, iOS не будет показывать баннер / предупреждение. Это по замыслу. Но если действительно нужно сделать это, то есть один способ. Я тоже добился этого тем же.

1. Загрузите работу разбора фрейма из Parse FrameWork

2.Import #import <Parse/Parse.h>

3. Добавьте следующий код в ваш метод didReceiveRemoteNotification.

 - (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
{
    [PFPush handlePush:userInfo];
}

PFPush позаботится о том, как обрабатывать удаленные уведомления. Если приложение находится на переднем плане, это показывает предупреждение, в противном случае оно показывает уведомление в верхней части.


предупреждение? ты имеешь ввиду бдительный вид?
iphondroid

1
но как получить обратный звонок для действий кнопки оповещения
Чарли
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.