Recevez une notification push lorsque l'application est au premier plan iOS

192

J'utilise le service de notification push dans mon application. Lorsque l'application est en arrière-plan, je peux voir la notification sur l'écran de notification (écran affiché lorsque nous glissons du haut de l'appareil iOS vers le bas). Mais si l'application est au premier plan, la méthode déléguée

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

est appelé mais la notification n'est pas affichée dans l'écran de notification.

Je souhaite afficher une notification sur l'écran de notification, que l'application soit en arrière-plan ou au premier plan. Je suis fatigué de chercher une solution. Toute aide est grandement appréciée.

Ab'initio
la source
35
Apple dit : Si vous recevez des notifications locales ou à distance pendant que votre application s'exécute au premier plan, vous êtes responsable de transmettre les informations à vos utilisateurs d'une manière spécifique à l'application.
Lauri Lehmijoki
2
Quelques liens Apple à jour (oct "16): ici , et
azmeuk
1
n'est pas le support au premier plan de la notification push pour iOS 9.3 et moins?
Anurag Sharma
Lien @Lauri Lehmijoki? Je n'ai pas trouvé cela sur le site officiel
Vyachaslav Gerchicov
1
Je suis confronté au même problème en ionique ...
Sayed Mohd Ali

Réponses:

208

Pour afficher le message de la bannière lorsque l'application est au premier plan, utilisez la méthode suivante.

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

Vous devez également enregistrer votre délégué d'application en tant que délégué pour le centre de notifications:

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
la source
Quand cette méthode est-elle appelée?
Uma Madhavi
S'il vous plaît, guidez-moi, je suis frappé d'afficher une notification du haut lorsque mon application en arrière-plan ou au premier plan.Depuis 2 semaines, je travaille avec des notifications push.Je suis en mesure de recevoir des msg du serveur.
Uma Madhavi
@UmaMadhavi Pouvez-vous recevoir des notifications push?
chengsam
21
N'oubliez pas de définir le délégué du centre de notifications en tant que délégué d'application: UNUserNotificationsCenter.current().delegate = selfdans l'application didFinishLaunchingWithOptions
Achintya Ashok
2
Pour ceux qui ont encore du mal, son UNUserNotificationCenter pas UNUserNotificationsCenter avec 's' avant le centre
Raj
58

Le code ci-dessous fonctionnera pour vous:

- (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
la source
Cela marche. Un peu plus d'informations sur ce qu'il fait; lorsque l'application est au premier plan, une boîte d'alerte de l'interface utilisateur native apparaît avec le texte de notification à l'intérieur (le texte titleest légèrement plus grand en gras et le messagetexte est plus petit en dessous. Un bouton "OK" pour ignorer se trouve en bas). L'option applicationIconBadgeNumber définie sur 0 consiste à masquer le nombre qui apparaît en haut de l'icône de l'application dans Springboard (par exemple, indiquant le nombre de messages non lus dans une application de messagerie). Dans cet exemple, je ne sais pas si cette option est même nécessaire.
jwinn
Cela fonctionne-t-il à la fois pour UNnotification ET UILocalNotification?
user6631314
38

Pour tous ceux qui pourraient être intéressés, j'ai fini par créer une vue personnalisée qui ressemble à la bannière push du système en haut, mais ajoute un bouton de fermeture (petit X bleu) et une option pour appuyer sur le message pour une action personnalisée. Il prend également en charge le cas de plus d'une notification arrivée avant que l'utilisateur n'ait le temps de lire / rejeter les anciennes (sans limite au nombre de notifications pouvant s'empiler ...)

Lien vers GitHub: AGPushNote

L'utilisation est essentiellement en ligne:

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

Et cela ressemble à ceci sur iOS7 (iOS6 a un look and feel iOS6 ...)

entrez la description de l'image ici

Aviel Gross
la source
1
Également maintenant repensé dans Swift: github.com/charliewilliams/CWNotificationBanner (par moi)
buildsucceeded
Bien , cela sera utile.
无 夜 之 星辰
35

Objectif c

entrez la description de l'image ici

Car iOS 10nous avons besoin d'une willPresentNotificationméthode d' intégration pour afficher la bannière de notification dans foreground.

Si l'application en mode premier plan (active)

- (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
la source
1
Copiez simplement le code et n'oubliez pas d'utiliser le protocole UNUserNotificationCenterDelegate.
Nik Kov le
si je veux afficher une alerte au lieu de cette notification, alors?
Mihir Oza
@MihirOza Vous voulez UIAlertController?
Ashwini Chougale
Je sais mais je ne veux pas de popup de notification lorsque l'application est active. Je veux seulement une alerte dans mon application.
Mihir Oza
J'ai essayé votre fonction mais je n'arrive toujours pas à être poussé au premier plan
Khaled Boussoffara
25

Si l'application s'exécute au premier plan, iOS n'affichera pas de bannière / alerte de notification. C'est par conception. Mais nous pouvons y parvenir en utilisant UILocalNotificationcomme suit

  • Vérifiez si l'application est à l'état actif lors de la réception d'une
    notification à distance . Si dans l'état actif, déclenchez un 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];
    }

RAPIDE:

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
la source
86
Je ne pense pas que cela aidera. Les notifications locales et distantes sont traitées de la même manière et, par conséquent, lorsque cette notification locale se déclenche et si l'application est en cours d'exécution, le badge / bannière ou le son ne sera pas affiché / lu.
RPM
3
Il laissera également une entrée dans le centre de notification iOS
Ab'initio
3
Cependant, je ne lancerais pas de notification locale lorsqu'une notification push arrive. Je lancerais plutôt un comportement similaire, comme @ Rick77 l'a mentionné: afficher une alerte ou un grille-pain. Je suppose que je n'ai pas à passer par le système d'exploitation à nouveau pour quelque chose que le système d'exploitation me demande de gérer.
Fábio Oliveira
3
Cette solution fonctionne, car local et distant sont gérés de la même manière, lorsque l'application est au premier plan, la création d'une notification de localisation lorsque la notification à distance arrive ne montre rien. Utiliser une alerte ou une alerte personnalisée est la solution
Hammer
19
Cela ne fonctionne pas vraiment. Extrait de la documentation 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 l'application s'exécute au premier plan, iOS n'affichera pas de bannière / alerte de notification. C'est par conception. Vous devez écrire du code pour gérer la situation dans laquelle votre application reçoit une notification alors qu'elle est au premier plan. Vous devez afficher la notification de la manière la plus appropriée (par exemple, ajouter un numéro de badge à une UITabBaricône, simuler une bannière du centre de notifications, etc.).

Daniel Martín
la source
1
mais dans l'application de messagerie iOS, ils l'ont fait, vous obtiendrez une nouvelle bannière / alerte de notification tandis que l'application de messagerie au premier plan
Ab'initio
3
@ Ab'initio Je ne sais pas avec certitude, mais sous iOS, toutes les applications ne sont pas créées égales. Je suppose que l'application de messagerie courante utilise une sorte d'API privée qui n'est pas disponible dans le SDK public. Ou peut-être que le code de notification fait une exception avec l'identifiant de l'application Mail d'Apple.
Daniel Martín
1
Quoi?? Je suis sur le point d'avoir une attaque de rage de harpie.
Josh
@ DanielMartín pourriez-vous me dire comment vais-je recevoir une notification au premier plan dans iOS 8.0
Dilip Tiwari
10
Gardez à l'esprit que cette réponse n'est vraie que pour iOS 9 et les versions antérieures . Depuis iOS 10, Apple a introduit une nouvelle API pour gérer les notifications (l' UNUserNotificationCenter API). Avec la nouvelle API, il est désormais possible d'afficher les notifications si l'application est au premier plan. Donc si vous êtes confus parce que les différentes réponses à cette question, c'est parce que certaines des réponses sont trop anciennes, et ne décrivent que le comportement pour iOS 9 et avant, alors que les autres ne tiennent pas compte du fait que le UNUserNotificationCenter n'est disponible que depuis iOS 10.
tomacco
13

Xcode 10 Swift 4.2

Pour afficher la notification push lorsque votre application est au premier plan -

Étape 1: ajoutez le délégué UNUserNotificationCenterDelegate dans la classe AppDelegate.

class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {

Étape 2: définir le délégué UNUserNotificationCenter

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

Étape 3: Cette étape permettra à votre application d'afficher la notification push même lorsque votre application est au premier plan

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

    }

Étape 4: Cette étape est facultative . Vérifiez si votre application est au premier plan et si elle est au premier plan, puis affichez 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()
        }
    }

Fonction de notification locale -

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
la source
1
Ceci est un excellent exemple de la nécessité de lire toutes les réponses à un fil de discussion. Les threads précédents mentionnent la méthode, le délégué et enfin celui-ci les trois étapes que vous devez effectuer. MERCI Prashant pour une réponse complète!
user3069232 le
C'est bon de savoir que cela vous a aidé. Happy coding
Prashant Gaikwad le
11

Selon la documentation Apple , Oui, vous pouvez afficher une notification pendant que l'application est en cours d'exécutionentrez la description de l'image ici

SPatel
la source
où puis-je écrire cette fonction dans le délégué d'application ou dans une classe spécifique ??
Développeur iOS
Et si je veux écrire que methd en vue a été chargé ??
Développeur iOS
vous pouvez écrire n'importe où, mais à condition qu'il soit conforme au UNUserNotificationCenterDelegateprotocole
SPatel
vous ne pouvez pas écrireviewDidLoad
SPatel
1
Je vous suggère d'étendre AppDelegateextension AppDelegate: UNUserNotificationCenterDelegate
SPatel
9

Vous pouvez créer votre propre notification qui imite l'alerte de bannière.

Une façon consiste à créer une vue uiview personnalisée qui ressemble à la bannière et peut animer et répondre aux touches. Dans cet esprit, vous pouvez créer des bannières encore meilleures avec encore plus de fonctionnalités.

Ou vous pouvez rechercher une API qui le fait pour vous et les ajouter en tant que podfiles à votre projet.

Voici quelques exemples que j'ai utilisés:

https://github.com/terryworona/TWMessageBarManager

https://github.com/toursprung/TSMessages

marécageux101
la source
1
Bien que ce lien puisse répondre à la question, il est préférable d'inclure les parties essentielles de la réponse ici et de fournir le lien pour référence. Les réponses aux liens uniquement peuvent devenir invalides si la page liée change.
Robert
1
TWMessageBarManagerpeut être facilement invoqué et utilisé via appdelegate lui-même car il utilise un modèle de conception singleton. Merci pour les liens.
Jay Mayu
8

Voici le code pour recevoir une notification push lorsque l'application est à l'état actif (au premier plan ou ouverte). Documentation UNUserNotificationCenter

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

Si vous devez accéder à userInfo de notification, utilisez le code: notification.request.content.userInfo

Kavin Kumar Arumugam
la source
où écrire cette fonction dans la vue a chargé? ou dans la classe de contrôleur de vue?
Développeur iOS
et si je peux l'appeler dans une fonction en tant que fonction imbriquée serait-il appelé> ??
Développeur iOS
1
mettez ceci dans la classe AppDelegate. Vous n'avez pas besoin d'appeler cette fonction.
Milan Jayawardane
4

L'ajout de cette ligne completionHandler à la méthode de délégation a résolu le même problème pour moi:

//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ğ
la source
3

Pour Swift 5 pour analyser le dictionnaire 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)")
                            }
                        }
                    }
                }
            }
        }

