iOS 푸시 알림 : 앱이 백그라운드에있을 때 사용자가 알림을 탭했는지 감지하는 방법은 무엇입니까?


116

이 주제와 관련된 많은 스택 오버플로 스레드가 있지만 여전히 좋은 해결책을 찾지 못했습니다.

앱이 배경에 없으면, 내가 확인하실 수 있습니다 launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]application:didFinishLaunchingWithOptions:이 통지에서 연 것 있는지 확인하기 위해 전화.

앱이 백그라운드에있는 경우 모든 게시물 application:didReceiveRemoteNotification:에서 애플리케이션 상태 를 사용 하고 확인하도록 제안합니다 . 그러나 내가 실험 한 것처럼 (또한이 API의 이름에서 알 수 있듯이)이 메서드는 탭하는 대신 알림을받을 때 호출됩니다.

따라서 문제는 앱이 시작된 후 백그라운드로 설정되고 알림이 수신 된 경우 application:didReceiveNotification( application:didFinishLaunchWithOptions:이 시점에서 트리거되지 않음) 사용자가 알림을 탭하거나 탭하여 앱을 다시 시작했는지 어떻게 알 수 있는가 앱 아이콘? 사용자가 알림을 탭한 경우 해당 알림에 언급 된 페이지가 열릴 것으로 예상됩니다. 그렇지 않으면 안됩니다.

handleActionWithIdentifier사용자 지정 작업 알림에 사용할 수 있지만 사용자가 알림 본문을 탭할 때가 아니라 사용자 지정 작업 버튼을 탭할 때만 트리거됩니다.

감사.

편집하다:

아래 답변 하나를 읽은 후 이런 식으로 내 질문을 명확히 할 수 있다고 생각했습니다.

이 두 가지 시나리오를 어떻게 차별화 할 수 있습니까?

(A) 1. 앱이 백그라운드로 이동합니다. 2. 통지 접수 3. 사용자가 알림을 탭합니다. 4. 앱이 포 그라운드로 들어감

(B) 1. 앱이 백그라운드로 이동합니다. 2. 통지 접수 3. 사용자가 알림을 무시하고 나중에 앱 아이콘을 탭합니다. 4. 앱이 포 그라운드로 들어감

이후로는 application:didReceiveRemoteNotification:2 단계에서 두 경우 모두에서 실행됩니다.

또는 application:didReceiveRemoteNotification:(A)에 대해서만 3 단계에서 트리거 되어야 하지만 어떻게 든 내 앱을 잘못 구성하여 2 단계에서 볼 수 있습니까?


페이로드에 사용자 지정 사전 값을 사용하고 그에 따라 조치를 취하십시오. 아주 간단합니다.
soulshined aug

@soulshined 페이로드의 사전은 사용자가 알림을 탭했는지 여부를 나타낼 수 있습니다. 예를 들어 친구 A가 기사 B를 게시 한 경우 페이로드에 {user : A, article : B}라고 말하면 앱이 백그라운드에 있고 didReceiveRemoteNotification이 표시됩니다. 앱이 다시 시작될 때 기사를 표시해야하는지 여부를 어떻게 알 수 있습니까?
Bao Lei

2
@soulshined 나는 문서를 읽었고 didReceiveRemoteNotification 이하는 일에 대해 스스로 교육했습니다. 제 질문을 실제로 읽었습니까? Apple의 공식 문서 didReceiveRemoteNotification에 따라 "실행중인 앱이 원격 알림을 받았음을 대리인에게 알립니다". 사용자가 알림을 탭했는지 알 수있는 좋은 방법이 무엇인지 묻고 있습니다. 당신이 언급 한 SO 링크는 앱이 새로 시작될 때에 대한 것입니다. 저는 앱이 백그라운드에있을 때 시나리오를 묻습니다.
Bao Lei


1
@soulshined OK 아마도 나는 그것을 충분히 명확하게 말하지 않았을 것입니다. 앱이 백그라운드가 아닌 완전히 종료되면 yes didFinishLaunching이 호출됩니다. 그러나 앱을 시작한 다음 앱을 백그라운드로 실행하면 이제 알림이 수신되고 사용자가 알림을 탭하면 didFinishLaunching이 다시 호출되지 않습니다. 대신 applicationWillEnterForeground 및 applicationDidBecomeActive가 호출됩니다. 사용자가 알림이나 앱 아이콘을 탭했기 때문에 앱이 포 그라운드로 진입하고 있음을 어떻게 알 수 있습니까?
Bao Lei

