Receber notificação por push enquanto App no ​​iOS em primeiro plano

189

Estou usando o serviço de notificação por push no meu aplicativo. Quando o aplicativo está em segundo plano, consigo ver uma notificação na tela de notificação (a tela é exibida quando deslizamos o dedo para baixo na parte superior do dispositivo iOS). Mas se o aplicativo estiver em primeiro plano, o método delegado

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

está sendo chamado, mas a notificação não é exibida na tela de notificação.

Quero mostrar a notificação na tela de notificação, independentemente de o aplicativo estar em segundo plano ou em primeiro plano. Estou cansado de procurar uma solução. Qualquer ajuda é muito apreciada.

Ab'initio
fonte
35
A Apple diz : Se você receber notificações locais ou remotas enquanto o aplicativo estiver sendo executado em primeiro plano, será responsável por passar as informações aos seus usuários de uma maneira específica.
Lauri Lehmijoki 18/03/16
2
Alguns up-to-date (outubro "16) Ligações de maçã: aqui , ali e
azmeuk
1
não há suporte de notificação por push para iOS 9.3 e menos?
Anurag Sharma
@Lauri Lehmijoki link? Não achei isso no site oficial.
Vyachaslav Gerchicov
1
Estou enfrentando o mesmo problema em iônica ...
Sayed Mohd Ali

Respostas:

204

Para exibir a mensagem de faixa enquanto o aplicativo estiver em primeiro plano, use o seguinte 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])
}

Você também deve registrar o delegado do aplicativo como delegado da central de notificações:

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
fonte
Quando esse método é chamado?
Uma Madhavi
Por favor, guie-me, estou impressionado com a notificação da parte superior quando o plano de fundo do aplicativo ou o primeiro plano.Desde 2 semanas, estou trabalhando com notificações push.Eu posso receber uma mensagem do servidor.
Uma Madhavi
@UmaMadhavi Você pode receber notificações push?
chengsam
21
Não se esqueça de definir a Notificação de Centro delegado como delegado app: UNUserNotificationsCenter.current().delegate = selfem didFinishLaunchingWithOptions aplicação
Achintya Ashok
2
Para aqueles que ainda lutam, o UNUserNotificationCenter não o UNUserNotificationsCenter com 's' antes do centro
Raj
58

O código abaixo será um trabalho para você:

- (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
fonte
Isso funciona. Um pouco mais de informação sobre o que faz; quando o aplicativo está em primeiro plano, uma caixa de alerta da interface do usuário nativa é exibida com o texto de notificação (o titletexto em negrito é ligeiramente maior e o messagetexto menor.) A opção applicationIconBadgeNumber que está sendo definida como 0 é ocultar o número que aparece na parte superior do ícone do aplicativo no Springboard (por exemplo, significando o número de mensagens não lidas em um aplicativo de email). Neste exemplo, não sei se essa opção é necessária.
jwinn
Isso funciona para UNnotification AND UILocalNotification?
User6631314
38

Para qualquer pessoa que esteja interessada, acabei criando uma exibição personalizada que se parece com o banner push do sistema na parte superior, mas adiciona um botão Fechar (pequeno X azul) e uma opção para tocar na mensagem para ação personalizada. Ele também suporta o caso de mais de uma notificação chegar antes que o usuário tenha tempo de ler / descartar as antigas (sem limite de quantas podem acumular-se ...)

Link para GitHub: AGPushNote

O uso é basicamente on-liner:

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

E fica assim no iOS7 (o iOS6 tem uma aparência e funcionalidade do iOS6 ...)

insira a descrição da imagem aqui

Aviel Gross
fonte
1
Também agora reimaginado no Swift: github.com/charliewilliams/CWNotificationBanner (por mim)
buildsucceeded
Bom, isso deve ser útil.
17177
36

Objetivo C

insira a descrição da imagem aqui

Pois iOS 10precisamos integrar o willPresentNotificationmétodo para mostrar o banner de notificação no foreground.

Se o aplicativo estiver no modo de primeiro plano (ativo)

- (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
fonte
1
Basta copiar o código e não se esqueça de usar o protocolo UNUserNotificationCenterDelegate.
Nik Kov
se eu quiser mostrar um alerta em vez desta notificação, então?
precisa
@MihirOza Você quer o UIAlertController?
Ashwini Chougale
Eu sei, mas não quero pop-up de notificação quando o aplicativo estiver ativo. Quero apenas alerta no meu aplicativo.
Mihir Oza
24

Se o aplicativo estiver sendo executado em primeiro plano, o iOS não mostrará um banner / alerta de notificação. Isso é por design. Mas podemos alcançá-lo usando UILocalNotificationo seguinte

  • Verifique se o aplicativo está no estado ativo ao receber uma
    notificação remota . Se estiver no estado ativo, dispare uma 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];
    }

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
fonte
86
Eu não acho que isso vai ajudar. As notificações locais e remotas são tratadas da mesma forma e, como resultado, quando essa notificação local é acionada e se o aplicativo estiver em execução, o emblema / banner ou som não será exibido / reproduzido.
RPM
3
Ele também deixará uma entrada no iOS Notification Center
Ab'initio
3
No entanto, eu não lançaria uma notificação local quando surgisse uma notificação por push. Eu iniciaria um comportamento semelhante, como @ Rick77 mencionado: mostrando um alerta ou uma torradeira. Acho que não preciso passar pelo sistema operacional novamente para algo que o sistema operacional está me pedindo para manipular.
Fábio Oliveira
3
Esta solução está funcionando, pois local e remoto são tratados da mesma maneira, quando, quando o aplicativo está em primeiro plano, a criação de uma notificação de localização quando a notificação remota chega não mostra nada. Usando alerta ou alerta personalizado é a solução
Martelo
18
Isso realmente não funciona. Desde a documentação do 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

