Obtenga notificaciones push mientras la aplicación está en primer plano iOS

189

Estoy usando el servicio de notificaciones push en mi aplicación. Cuando la aplicación está en segundo plano, puedo ver notificaciones en la pantalla de notificaciones (pantalla que se muestra cuando deslizamos hacia abajo desde la parte superior del dispositivo iOS). Pero si la aplicación está en primer plano, el método delegado

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

se llama pero no se muestra la notificación en la pantalla de notificación.

Quiero mostrar notificaciones en la pantalla de notificaciones independientemente de si la aplicación está en segundo plano o en primer plano. Estoy cansado de buscar una solución. Cualquier ayuda es muy apreciada.

Ab'initio
fuente
35
Apple dice : si recibe notificaciones locales o remotas mientras su aplicación se está ejecutando en primer plano, usted es responsable de pasar la información a sus usuarios de una manera específica de la aplicación.
Lauri Lehmijoki
2
Algunos enlaces de Apple actualizados (oct "16): aquí , allá y allá
azmeuk
1
¿No es el soporte en primer plano de notificaciones push para iOS 9.3 y menos?
Anurag Sharma
@Lauri Lehmijoki enlace? No encontré eso en el sitio web oficial
Vyachaslav Gerchicov
1
Estoy enfrentando el mismo problema en iónico ...
Sayed Mohd Ali

Respuestas:

204

Para mostrar un mensaje de banner mientras la aplicación está en primer plano, use el siguiente método.

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])
}

También debe registrar su delegado de aplicaciones como delegado para el centro de notificaciones:

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
      ...
   }
chengsam
fuente
Cuando se llama a este método?
Uma Madhavi
Guíeme, estoy sorprendido de mostrar una notificación desde arriba cuando mi aplicación está en segundo plano o en primer plano. Desde hace 2 semanas estoy trabajando con notificaciones push. Puedo recibir mensajes del servidor.
Uma Madhavi
@UmaMadhavi ¿Puedes recibir notificaciones push?
chengsam
21
No olvide establecer el delegado del Centro de notificaciones como delegado de la aplicación: UNUserNotificationsCenter.current().delegate = selfen la aplicación didFinishLaunchingWithOptions
Achintya Ashok
2
Para aquellos que todavía luchan, su UNUserNotificationCenter no UNUserNotificationsCenter con 's' antes del centro
Raj
58

El siguiente código funcionará para usted:

- (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];          
    }    
}
Mahesh Peri
fuente
Esto funciona. Un poco más de información sobre lo que hace; cuando la aplicación está en primer plano, aparece un cuadro de alerta de la interfaz de usuario nativa con el texto de notificación dentro ( titlees un texto en negrita ligeramente más grande y el messagetexto más pequeño debajo de eso. Un botón 'Aceptar' para descartar está en la parte inferior). La opción applicationIconBadgeNumber que se establece en 0 es ocultar el número que aparece en la parte superior del icono de la aplicación en Springboard (por ejemplo, el número de mensajes no leídos en una aplicación de correo). En este ejemplo, no sé si esa opción es necesaria.
jwinn
¿Funciona esto tanto para UNnotification como para UILocalNotification?
user6631314
38

Para cualquiera que esté interesado, terminé creando una vista personalizada que se parece al banner de inserción del sistema en la parte superior, pero agrega un botón de cierre (pequeña X azul) y una opción para tocar el mensaje para una acción personalizada. También admite el caso de más de una notificación recibida antes de que el usuario tuviera tiempo de leer / descartar las antiguas (sin límite de cuántas se pueden acumular ...)

Enlace a GitHub: AGPushNote

El uso es básicamente en línea:

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

Y se ve así en iOS7 (iOS6 tiene una apariencia de iOS6 ...)

ingrese la descripción de la imagen aquí

Aviel Gross
fuente
1
También ahora reinventado en Swift: github.com/charliewilliams/CWNotificationBanner (por mí)
buildsucceeded
Agradable, esto será útil.
无 夜 之 星辰
36

C objetivo

ingrese la descripción de la imagen aquí

Porque iOS 10necesitamos integrar el willPresentNotificationmétodo para mostrar el banner de notificación en foreground.

Si la aplicación está en modo de primer plano (activa)

- (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);
}
Ashwini Chougale
fuente
1
Simplemente copie el código y no olvide usar el protocolo UNUserNotificationCenterDelegate.
Nik Kov
si quiero mostrar una alerta en lugar de esta notificación, entonces?
Mihir Oza
@MihirOza ¿Quieres UIAlertController?
Ashwini Chougale
Lo sé, pero no quiero una ventana emergente de notificación cuando la aplicación está activa. Solo quiero alertas en mi aplicación.
Mihir Oza
24