Pour récupérer la vue de dessusContrôleur sur lequel nous montrons 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
la source
La guarddéclaration est votre ami :-)
Nicolas Miari
2

Dans votre délégué d'application, utilisez le code ci-dessous

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
la source
1

Pour Swift 5

1) Confirmez le délégué à AppDelegate avec UNUserNotificationCenterDelegate

2) UNUserNotificationCenter.current().delegate = selfdansdidFinishLaunch

3) Implémentez la méthode ci-dessous dans AppDelegate.

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

C'est tout!

Karthik
la source
0

Comme mentionné ci-dessus, vous devez utiliser UserNotification.frameworkpour y parvenir. Mais pour mes besoins, je dois quand même le montrer dans l'application et iOS 11je voulais avoir du style, j'ai donc créé une petite vue d'aide, ce qui serait peut-être utile pour quelqu'un.

Affichage des notifications push GitHub iOS 11 .

Orest Savchak
la source
0

La meilleure approche pour cela est d'ajouter UNUserNotificationCenterDelegateen AppDelegateutilisant extension AppDelegate: UNUserNotificationCenterDelegate cette extension indique à l'application d'être en mesure de recevoir une notification lorsqu'elle est utilisée

Et implémentez cette méthode

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

Cette méthode sera appelée sur le délégué uniquement si l'application est au premier plan .