Se o aplicativo estiver sendo executado em primeiro plano, o iOS não mostrará um banner / alerta de notificação. Isso é por design. Você precisa escrever um código para lidar com a situação do seu aplicativo que recebe uma notificação enquanto está em primeiro plano. Você deve mostrar a notificação da maneira mais apropriada (por exemplo, adicionando um número de crachá a um UITabBarícone, simulando um banner da Central de Notificações, etc.).

Daniel Martín
fonte
1
mas no aplicativo de email do iOS, eles receberão um novo banner / alerta de notificação enquanto o aplicativo de email em primeiro plano
Ab'initio
3
@ Ab'initio Não sei ao certo, mas no iOS todos os aplicativos não são criados iguais. Suponho que o aplicativo de email padrão esteja usando algum tipo de API privada que não está disponível no SDK público. Ou talvez o código de notificação esteja abrindo uma exceção com o ID do aplicativo Mail da Apple.
Daniel Martín
1
O que?? Estou prestes a ter um ataque de fúria harpia.
Josh
@ Danielmartin u poderia me dizer como eu vou receber uma notificação no Estado de primeiro plano no iOS 8.0
Dilip Tiwari
9
Lembre-se de que esta resposta é verdadeira apenas para iOS 9 e versões inferiores . Desde o iOS 10, a Apple introduziu uma nova API para lidar com notificações (a UNUserNotificationCenter API). Juntamente com a nova API, agora é possível mostrar as notificações se o aplicativo estiver em primeiro plano. Portanto, se você estiver confuso por causa das respostas diferentes nesta pergunta, é porque algumas das respostas são muito antigas e descrevem apenas o comportamento do iOS 9 e anterior, enquanto as outras não levam em conta que o UNUserNotificationCenter conteúdo está disponível apenas em iOS 10.
tomacco
12

Xcode 10 Swift 4.2

Para mostrar a notificação por push quando seu aplicativo estiver em primeiro plano -

Passo 1 : adicione delegado UNUserNotificationCenterDelegate na classe AppDelegate.

class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {

Passo 2 : definir o delegado UNUserNotificationCenter

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

Etapa 3: esta etapa permitirá que seu aplicativo mostre a notificação por push mesmo quando o aplicativo estiver em primeiro plano

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

    }

Etapa 4: esta etapa é opcional . Verifique se o aplicativo está em primeiro plano e se está em primeiro plano e, em seguida, mostre a PushNotification local.

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

Função de Notificação 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
fonte
1
Este é um ótimo exemplo da necessidade de ler todas as respostas em um tópico. Os threads anteriores mencionam o método, que o delegado e, finalmente, este, todos os três passos que você precisa executar. OBRIGADO Prashant por uma resposta completa!
user3069232
É bom saber que isso ajudou você. Feliz codificação
Prashant Gaikwad 14/02
10

De acordo com a documentação da apple , Sim, você pode exibir uma notificação enquanto o aplicativo está sendo executadoinsira a descrição da imagem aqui

SPatel
fonte
Onde posso escrever essa função no delegado do aplicativo ou em uma classe específica?
Desenvolvedor iOS
e se eu quiser escrever que o methd em vista foi carregado?
Desenvolvedor iOS
você pode escrever em qualquer lugar, mas a condição é que deve estar de acordo com UNUserNotificationCenterDelegateo protocolo
SPatel
você não pode escreverviewDidLoad
SPatel
1
eu sugiro que você estenda AppDelegateextension AppDelegate: UNUserNotificationCenterDelegate
SPatel
9