Si la aplicación se ejecuta en primer plano, iOS no mostrará un banner / alerta de notificación. Eso es por diseño. Pero podemos lograrlo usando UILocalNotificationlo siguiente

  • Compruebe si la aplicación está en estado activo al recibir una
    notificación remota . Si está en estado activo, dispare una Notificación UILocal.

    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];
    }

RÁPIDO:

if application.applicationState == .active {
    var localNotification = UILocalNotification()
    localNotification.userInfo = userInfo
    localNotification.soundName = UILocalNotificationDefaultSoundName
    localNotification.alertBody = message
    localNotification.fireDate = Date()
    UIApplication.shared.scheduleLocalNotification(localNotification)
}
Ab'initio
fuente
86
No creo que esto ayude. Las notificaciones locales y remotas se tratan de la misma manera y, como resultado, cuando esta notificación local se apaga y si la aplicación se está ejecutando, la insignia / pancarta o el sonido no se mostrarán / reproducirán.
RPM
3
También dejará una entrada en el Centro de notificaciones de iOS
Ab'initio
3
Sin embargo, no lanzaría una notificación local cuando llegue una notificación push. En su lugar, lanzaría un comportamiento similar al que @ Rick77 mencionó: mostrar una alerta o alguna tostadora. Supongo que no tengo que volver a pasar por el sistema operativo por algo que el sistema operativo me pide que maneje.
Fábio Oliveira
3
Esta solución está funcionando, ya que las aplicaciones locales y remotas se manejan de la misma manera, donde cuando la aplicación está en primer plano, crear una notificación de ubicación cuando llegue la notificación remota no mostrará nada. El uso de alertas o alertas personalizadas es la solución
Hammer
18
Esto en realidad no funciona. De los documentos 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.
Chris Morse
15

Si la aplicación se ejecuta en primer plano, iOS no mostrará un banner / alerta de notificación. Eso es por diseño. Tienes que escribir un código para lidiar con la situación de que tu aplicación reciba una notificación mientras está en primer plano. Debe mostrar la notificación de la manera más adecuada (por ejemplo, agregar un número de insignia a un UITabBaricono, simular un banner del Centro de notificaciones, etc.).

Daniel Martín
fuente
1
pero en la aplicación de correo de iOS lo han hecho, recibirá un nuevo banner / alerta de notificación mientras la aplicación de correo está en primer plano
Ab'initio
3
@ Ab'initio No estoy seguro, pero en iOS no todas las aplicaciones son iguales. Supongo que la aplicación Stock Mail está utilizando algún tipo de API privada que no está disponible en el SDK público. O tal vez el código de notificación está haciendo una excepción con la identificación de la aplicación Mail de Apple.
Daniel Martín
1
¿¿Qué?? Estoy a punto de tener un ataque de furia arpía.
Josh
@ DanielMartín, ¿podría decirme cómo recibiré una notificación en primer plano en iOS 8.0
Dilip Tiwari
9
Tenga en cuenta que esta respuesta es cierta solo para iOS 9 y versiones anteriores . Desde iOS 10, Apple introdujo una nueva API para manejar las notificaciones (la UNUserNotificationCenter API). Junto con la nueva API, ahora es posible mostrar las notificaciones si la aplicación está en primer plano. Entonces, si está confundido debido a las diferentes respuestas en esta pregunta, es porque algunas de las respuestas son demasiado antiguas y solo describen el comportamiento para iOS 9 y anteriores, mientras que las otras no tienen en cuenta que UNUserNotificationCenter solo está disponible en iOS 10.
tomacco
12

Xcode 10 Swift 4.2

Para mostrar notificaciones push cuando su aplicación está en primer plano:

Paso 1: agregue delegado UNUserNotificationCenterDelegate en la clase AppDelegate.

class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {

Paso 2: configurar el delegado UNUserNotificationCenter

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

Paso 3: este paso permitirá que su aplicación muestre notificaciones push incluso cuando su aplicación esté en primer plano

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

    }

Paso 4: este paso es opcional . Compruebe si su aplicación está en primer plano y si está en primer plano, luego muestre Notificación local de inserción.

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()
        }
    }

Función de notificación local

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)
    }
Prashant Gaikwad
fuente
1
Este es un gran ejemplo de la necesidad de leer todas las respuestas a un hilo. Los subprocesos anteriores mencionan el método, que el delegado y finalmente este, los tres pasos que debe realizar. GRACIAS Prashant por una respuesta completa!
user3069232
Es bueno saber que te ayudó. Feliz codificación
Prashant Gaikwad
10

Segun apple documentación de , Sí, puede mostrar notificaciones mientras la aplicación se está ejecutandoingrese la descripción de la imagen aquí

SPatel
fuente
¿Dónde puedo escribir esa función en delegado de aplicación o en una clase específica?
Desarrollador iOS
¿Qué pasa si quiero escribir que methd a la vista se cargó?
Desarrollador iOS
puede escribir en cualquier lugar, pero la condición es que debe cumplir con el UNUserNotificationCenterDelegateprotocolo
SPatel
no se puede escribirviewDidLoad
SPatel
1
te sugiero que extiendas AppDelegateextension AppDelegate: UNUserNotificationCenterDelegate
SPatel el
9

