web-dev-qa-db-ja.com

iOSプッシュ通知:アプリがバックグラウンドにあるときにユーザーが通知をタップしたかどうかを検出する方法

このトピックに関して多くのstackoverflowスレッドがありますが、まだ良い解決策は見つかりませんでした。

アプリがバックグラウンドにない場合、launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]呼び出しでapplication:didFinishLaunchingWithOptions:を確認して、通知から開かれているかどうかを確認できます。

アプリがバックグラウンドにある場合、すべての投稿でapplication:didReceiveRemoteNotification:を使用してアプリケーションの状態を確認することをお勧めします。しかし、私が実験したように(そしてこのAPIの名前が示唆するように)、通知が受信されると、タップされる代わりにこのメソッドが呼び出されます。

問題は、アプリを起動してバックグラウンドにし、application:didReceiveNotificationから通知を受信したことがわかっている場合(application:didFinishLaunchWithOptions:はこの時点ではトリガーしません)、ユーザーが通知をタップすることでアプリを再開したか、または単にアプリのアイコンをタップしますか?ユーザーが通知をタップした場合、その通知に記載されているページを開くことが期待されるためです。それ以外の場合はできません。

カスタムアクション通知にhandleActionWithIdentifierを使用できますが、これは、ユーザーが通知の本文をタップしたときではなく、カスタムアクションボタンがタップされたときにのみトリガーされます。

ありがとう。

編集:

以下の回答を1つ読んだ後、この方法で質問を明確にできると思いました。

これら2つのシナリオをどのように区別できますか?

(A)1.アプリがバックグラウンドになります。 2.受け取った通知; 3.ユーザーが通知をタップします。 4.アプリがフォアグラウンドに入る

(B)1.アプリがバックグラウンドになります。 2.受け取った通知; 3.ユーザーは通知を無視し、後でアプリアイコンをタップします。 4.アプリがフォアグラウンドに入る

application:didReceiveRemoteNotification:は両方のケースでステップ2でトリガーされるためです。

または、(A)の場合のみ、ステップ3でapplication:didReceiveRemoteNotification:をトリガーする必要がありますが、何らかの方法でアプリを誤って構成したため、ステップ2で表示されますか?

100
Bao Lei

わかった。

ターゲット設定➝[機能]タブ➝バックグラウンドモードで、[リモート通知]をオンにすると、通知が到着するとすぐに(アプリがバックグラウンドにある限り)application:didReceiveRemoteNotification:がトリガーされます。その場合、通知する方法はありませんユーザーが通知をタップするかどうか。

このボックスのチェックを外すと、通知をタップしたときにのみapplication:didReceiveRemoteNotification:がトリガーされます。

このボックスをチェックすると、アプリのデリゲートメソッドの1つの動作が変わることは少し奇妙です。そのボックスがチェックされている場合、Appleは通知の受信と通知のタップに2つの異なるデリゲートメソッドを使用する方が良いでしょう。ほとんどの開発者は、通知がタップされたかどうかを常に知りたがっていると思います。

うまくいけば、これがこの問題に遭遇した他の人にとって役立つことを願っています。 Appleもそれを明確に文書化していませんでした ここ なので、理解するのに時間がかかりました。

enter image description here

88
Bao Lei

私はあなたと同じものを探していましたが、実際にはリモート通知をオフにする必要のないソリューションを見つけました。

ユーザーがタップしたか、アプリがバックグラウンドにあるかアクティブになっているかを確認するには、アプリケーションの状態を確認するだけです

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

    if(application.applicationState == UIApplicationStateActive) {

        //app is currently active, can update badges count here

    }else if(application.applicationState == UIApplicationStateBackground){

        //app is in background, if content-available key of your notification is set to 1, poll to your backend to retrieve data and update your interface here

    }else if(application.applicationState == UIApplicationStateInactive){

        //app is transitioning from background to foreground (user taps notification), do what you need when user taps here

    }

詳細情報の確認:

IKit Framework Reference> UIApplication Class Reference> UIApplicationState

62
Dennism

iOS/XCode:通知またはスプリングボードアプリアイコンをクリックしてアプリが起動されたことを確認する方法 didReceiveLocalNotificationで次のようにアプリケーションの状態を確認する必要があります。

if ([UIApplication sharedApplication].applicationState == UIApplicationStateInactive)
{
    // user has tapped notification
}
else
{
    // user opened app from app icon
}

私にはまったく意味がありませんが、うまくいくようです。

19

誰かがSwift 3.0でそれを望んでいる場合

switch application.applicationState {
    case .active:
        //app is currently active, can update badges count here
        break
    case .inactive:
        //app is transitioning from background to foreground (user taps notification), do what you need when user taps here
        break
    case .background:
        //app is in background, if content-available key of your notification is set to 1, poll to your backend to retrieve data and update your interface here
        break
    default:
        break
    }

Swift 4の場合

switch UIApplication.shared.applicationState {
case .active:
    //app is currently active, can update badges count here
    break
case .inactive:
    //app is transitioning from background to foreground (user taps notification), do what you need when user taps here
    break
case .background:
    //app is in background, if content-available key of your notification is set to 1, poll to your backend to retrieve data and update your interface here
    break
default:
    break
}
14

[バックグラウンドモード]> [リモート通知]がオンになっている場合== YESの場合、通知イベントのタップは次の場所に到着します。

-(void)userNotificationCenter:(UNUserNotificationCenter *)center **didReceiveNotificationResponse**:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler.

助けてくれました。お楽しみください :)

5
Aleks Osipov

私もこの問題に遭遇しましたが、iOS 11では新しいUserNotifications Frameworkを使用していました。

私にとっては、これは次のようなものです。

  • 新規発売:application:didFinishLaunchingWithOptions:
  • フォアグラウンドで受信:application:didReceiveRemoteNotification:fetchCompletionHandler:
  • バックグラウンドで受信:userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:
4
pre

私の場合、バックグラウンドモードをオフにしても何の違いもありませんでした。ただし、アプリが中断され、ユーザーが通知をタップした場合、このコールバックメソッドでケースを処理できます。

func userNotificationCenter(_ center: UNUserNotificationCenter,
                            didReceive response: UNNotificationResponse,
                            withCompletionHandler completionHandler: @escaping () -> Void) {

}
2
DoruChidean

IOS 10以降では、これがAppDelegateに配置され、通知がタップされたことを知ることができます(アプリが閉じていても開いていても動作します)

func userNotificationCenter(_ center: UNUserNotificationCenter,
                                didReceive response: UNNotificationResponse,
                                withCompletionHandler completionHandler: @escaping () -> Void) {
print("notification tapped here")
}
1
Yatin Arora

内部で受信したPushNotificationを処理する2つのFuncsがあります。

class PushNotificationManager: NSObject, MessagingDelegate, UNUserNotificationCenterDelegate{

}

通知が到着するとすぐに最初のトリガーをテストしたので

@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {

    completionHandler(UNNotificationPresentationOptions.alert)

    //OnReceive Notification
    let userInfo = notification.request.content.userInfo
    for key in userInfo.keys {
         Constants.setPrint("\(key): \(userInfo[key])")
    }

    completionHandler([])

}

そして、通知をタップしたときの2番目:

@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {

    //OnTap Notification
    let userInfo = response.notification.request.content.userInfo
    for key in userInfo.keys {
        Constants.setPrint("\(key): \(userInfo[key])")
    }

    completionHandler()
}

また、両方のリモート通知(バックグラウンドモード)のオン/オフ状態でテストしました。

0
Saeid