Anzeigen eines Standard-iOS-Benachrichtigungsbanners, wenn Ihre App geöffnet ist und im Vordergrund steht?

123

Wenn Apples offizielle iOS-Nachrichten-App geöffnet ist und im Vordergrund steht, lösen neue Nachrichten von anderen Kontakten ein natives iOS-Benachrichtigungsbanner aus. Siehe Bild unten.

Ist dies in Apps von Drittanbietern im App Store möglich? Lokale und / oder Push-Benachrichtigungen für Ihre App, während Ihre App geöffnet ist und im Vordergrund steht ?

Beim Testen meiner App werden Benachrichtigungen empfangen, aber es wird keine Benutzeroberfläche für iOS-Warnungen angezeigt .

Dieses Verhalten ist jedoch in Apples offizieller Nachrichten-App zu sehen:

Nachrichten sind offen und im Vordergrund.  Zeigt weiterhin eine Benachrichtigung an.

Das Programmierhandbuch für lokale und Remote-Benachrichtigungen lautet:

Wenn das Betriebssystem eine lokale Benachrichtigung oder eine Remote-Benachrichtigung übermittelt und die Ziel-App nicht im Vordergrund ausgeführt wird , kann es dem Benutzer die Benachrichtigung über eine Warnung , eine Symbolausweisnummer oder einen Sound anzeigen.

Wenn die App bei der Zustellung der Benachrichtigung im Vordergrund ausgeführt wird, erhält der App-Delegat eine lokale oder Remote-Benachrichtigung.

Ja, wir können die Benachrichtigungsdaten im Vordergrund empfangen . Ich sehe jedoch keine Möglichkeit, die native Benutzeroberfläche für iOS-Benachrichtigungen anzuzeigen .

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo 
{
    // I know we still receive the notification `userInfo` payload in the foreground.
    // This question is about displaying the stock iOS notification alert UI.

    // Yes, one *could* use a 3rd party toast alert framework. 
    [self use3rdPartyToastAlertFrameworkFromGithub]
}

Verwenden Nachrichten dann eine private API, um die Warnung im Vordergrund anzuzeigen?

Für die Zwecke dieser Frage, bitte geben keinen Hinweis auf 3rd - Party „Toast“ Pop-up - Benachrichtigungen auf GitHub oder etc. Ich bin nur interessiert , wenn dies mit der getan werden kann , Lager, nativen iOS Lokale oder Push Notification Benachrichtigung UI während Anwendung ist offen und im Vordergrund .

pkamb
quelle

Antworten:

152

iOS 10 fügt das UNUserNotificationCenterDelegateProtokoll für die Verarbeitung von Benachrichtigungen hinzu, während sich Ihre App im Vordergrund befindet.

Das UNUserNotificationCenterDelegateProtokoll definiert Methoden zum Empfangen von Benachrichtigungen und zum Behandeln von Aktionen. Wenn sich Ihre App im Vordergrund befindet, werden ankommende Benachrichtigungen an Ihr Delegatenobjekt gesendet und nicht automatisch über die Systemschnittstellen angezeigt.

Schnell:

optional func userNotificationCenter(_ center: UNUserNotificationCenter, 
                     willPresent notification: UNNotification, 
      withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void)

Ziel c:

- (void)userNotificationCenter:(UNUserNotificationCenter *)center 
       willPresentNotification:(UNNotification *)notification 
         withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler;

Mit den Flags UNNotificationPresentationOptions können Sie festlegen UNNotificationPresentationOptionAlert, dass eine Warnung mithilfe des in der Benachrichtigung angegebenen Texts angezeigt werden soll.

Dies ist wichtig, da Sie die Warnung anzeigen können, während Ihre App geöffnet ist, und im Vordergrund , was für iOS 10 neu ist.


Beispielcode:

class AppDelegate: UIResponder, UIApplicationDelegate {
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        // Set UNUserNotificationCenterDelegate
        UNUserNotificationCenter.current().delegate = self
        
        return true
    }
    
}

// Conform to UNUserNotificationCenterDelegate
extension AppDelegate: UNUserNotificationCenterDelegate {
    
    func userNotificationCenter(_ center: UNUserNotificationCenter,
           willPresent notification: UNNotification,
           withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void)
    {
        completionHandler(.alert)
    }
    
}
pkamb
quelle
4
Könnten Sie ein Arbeitscodebeispiel bereitstellen, in dem eine eingehende Vordergrundbenachrichtigung vom System angezeigt wird, als ob die Anwendung Hintergrundinformationen hätte?
Azmeuk
1
@azmeuk Überprüfen Sie meine Antwort ...
Chengsam
8
Vergessen Sie nicht, UNUserNotificationCenter.current().delegate = selfdie Methode application(_:willFinishLaunchingWithOptions:)oder hinzuzufügenapplication(_:didFinishLaunchingWithOptions:)
Deniss Fedotovs
3
Stellen Sie außerdem sicher, dass sich Ihr Gerät nicht im Modus "Nicht stören" befindet. Andernfalls werden die Benachrichtigungen im Benachrichtigungscenter
angezeigt
2
meine 2 Cent: nicht verpassen: UserNotifications importieren. !
Ingconti
94

