アプリが開いていてフォアグラウンドにあるときに、ストックのiOS通知バナーを表示しますか?


123

Appleの公式iOSメッセージアプリが開いていてフォアグラウンドにあるとき、他の連絡先からの新しいメッセージが、在庫のネイティブiOS通知アラートバナーをトリガーします。下の画像を参照してください。

これはApp Storeのサードパーティアプリで可能ですか?ローカルおよび/またはあなたのアプリがありながら、アプリのプッシュ通知をオープンし、フォアグラウンドで

アプリをテストすると、通知は受信されますが、iOSアラートUIが表示されません

しかし、この動作 Appleの公式メッセージアプリで見られます。

メッセージは開いており、フォアグラウンドにあります。 引き続き通知アラートが表示されます。

ローカルおよびリモート通知プログラミングガイドは言います:

オペレーティングシステムがローカル通知またはリモート通知を配信し、ターゲットアプリがフォアグラウンド実行されていない場合、アラート、アイコンバッジ番号、またはサウンドを通じてユーザーに通知を表示できます。

通知の配信時にアプリがフォアグラウンドで実行されている場合、アプリのデリゲートはローカルまたはリモートの通知を受け取ります。

つまり、フォアグラウンドで通知データを受信できます。しかし、ネイティブのiOS通知アラートUIを表示する方法がわかりません。

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

その後、メッセージはプライベートAPIを使用して、フォアグラウンドでアラートを表示しますか?

この質問の目的で、githubなどでサードパーティの「トースト」ポップアップアラート提案しないください。これは、在庫、ネイティブiOSローカル、またはプッシュ通知アラートUI 使用してこれを実行できる場合にのみ興味があります。アプリケーションは開いており、フォアグラウンドにあります。

回答:


152

iOS 10では、UNUserNotificationCenterDelegateアプリがフォアグラウンドにあるときに通知を処理するためのプロトコルが追加されています。

UNUserNotificationCenterDelegateプロトコルは、通知を受信し、アクションを処理するためのメソッドを定義します。アプリがフォアグラウンドにある場合、到着した通知は、システムインターフェイスを使用して自動的に表示されるのではなく、デリゲートオブジェクトに配信されます。

迅速:

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

Objective-C:

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

UNNotificationPresentationOptionsのフラグを使用すると、指定することができUNNotificationPresentationOptionAlert、通知によって提供されたテキストを使用してアラートを表示します。

これは、アプリが開いているときにフォアグラウンドでアラートを表示できるため、重要です。これはiOS 10の新機能です。


サンプルコード:

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

4
アプリケーションがバックグラウンドであるかのように、着信フォアグラウンド通知がシステムによって表示される実際のコードサンプルを提供できますか?
azmeuk

1
@azmeuk私の答えを確認してください...
chengsam

8
追加することを忘れないでくださいUNUserNotificationCenter.current().delegate = selfapplication(_:willFinishLaunchingWithOptions:)またはapplication(_:didFinishLaunchingWithOptions:)方法
Deniss Fedotovsに

3
また、デバイスがサイレントモードになっていないことを確認してください。そうしないと、通知は通知センターに表示されますが、アプリケーションの前面には表示されません
Jadent

2
私の2セント:お見逃しなく:UserNotificationsをインポートしてください。!
ingconti

94

アプリがフォアグラウンドにあるときにバナーメッセージを表示するには、次のメソッドを使用します。

iOS 10以降、Swift 3以降

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

1
うわー、私が読んだところはどこでも、これは不可能だと言っていました。私はこの答えを見つけてうれしいです、それは期待通りに機能します!アプリの実行中に、アプリがバックグラウンドにある場合とまったく同じようにプッシュ通知が表示されるようになりました。ありがとうございました!
Torre Lasley、

1
このスニペットはどこに行きますか?appDelegate、または他のどこか?
Yoav R.

@YoavR。AppDelegate
chengsam 16

同じコードを使用しました。しかし、アプリがフォアグラウンドにあるときに通知が表示されない理由はわかりません。
Boominadha Prakash M 2017

2
Chengsamあなたはこれを修正したいと思うかもしれません:それをに置く必要はありませんAppDelegate。に準拠するすべてのオブジェクトに対して配置する必要がありますUNUserNotificationCenterDelegate。そうは言っても、ほとんどの開発者はにAppDelegate準拠していUNUserNotificationCenterDelegateます。@YoavR。
ハニー、

16

編集:

iOS 10でフォアグラウンドアラートが可能になりました。この回答をご覧ください

iOS 9以下の場合:

アプリが開いていてフォアグラウンドにあるときに、標準のiOS通知アラートを表示することができないようです。Messages.appはプライベートAPIを使用している必要があります。

アプリがすでに最前面にある場合、システムはアラートを表示したり、アプリのアイコンにバッジを付けたり、サウンドを再生したりしません。- UILocalNotificationドキュメント

UIApplicationDelegate方法がしますまだあなたのアプリは、ローカルまたはリモートの通知に応答することができ、呼び出されます。

application:didReceiveLocalNotification:
application:didReceiveRemoteNotification:

ただし、プライベートのAPIを使用する必要があるAppleのMessages.appにあるため、標準のネイティブiOS通知アラートバナーUIは表示されません。

最善の方法は、独自のアラートバナーをロールするか、既存のフレームワークを使用することです。

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

私はこの行動のレーダーをここに開きました: rdar://22313177