Donc, la mise en œuvre finale:

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

Et pour appeler cela, vous devez définir le délégué dans AppDelegate en didFinishLaunchingWithOptionsajoutant cette ligne

UNUserNotificationCenter.current().delegate = self

Vous pouvez modifier

completionHandler(.alert) 

avec

completionHandler([.alert, .badge, .sound]))
JhonnyTawk
la source
-2

Si votre application est au premier plan, cela signifie que vous utilisez actuellement la même application. Il n'est donc pas nécessaire d'afficher une notification en haut en général.

Mais toujours si vous souhaitez afficher une notification dans ce cas, vous devez créer votre vue d'alerte personnalisée ou vue personnalisée comme Toast ou autre chose pour montrer à l'utilisateur que vous avez reçu une notification.

Vous pouvez également afficher un badge en haut si vous disposez de ce type de fonctionnalité dans votre application.

SHIV
la source
-3

Comme @Danial Martine l'a dit, iOS n'affichera pas de bannière / alerte de notification. C'est par conception. Mais s'il faut vraiment le faire, il y a un moyen. J'ai également réalisé cela par le même.

1.Téléchargez le travail du cadre d'analyse à partir de Parse FrameWork

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

3.Ajoutez le code suivant à votre méthode didReceiveRemoteNotification

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

PFPush prendra soin de gérer la notification à distance. Si l'application est au premier plan, cela affiche l'alerte, sinon la notification en haut.

V-Xtreme
la source
alerte? vous voulez dire une vue d'alerte?
iphondroid
1
mais comment obtenir un rappel pour les actions du bouton d'alerte
Charlie