Verwenden Sie die folgende Methode, um Bannermeldungen anzuzeigen, während sich die App im Vordergrund befindet.

iOS 10+, Swift 3+ :

func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    completionHandler([.alert, .badge, .sound])
}
Chengsam
quelle
1
Wow, überall, wo ich las, sagten die Leute, das sei nicht möglich. Ich bin so froh, dass ich diese Antwort gefunden habe, sie funktioniert genau so, wie ich es erwartet hatte! Wenn die App ausgeführt wird, werden Push-Benachrichtigungen jetzt genau so angezeigt, als ob die App im Hintergrund wäre. Danke dir!
Torre Lasley
1
Wohin geht dieser Ausschnitt? In der AppDelegate oder woanders?
Yoav R.
@ YoavR. AppDelegate
Chengsam
Ich habe den gleichen Code verwendet. Aber ich weiß nicht, warum die Benachrichtigung nicht angezeigt wird, wenn die App im Vordergrund war.
Boominadha Prakash M
2
Chengsam, vielleicht möchten Sie dies korrigieren: Es muss nicht in die AppDelegate. Es muss für jedes Objekt platziert werden, das dem entspricht UNUserNotificationCenterDelegate. Trotzdem passen sich die meisten Entwickler AppDelegatean UNUserNotificationCenterDelegate. @ YoavR.
Honig
16

BEARBEITEN:

Vordergrundwarnungen sind jetzt in iOS 10 möglich! Bitte sehen Sie diese Antwort .

Für iOS 9 und niedriger:

Es scheint nicht möglich zu sein, die Standard-iOS-Benachrichtigung anzuzeigen, wenn Ihre App geöffnet ist und im Vordergrund steht. Messages.app muss eine private API verwenden.

Das System zeigt keine Warnungen an, kennzeichnet das App-Symbol und spielt keine Sounds ab, wenn sich die App bereits ganz vorne befindet. - UILocalNotification-Dokumente

Die UIApplicationDelegateMethoden werden weiterhin aufgerufen, sodass Ihre App auf die lokale oder Remote-Benachrichtigung reagieren kann:

application:didReceiveLocalNotification:
application:didReceiveRemoteNotification:

Die native Benutzeroberfläche des iOS-Benachrichtigungsbanners wird jedoch nicht wie in Apples Messages.app angezeigt , für die eine private API verwendet werden muss.

Das Beste, was Sie tun können, ist, Ihr eigenes Warnbanner zu rollen oder ein vorhandenes Framework zu verwenden:

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo 
{    
    // Use a 3rd party toast alert framework to display a banner 
    [self toastAlertFromGithub]
}

Ich habe hier ein Radar für dieses Verhalten geöffnet: rdar://22313177

pkamb
quelle
3
Wie machen WhatsApp und andere berühmte Apps das dann?
Machado
@tardoandre haben einen Screenshot? Ich gehe davon aus, dass die Standard-iOS-Warnung in ihren eigenen Ansichten nachgeahmt wird.
pkamb
2
Sie sollten einen Link einfügen, toastAlertFromGithubwenn Sie die Verwendung dieser Drittanbieter-Bibliothek vorschlagen!
Ketan Parmar
14

Um Benachrichtigungen anzuzeigen, während die App geöffnet ist, müssen wir sie manuell bearbeiten. Was ich unten mache, ist, die Benachrichtigung zu bearbeiten, sobald sie empfangen wurde.

Fügen Sie alle unten in AppDelegate.m hinzu

  1. Anruf zur Benachrichtigung bearbeiten
  2. Erstellen Sie eine Ansicht, fügen Sie AppIcon, Benachrichtigungsnachricht hinzu und zeigen Sie sie als Animation an
  3. Fügen Sie den Touch-Erkenner hinzu, um ihn zu entfernen, wenn er berührt wird, oder entfernen Sie ihn in 5 Sekunden mit der Animation.

Lassen Sie mich wissen, ob dies eine gute Lösung ist. Hat bei mir gut funktioniert, bin mir aber nicht sicher, ob dies der richtige Weg ist.