3
では、whatsappや他の有名なアプリはどのようにしてそれを行うのでしょうか?
マチャド

@tardoandreスクリーンショットをお持ちですか?私はそれが彼ら自身の見方で株式のiOSアラートを模倣することによると思います。
pkamb

2
toastAlertFromGithubこのサードパーティのライブラリの使用を提案する場合は、リンクを含める必要があります。
Ketan Parmar 2016

14

アプリが開いているときに通知を表示するには、手動で処理する必要があります。だから私が下でやっていることは、一度受け取った通知を処理することです。

以下をすべてAppDelegate.mに追加します

  1. 通知の呼び出しを処理する
  2. ビューを作成し、AppIcon、通知メッセージを追加して、アニメーションとして表示します
  3. タッチ認識機能を追加して、触れた場合は削除するか、アニメーションで5秒以内に削除します。

これが問題のない解決策かどうか教えてください。私にとってはうまくいきましたが、これが正しい方法であるかどうかはわかりません。

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


}];


}

3
これは、独自のアラートを作成するのに適した回答かもしれませんが、スクリーンショットに示すように、ストック iOSアラートを表示していません。
pkamb 2016年

こんにちは、優しい言葉をありがとう。はい、上記の画像に示されているのはiOS通知であり、コードによるものはカスタムであるため、外観について話している場合はそのようには見えません。ビューの外観を複製できます。WhatsAppには、背景ぼかしなどの見栄えの良いものがあると思います
Hafeez

1
誰かが反対票を投じた:(。理由を聞いて良かった!?。ありがとう。
Hafeez

2
私はこの答えは本当に質問に答えていない(それはかもしれませんが素敵)のコードとして、やった質問:示す株価アプリ内のバナートーストのiOSを。この回答が素晴らしいと思われるSOに関する他の質問があります。
pkamb

1
明確にしてくれたpkambに感謝します。「在庫」という言葉を逃した。
Hafeez

10

アプリがフォアグラウンドまたはオープンステージ、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])
}

通知のuserInfoにアクセスする必要がある場合は、コードを使用します。 notification.request.content.userInfo

このメソッドuserNotificationCenter(_:willPresent:withCompletionHandler:)は、属性をペイロードに追加する場合にのみ呼び出されますcontent-available:1。最終的なペイロードは次のようになります。

{
     "aps":{
          "alert":"Testing.. (7)",
          "badge":1,"sound":"default"
     },
     "content-available":1
}

1
userNotificationCenter(_:willPresent:withCompletionHandler:)アプリがフォアグラウンドで実行されているときに呼び出されます。したがって、「バックグラウンドフェッチ」に関連する「content-available」では問題になりません。
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);
}];

iOS 10でアプリがアクティブなときにプッシュ通知を表示できます。

  1. サーバーからのプッシュ通知はサイレントにする必要があります。

  2. サーバーからリモート通知を受信したら、ローカル通知を送信し、keyPathの値を設定します:shouldAlwaysAlertWhileAppIsForeground = True


迅速な2で-それはcontent.setValue("YES", forKeyPath: "shouldAlwaysAlertWhileAppIsForeground")、そうですか?(「はい」で、真ではありません)
Yoav R.

注意:これはここにiOSの12を参照の議論の下にアプリがクラッシュします: stackoverflow.com/questions/41373321/...
マットBearson

5

通知を自分で処理し、カスタムアラートを表示できます。Viber、Whatsapp、BisPhoneなどのアプリはこのアプローチを使用します。

サードパーティのカスタムアラートの一例はCRToastです。

アプリがフォアグラウンドにあるときにローカル通知をスケジュールすると、標準のiOSアラートが表示されないことがわかります。

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

ありがとうございます。ただし、標準のiOS通知アラートを使用して回答を探しています。
pkamb

1
:[OK]をしかし、私はあなたにも、このリンクを見て、それをしないことができると思いstackoverflow.com/questions/14872088/...
MoのFarhand

6
@matt私はトピックに関するこの質問を保持しようとしています:フォアグラウンドで株式のiOSアラートを表示します。他の多くの「最高のトースト警告フレームワーク」の質問。「いいえ、iOSアラートをフォアグラウンドで表示することはできません」という答えは完全に受け入れられます。これ、iOSの将来のバージョンで可能になるまでその答えを受け入れます。
pkamb

4

Swift 3バージョン

これは、アプリケーションがフォアグラウンドにあるときにアラートを表示します。

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

ApplicationDelegateの実装 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
}

念のため... iOS 10以降、バックグラウンドで行うように、フォアグラウンドでアラート/バナー/サウンドを表示できるようになったということですか?
ハニー

上記のコーディング部分をどこに置くことができますか?receiveRemoteNotificationにありましたか?
user1960169 2017

@Leslie GodwinはiOS 8.0でフォアグラウンドで通知を表示するように機能します
Dilip Tiwari '22

2

ローカル通知を表示するには、これが最適なオプションです。「BRYXBanner」をライトするために必要なコードが少ないhttps://cocoapods.org/pods/BRYXBanner

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)

このBRYXBannerフレームワークは、使用していないようです株式 iOSの通知バナーを。
pkamb

1

展開ターゲット> = iOS10の場合、以下のようなUNUserNotificationを使用します

func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void)
    {
        // Change this to your preferred presentation option
        completionHandler([.alert, .sound])
    }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.