답변:


102

OK 마침내 알아 냈습니다.

대상 설정에서 ➝ 기능 탭 ➝ 백그라운드 모드에서 "원격 알림"을 ​​선택 application:didReceiveRemoteNotification:하면 알림이 도착하는 즉시 (앱이 백그라운드에있는 한) 트리거되며,이 경우 알 수있는 방법이 없습니다. 사용자는 알림을 탭합니다.

해당 상자를 선택 취소 application:didReceiveRemoteNotification:하면 알림을 탭할 때만 트리거됩니다.

이 체크 박스를 선택하면 앱 델리게이트 메서드 중 하나가 작동하는 방식이 변경된다는 것은 조금 이상합니다. 이 확인란을 선택하면 Apple은 알림 수신 및 알림 탭에 대해 두 가지 다른 위임 방법을 사용합니다. 대부분의 개발자는 알림이 탭되었는지 여부를 항상 알고 싶어합니다.

이 문제가 발생하는 다른 사람에게 도움이되기를 바랍니다. Apple은 또한 여기에 명확하게 문서화하지 않았 으므로 알아내는 데 시간이 걸렸습니다.

여기에 이미지 설명 입력


6
백그라운드 모드를 완전히 "OFF"로 설정했지만 백그라운드 모드에서 앱과 함께 알림이 도착하면 여전히 알림을받습니다.
Gottfried

5
큰! 이것은 나를 도왔다. 그러나 원격 알림을 꺼야하는 것은 유감입니다. 푸시 알림이 도착하면 데이터를 미리 가져 와서 사용자 탭을 감지하고 싶습니다. 이것을 달성하는 방법을 찾을 수 없습니다.
Peter Fennema 2015

1
배경 모드를 "ON"모드로 설정하고 원격 알림을 활성화합니다. 여전히 알림 이벤트를 감지 할 수 없습니다.
카림 sayyad

1
나는 같은 문제의 배경 모드를 "ON"으로 설정하고 원격 통지를 사용 가능하지만, 여전히 알림 백그라운드 모드에서 응용 프로그램에 도착할 때 알림을받을되지 않은
Swapnil Dhotre을

@Bao-이 옵션은 기본적으로 백그라운드에서 알림 관련 콘텐츠를 다운로드하는 데 사용되므로 Appstore에서 거부 될 것이라고 생각합니다. 따라서 콘텐츠를 다운로드하지 않는 경우 Apple은 앱을 거부 할 수 있습니다. developer.apple.com/library/ios/documentation/iPhone/Conceptual/...는
NIKS

69

나는 당신과 똑같은 것을 찾고 있었고 실제로 원격 알림이 필요하지 않은 솔루션을 찾았습니다.

사용자가 탭했는지, 앱이 백그라운드에 있는지 또는 활성화되었는지 확인하려면 다음에서 애플리케이션 상태를 확인하면됩니다.

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

    }

자세한 정보 확인 :

UIKit 프레임 워크 참조> UIApplication 클래스 참조> UIApplicationState


10
앱이 화면에있는 동안 사용자가 알림 센터 (위에서 스 와이프) 또는 제어 센터 (아래에서 스 와이프)를 사용하여 앱이 UIApplicationStateInactive가되는 것은 어떻습니까? 분명히 APNS가 비활성 상태에서 수신되었는지 또는 사용자가 실제로 탭했는지 알 수있는 방법이 없습니다.
Kostia Kim

1
@KostiaKim 맞아요,하지만 그건 슈퍼 에지 케이스입니다 ... 그 외에는이 답변은 포 그라운드에서 앱을 구분하는 측면에서 가장 유효합니다 ... 사용자 탭핑 ... 백그라운드에서 앱
Honey

고마워요, 이런 종류의 모든 것을 이해합니다. 앱이 백그라운드에있을 때 델리게이트 메서드가 호출 되려면 푸시 알림에 content-available키 가 포함 되어야하지만 알림은 공식 문서에 명시된대로 조용해야합니다 (즉, 사운드 또는 배지를 포함하지 않음). .
Nickkk