Puede crear su propia notificación que imite la alerta de banner.

Una forma es crear una vista personalizada que se parezca a la pancarta y pueda animar y responder a toques. Con esto en mente, puede crear pancartas aún mejores con aún más funcionalidad.

O puede buscar una API que lo haga por usted y agregarlas como archivos pod a su proyecto.

Aquí hay una pareja que he usado:

https://github.com/terryworona/TWMessageBarManager

https://github.com/toursprung/TSMessages

marshy101
fuente
1
Si bien este enlace puede responder la pregunta, es mejor incluir las partes esenciales de la respuesta aquí y proporcionar el enlace como referencia. Las respuestas de solo enlace pueden volverse inválidas si la página vinculada cambia.
Robert
1
TWMessageBarManagerse puede invocar y usar fácilmente mediante appdelegate, ya que utiliza un patrón de diseño único. Gracias por los enlaces.
Jay Mayu
8

Aquí está el código para recibir notificaciones push cuando la aplicación está en estado activo (primer plano o abierto). Documentación de UNUserNotificationCenter

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

Si necesita acceder a la información de usuario de la notificación, use el código: notification.request.content.userInfo

Kavin Kumar Arumugam
fuente
¿Dónde escribir esta función a la vista se cargó? o en la clase de controlador de vista?
Desarrollador iOS
¿Qué pasa si puedo llamarlo en una función como una función anidada se llamaría> ??
Desarrollador iOS
1
pon esto en la clase AppDelegate. No tiene que llamar a esta función.
Milan Jayawardane
4

Agregar esa línea completeHandler para delegar el método resolvió el mismo problema para mí:

//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])
} 
Furkan S. Dağ
fuente
3

Para que Swift 5 analice el diccionario 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)")
                            }
                        }
                    }
                }
            }
        }

Para obtener vista superior Controlador en el que mostramos 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
    }
}
Hardik Thakkar
fuente
La guarddeclaración es tu amigo :-)
Nicolas Miari
2

En el delegado de su aplicación, use el siguiente código

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])
    }
}
Varun Naharia
fuente
0

Como se mencionó anteriormente, debe usar UserNotification.frameworkpara lograr esto. Pero para mis propósitos, tengo que mostrarlo en la aplicación de todos modos y quería tener iOS 11estilo, así que he creado una pequeña vista auxiliar, tal vez sería útil para alguien.

Vista de notificaciones push de GitHub iOS 11 .

Orest Savchak
fuente
0

Mejor enfoque para esto es agregar UNUserNotificationCenterDelegateen AppDelegatemediante el uso deextension AppDelegate: UNUserNotificationCenterDelegate Esa extensión le dice a la aplicación para que pueda obtener una notificación cuando esté en uso

E implementar este método

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

Este método se invocará en el delegado solo si la aplicación está en primer plano .

Entonces, la implementación final:

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

Y para llamar a esto, debe configurar el delegado en AppDelegate en didFinishLaunchingWithOptionsagregar esta línea

UNUserNotificationCenter.current().delegate = self

Puedes modificar

completionHandler(.alert) 

con

completionHandler([.alert, .badge, .sound]))
JhonnyTawk
fuente
0

Para Swift 5

1) Confirme el delegado a AppDelegate con UNUserNotificationCenterDelegate

2) UNUserNotificationCenter.current().delegate = selfendidFinishLaunch

3) Implemente el siguiente método en AppDelegate.

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

¡Eso es!

karthik
fuente
-2

Como @Danial Martine dijo, iOS no mostrará un banner / alerta de notificación. Eso es por diseño. Pero si realmente tiene que hacerlo, entonces hay una manera. También he logrado esto por igual.

1.Descargue el marco de análisis de Parse FrameWork

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

3.Agregue el siguiente código a su método didReceiveRemoteNotification

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

PFPush se encargará de cómo manejar la notificación remota. Si la aplicación está en primer plano, muestra la alerta; de lo contrario, muestra la notificación en la parte superior.

V-Xtreme
fuente
¿alerta? te refieres a una vista de alerta?
iphondroid
1
pero cómo recuperar la llamada para acciones del botón de alerta
Charlie
-2

Si su aplicación está en primer plano, significa que actualmente está utilizando la misma aplicación. Por lo tanto, no es necesario mostrar notificaciones en la parte superior en general.

Pero aún así, si desea mostrar una notificación en ese caso, debe crear su Vista de alerta personalizada o Vista personalizada como Toast o algo más para mostrarle al usuario que recibió una notificación.

También puede mostrar una insignia en la parte superior si tiene ese tipo de función en su aplicación.

SHIV
fuente