- (void)application:(UIApplication *)applicationdidReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {


NSString *notifMessage = [[userInfo objectForKey:@"aps"] objectForKey:@"alert"];

//Define notifView as UIView in the header file
[_notifView removeFromSuperview]; //If already existing

_notifView = [[UIView alloc] initWithFrame:CGRectMake(0, -70, self.window.frame.size.width, 80)];
[_notifView setBackgroundColor:[UIColor blackColor]];

UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(10,15,30,30)];
imageView.image = [UIImage imageNamed:@"AppLogo.png"];

UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(60, 15, self.window.frame.size.width - 100 , 30)];
myLabel.font = [UIFont fontWithName:@"Helvetica" size:10.0];
myLabel.text = notifMessage;

[myLabel setTextColor:[UIColor whiteColor]];
[myLabel setNumberOfLines:0];

[_notifView setAlpha:0.95];

//The Icon
[_notifView addSubview:imageView];

//The Text
[_notifView addSubview:myLabel];

//The View
[self.window addSubview:_notifView];

UITapGestureRecognizer *tapToDismissNotif = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                                                    action:@selector(dismissNotifFromScreen)];
tapToDismissNotif.numberOfTapsRequired = 1;
tapToDismissNotif.numberOfTouchesRequired = 1;

[_notifView addGestureRecognizer:tapToDismissNotif];


[UIView animateWithDuration:1.0 delay:.1 usingSpringWithDamping:0.5 initialSpringVelocity:0.1 options:UIViewAnimationOptionCurveEaseIn animations:^{

    [_notifView setFrame:CGRectMake(0, 0, self.window.frame.size.width, 60)];

} completion:^(BOOL finished) {


}];


//Remove from top view after 5 seconds
[self performSelector:@selector(dismissNotifFromScreen) withObject:nil afterDelay:5.0];


return;


}

//If the user touches the view or to remove from view after 5 seconds
- (void)dismissNotifFromScreen{

[UIView animateWithDuration:1.0 delay:.1 usingSpringWithDamping:0.5 initialSpringVelocity:0.1 options:UIViewAnimationOptionCurveEaseIn animations:^{

    [_notifView setFrame:CGRectMake(0, -70, self.window.frame.size.width, 60)];

} completion:^(BOOL finished) {


}];


}
Hafeez
quelle
3
Dies ist möglicherweise eine gute Antwort für die Erstellung Ihrer eigenen Warnung, zeigt jedoch nicht die Stock- iOS-Warnung an, wie im Screenshot gezeigt.
pkamb
Hallo, danke für deine freundlichen Worte. Ja, es wird nicht so aussehen (wenn Sie über das Erscheinungsbild sprechen), da das oben im Bild gezeigte eine iOS-Benachrichtigung ist und das über Code benutzerdefinierte. Wir können vielleicht das Aussehen in der Ansicht replizieren. Ich denke, WhatsApp hat eine ordentlich aussehende mit Hintergrundunschärfe usw.
Hafeez
1
Jemand unten stimmte ab :(. Wäre schön zu hören warum!?. Danke.
Hafeez
2
Ich habe es getan, da der Code in dieser Antwort (so schön es auch sein mag) die gestellte Frage nicht wirklich beantwortet: Anzeigen eines Standard- iOS-Toastbanners in der App. Es gibt andere Fragen zu SO, bei denen diese Antwort großartig wäre.
Pkamb
1
Danke pkamb für die Klarstellung, macht Sinn. Ich habe das "Aktien" -Wort verpasst, denke ich.
Hafeez
10

Hier ist der Code zum Empfangen der Push-Benachrichtigung, wenn sich die App im Vordergrund oder in der offenen Phase befindet, iOS 10 & Swift 2.3

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

Wenn Sie auf userInfo der Benachrichtigung zugreifen müssen, verwenden Sie den folgenden Code: notification.request.content.userInfo

Die Methode userNotificationCenter(_:willPresent:withCompletionHandler:)wird nur aufgerufen, wenn Sie das Attribut zur Nutzlast hinzufügen content-available:1. Die endgültige Nutzlast sollte ungefähr so ​​lauten:

{
     "aps":{
          "alert":"Testing.. (7)",
          "badge":1,"sound":"default"
     },
     "content-available":1
}
Kavin Kumar Arumugam
quelle
1
userNotificationCenter(_:willPresent:withCompletionHandler:)wird aufgerufen, wenn Ihre App im Vordergrund läuft. Es spielt also KEINE Rolle bei " content-available ", was mit " background fetch " zusammenhängt.
DawnSong
9
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
content.body = body;
content.userInfo = userInfo;
content.sound = [UNNotificationSound defaultSound];
[content setValue:@(YES) forKeyPath:@"shouldAlwaysAlertWhileAppIsForeground"];

UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@"Notif" content:content trigger:nil];
[[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
    DLog(@"Error:%@", error);
}];