1
@KostiaKim 실제로 제어 센터가 열려 또는 사용자가 실제로 true로 설정되는 부울 추가하여 알림을 탭하면 여부를 모르고의 문제를 해결할 수 있었다 func applicationDidEnterBackground(_ application: UIApplication)과 거짓 func applicationDidBecomeActive(_ application: UIApplication)이 허용 나를 앱에서 보여을 앱이 제어 센터 또는 알림 목록에 인해 비활성 통지
DatForis

3
왜 Apple이 다른 이벤트를 표시하지 않았는지 또는 단순히 사용자가 실제로 알림과 상호 작용했음을 나타내는 플래그를 메타 데이터에 추가하지 않은 이유가 내 마음을 깜짝 놀라게합니다. 사용자가 애플리케이션 상태에 대한 주변 정보를 기반으로 조치를 취했는지 여부를 '추론'해야하는 것은 애플리케이션 동작에 대한 사용자의 기대에 영향을 미치는 주요 정보에 대해 매우 비합리적입니다. 할 수있는 유일한 일은 해당 정보로 앱을 여는 사용자 지정 작업을 만드는 것입니까?
Allan Nienhuis 2017

20

iOS / XCode 에 따르면 : 알림 또는 스프링 보드 앱 아이콘을 클릭하여 앱이 시작되었는지 확인하는 방법은 무엇입니까? 다음과 같이 didReceiveLocalNotification에서 애플리케이션 상태를 확인해야합니다.

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

나에게 완전히 이해가되지는 않지만 작동하는 것 같습니다.


1
이 시나리오에서는 작동하지 않습니다. 나는 전에 그것을 시도했다. 해당 확인란을 선택하면 (자세한 내용은 내 수락 된 답변 참조) 알림이 도착하면 사용자가 알림을 탭하지 않았더라도 "// 사용자가 알림을 탭했습니다"라는 주석이있는 줄이 입력됩니다 (알림이 방금 도착했습니다 ).
Bao Lei

3
동의하지 않습니다. 내 백그라운드 기능에서 "원격 알림"을 ​​확인했으며 내 대답에 설명 된 방식으로 작동합니다. "백그라운드 가져 오기"도 확인했습니다. 그게 변화의 원인일까요?
Werner Kratochwil

내 답변을 +1 해 주 시겠어요? ;-) 여전히 stackoverflow에 더 많이 참여하려면 몇 가지 투표가 필요합니다. 고마워요
베르너 크라 토치 윌

Yupe, 이것이 해결책입니다. tnx.
아프신

사용자가 다른 화면에있는 동안 알림이 전송되면 (예 : 상태 표시 줄을 아래로 내린 다음 앱에서 알림을받는 경우) 오탐이됩니다.
Kevin Cooper

16

누군가가 신속한 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
    }

신속한 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
}

어떤 트리거에서이 코드를 추가해야합니까? didReceiveRemoteNotification 또는 didFinishLaunchingWithOptions?
Dashrath

2
didReceiveRemoteNotification에
하미드 샤사 바리

@Hamid sh ,,,, 모든 상태, 즉 앱이 포 그라운드, 백그라운드, 닫기 (종료)에있을 때 푸시 알림을 받았습니다 ..! 하지만 내 문제는 앱이 백그라운드 상태이고 종료 (종료) 상태 일 때 배지 수를 늘리는 방법입니다. ???? 어떻게하는지 자세히 알려주세요 ....? 내 앱 배지 수는 앱이 포 그라운드 상태 일 때만 증가합니다 .....? 가능하면 간략하게 말씀 해주세요 .......!
키란 jadhav

8

"백그라운드 모드"> "원격 알림"이 선택되어있는 경우 == 예, 알림 이벤트를 탭하면 다음 위치에 도착합니다.

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

그것은 나를 도왔다. 즐기세요 :)


Apple이 이것을 추가 한 것을 보았지만 이런 방식으로 알림의 사용자 지정 페이로드를 얻는 방법을 알아낼 수 없었습니다.
sudo

이 함수는 앱이 백그라운드 상태에 있고 활성화 될 때 호출되며 앱이 종료 된 상태에서 시작될 때도 호출됩니다
Nikhil Muskur

@NikhilMuskur "원격 알림"이 활성화 된 경우에만 그렇습니까?
Zorayr