Você pode criar sua própria notificação que imita o alerta do banner.

Uma maneira é criar uma visão geral personalizada que se pareça com o banner e possa animar e responder a toques. Com isso em mente, você pode criar banners ainda melhores com ainda mais funcionalidade.

Ou você pode procurar uma API que faça isso por você e adicioná-las como podfiles ao seu projeto.

Aqui estão algumas que eu usei:

https://github.com/terryworona/TWMessageBarManager

https://github.com/toursprung/TSMessages

marshy101
fonte
1
Embora esse link possa responder à pergunta, é melhor incluir aqui as partes essenciais da resposta e fornecer o link para referência. As respostas somente para links podem se tornar inválidas se a página vinculada for alterada.
Robert
1
TWMessageBarManagerpode ser facilmente chamado e usado via appdelegate, pois usa o padrão de design singleton. Obrigado pelos links.
21415 Jay Mayu
8

Aqui está o código para receber a notificação por push quando o aplicativo estiver no estado ativo (em primeiro plano ou aberto). Documentação UNUserNotificationCenter

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

Se você precisar acessar as informações do usuário da notificação, use o código: notification.request.content.userInfo

Kavin Kumar Arumugam
fonte
onde escrever esta função em vista carregou? ou na classe de controlador de exibição?
Desenvolvedor iOS
e se eu puder chamá-lo em uma função como uma função aninhada, seria chamado> ??
Desenvolvedor iOS
1
coloque isso na classe AppDelegate. Você não precisa chamar esta função.
Milan Jayawardane
4

Adicionar essa linha completeHandler para delegar o método resolveu o mesmo problema para mim:

//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ğ
fonte
3

Para o Swift 5 analisar o dicionário 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 obter o viewController superior no qual 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
fonte
A guardafirmação é do seu amigo :-)
Nicolas Miari 23/03
2

No delegado do aplicativo, use o código abaixo

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
fonte
0

Como mencionado acima, você deve usar UserNotification.frameworkpara conseguir isso. Mas, para os meus propósitos, tenho que mostrá-lo no aplicativo de qualquer maneira e queria ter iOS 11estilo, por isso criei uma pequena exibição auxiliar, talvez fosse útil para alguém.

Visualização de notificação por push do iOS 11 do GitHub .

Orest Savchak
fonte
0

Melhor abordagem para este objetivo é adicionar UNUserNotificationCenterDelegateem AppDelegateusandoextension AppDelegate: UNUserNotificationCenterDelegate Isso extensão informa o aplicativo para ser capaz de obter uma notificação quando em uso

E implemente esse método

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

Este método será chamado no delegado apenas se o aplicativo estiver em primeiro plano .

Portanto, a implementação final:

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

E para chamar isso, você deve definir o delegado no AppDelegate em didFinishLaunchingWithOptionsadicionar esta linha

UNUserNotificationCenter.current().delegate = self

Você pode modificar

completionHandler(.alert) 

com

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

Para Swift 5

1) Confirme o delegado no AppDelegate com UNUserNotificationCenterDelegate

2) UNUserNotificationCenter.current().delegate = selfemdidFinishLaunch

3) Implemente o método abaixo em AppDelegate.

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

É isso aí!

Karthik
fonte
-2

Como o @Danial Martine disse que o iOS não mostrará um banner / alerta de notificação. Isso é por design. Mas se realmente for necessário, existe um caminho. Eu também consegui isso da mesma forma.

1. Faça o download do trabalho do quadro de análise no Parse FrameWork

2.Importação #import <Parse/Parse.h>

3. Adicione o seguinte código ao seu método didReceiveRemoteNotification

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

O PFPush cuidará de como lidar com a notificação remota. Se o aplicativo estiver em primeiro plano, isso mostra o alerta, caso contrário, mostra a notificação na parte superior.

V-Xtreme
fonte
alerta? você quer dizer uma visão de alerta?
Iphondroid
1
mas como chegar chamada de volta para ações de botão de alerta
Charlie
-2

Se o seu aplicativo estiver no estado de primeiro plano, isso significa que você está usando o mesmo aplicativo. Portanto, não há necessidade de mostrar notificações no topo em geral.

Ainda assim, se você quiser mostrar uma notificação nesse caso, precisará criar sua Visualização de alerta personalizada ou Visualização personalizada como o Toast ou algo mais para mostrar ao usuário que você recebeu uma notificação.

Você também pode mostrar um selo na parte superior se tiver esse tipo de recurso no seu aplicativo.

SHIV
fonte