Ich kann eine Push-Benachrichtigung anzeigen, wenn die App für iOS 10 aktiv ist.

  1. Die Push-Benachrichtigung vom Server sollte stumm sein .

  2. Wenn Sie eine Remote-Benachrichtigung vom Server erhalten, senden Sie eine lokale Benachrichtigung und legen den Wert für keyPath fest: shouldAlwaysAlertWhileAppIsForeground = True

Nguyen Loc
quelle
in Swift 2 - ist es content.setValue("YES", forKeyPath: "shouldAlwaysAlertWhileAppIsForeground"), richtig? (mit "Ja" und nicht wahr)
Yoav R.
Achtung: Dies wird Ihre App unter iOS 12 zum Absturz bringen. Siehe Diskussion hier: stackoverflow.com/questions/41373321/…
Matt Bearson
5

Sie können die Benachrichtigung selbst bearbeiten und eine benutzerdefinierte Warnung anzeigen. Apps wie Viber, WhatsApp und BisPhone verwenden diesen Ansatz.

Ein Beispiel für eine benutzerdefinierte Warnung eines Drittanbieters ist CRToast .

Versuchen Sie, eine lokale Benachrichtigung zu planen, während sich Ihre App im Vordergrund befindet, und Sie werden feststellen, dass keine Standard-iOS-Warnung angezeigt wird:

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];
}
Mo Farhand
quelle
Vielen Dank, aber ich suche nur nach Antworten mithilfe der Standard-iOS-Benachrichtigung.
pkamb
1
ok, aber ich denke, du kannst es nicht tun, sieh dir auch diesen Link an: stackoverflow.com/questions/14872088/…
Mo Farhand
6
@matt Ich versuche, diese Frage zum Thema zu halten: Die Standard-iOS-Warnung wird im Vordergrund angezeigt. Viele andere "Best Toast Alert Framework" -Fragen. Eine Antwort „Nein, Sie können nicht den iOS - Alarm im Vordergrund anzeigen“ wäre durchaus akzeptabel sein, und ich werde diese Antwort akzeptieren , bis dies ist in einer zukünftigen Version von iOS möglich.
Pkamb
4

Swift 3 Version

Dies zeigt eine Warnung an, wenn sich die Anwendung im Vordergrund befindet.

if #available(iOS 10.0, *)
{
    // need to setup the global notification delegate somewhere when your app starts
    //
    UNUserNotificationCenter.current().delegate = applicationDelegate

    // to show a message
    //
    let content = UNMutableNotificationContent()
    content.body = "MESSAGE"

    let request = UNNotificationRequest(identifier: "fred", content: content, trigger: nil)
    UNUserNotificationCenter.current().add(request)
    {
       error in // called when message has been sent

       debugPrint("Error: \(error)")
    }
}

ApplicationDelegates Implementierung von UNUserNotificationCenterDelegate

@available(iOS 10.0, *)
public func userNotificationCenter(_ center : UNUserNotificationCenter, willPresent notification : UNNotification, withCompletionHandler completionHandler : @escaping (UNNotificationPresentationOptions) -> Void)
{
    completionHandler([.alert]) // only-always show the alert
}
Leslie Godwin
quelle
Nur um sicher zu gehen ... meinst du, seit iOS 10 kannst du jetzt auch Warnungen / Banner / Sounds im Vordergrund anzeigen, genau wie du es im Hintergrund tust?
Honey
Wo kann ich den obigen Codierungsteil platzieren? in hat ReceiveRemoteNotification?
user1960169
@Leslie Godwin wird es für iOS 8.0 funktionieren, um Benachrichtigungen im Vordergrund anzuzeigen
Dilip Tiwari
2

Um die lokale Benachrichtigung anzuzeigen, ist dies die beste Option. Benötigen Sie weniger Code, um "BRYXBanner" https://cocoapods.org/pods/BRYXBanner zu schreiben

let banner = Banner(title: "title", subtitle: "subtitle", image: UIImage(named: "addContact"), backgroundColor: UIColor(red:137.0/255.0, green:172.0/255.0, blue:2.0/255.0, alpha:1.000))
    banner.dismissesOnTap = true
    banner.show(duration: 1.0)
Mantosh Kumar
quelle
Dieses BRYXBannerFramework scheint nicht das Standard- iOS-Benachrichtigungsbanner zu verwenden.
Pkamb
1

Wenn Ihr Bereitstellungsziel> = iOS10 ist, verwenden Sie UNUserNotification wie folgt:

func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void)
    {
        // Change this to your preferred presentation option
        completionHandler([.alert, .sound])
    }
Vishwas Singh
quelle