@Zorayr yup 맞습니다
Nikhil Muskur

8

나도이 문제에 부딪 혔지만 새로운 UserNotifications프레임 워크 가있는 iOS 11에서 .

여기에서는 다음과 같습니다.

  • 새로운 출시 : application:didFinishLaunchingWithOptions:
  • 종료 상태에서 수신 : application(_:didReceiveRemoteNotification:fetchCompletionHandler:)
  • 포 그라운드에서 수신 : userNotificationCenter(_:willPresent:withCompletionHandler:)
  • 백그라운드에서 수신 : userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:

이것이 iOS 11 +
OhadM

이것은 너무 복잡합니다 🤦‍♂️
Zorayr

4

제 경우에는 백그라운드 모드 OFF가 아무런 차이가 없었습니다. 그러나 앱이 일시 중지되고 사용자가 알림을 탭했을 때이 콜백 메서드에서 케이스를 처리 할 수 ​​있습니다.

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

}

이것은 Apple이 말하는 공식적인 방법입니다. Apple의 문서에 따르면 사용자가 푸시 알림 UI와 상호 작용할 때마다 호출됩니다. 앱이 백그라운드에 없으면 백그라운드 모드에서 앱을 시작하고이 메서드를 호출합니다.
라이언

3

iOS 10 이상에서는이를 AppDelegate에 넣으면 알림이 탭되었음을 알 수 있습니다 (앱이 닫히거나 열려 있어도 작동).

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

1
이것은 iOS 10 이상에 대한 정답입니다. 여기에 다른 스레드에 대한 전체 설명이 제공됩니다 : stackoverflow.com/a/41783666/1761357 .
dead_can_dance

2

PushNotificationManager클래스 내에서 PushNotification을 수신 한 핸들에 대한 두 가지 Func가 있습니다 .

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([])

}

두 번째 알림을 탭했을 때 :

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

또한 원격 알림의 ON 및 OFF 상태 (백그라운드 모드에서)로 테스트했습니다.


1

SWIFT 5.1

UIApplication.State 내 앱에서 지문 (모달이 표시됨)을 읽으면 알림이 상단 표시 줄에도 표시되고 사용자가 클릭해야하기 때문에 작동하지 않았습니다.

나는 만들었습니다

public static var isNotificationFromApp: Bool = false

에서 시작 하고 알림 에서 AppDelegate설정하고 / 그냥 확인합니다 :)trueviewControllerstoryboardviewController

유용 할 수 있기를 바랍니다.


-7

application:didReceiveRemoteNotification:fetchCompletionHandler:앱이 백그라운드에있을 때 앱 대리자의 메서드 를 호출하도록 푸시 알림의 페이로드를 구성 할 수 있습니다 . 사용자가 다음에 애플리케이션을 시작할 때 작업을 수행 할 수 있도록 여기에서 일부 플래그를 설정할 수 있습니다.

Apple의 문서에서이 방법을 사용하여 푸시 알림과 관련된 새 콘텐츠를 다운로드해야합니다. 또한이 기능이 작동하려면 백그라운드 모드에서 원격 알림을 활성화해야하며 푸시 알림 페이로드는 content-available값이 1로 설정된 키를 포함해야합니다 . 자세한 내용은 여기 에서 애플 문서의 푸시 알림을 사용하여 다운로드 시작 섹션을 참조 하십시오 .

또 다른 방법은 푸시 알림 페이로드에 배지 개수를 포함하는 것입니다. 따라서 다음에 응용 프로그램을 시작할 때 응용 프로그램 배지 수를 확인할 수 있습니다. 0보다 크면 작업을 수행하고 서버에서 배지 카운트를 0 / 지 웁니다.

이것이 도움이되기를 바랍니다.


@bhusan 내 질문에 대한 자세한 내용을 읽었습니까? 알림이 방금 도착했을 때 (사용자가 탭하기 전에) didReceiveRemoteNotification이 호출되는 것을 봅니다. 사용자가 탭했는지 확인하고 싶었습니다.
Bao Lei

OP의 질문에 대답하지 않았습니다. 그는 단지 알림이 있었다는 것을 알고 싶어하지 않습니다. 그는 사용자가 원격 알림을 탭하여 앱을 열 었는지 알고 싶어합니다.
조 C
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.