Skip to content

fix(messaging): iOS - fix bug where tapping a notification when the app is either in the background or closed, would not trigger any listener#267

Closed
jaco-terbraak wants to merge 1 commit intocapawesome-team:mainfrom
jaco-terbraak:fix/tapping-notifications
Closed

fix(messaging): iOS - fix bug where tapping a notification when the app is either in the background or closed, would not trigger any listener#267
jaco-terbraak wants to merge 1 commit intocapawesome-team:mainfrom
jaco-terbraak:fix/tapping-notifications

Conversation

@jaco-terbraak
Copy link
Copy Markdown

One would expect the notificationActionPerformed listener to be called once a notification is tapped on iOS, while the app is in the background or closed. However this does not happen. This PR fixes that.

Tested on iOS 15.4.1.

Pull request checklist

Please check if your PR fulfills the following requirements:

  • [ x ] The changes have been tested successfully.
  • [ x ] A changeset has been created (npm run changeset).

…he background or closed did not trigger any function call
@alexookah
Copy link
Copy Markdown
Contributor

alexookah commented Nov 26, 2022

@jaco-terbraak Do you use the iOS setup with swizzling disabled or enabled?
My notifications are working great (with swizzling enabled default*) without your addition both closed and in background.

@jaco-terbraak
Copy link
Copy Markdown
Author

jaco-terbraak commented Nov 28, 2022

@jaco-terbraak Do you use the iOS setup with swizzling disabled or enabled? My notifications are working great (with swizzling enabled default*) without your addition both closed and in background.

I've tested with both FirebaseAppDelegateProxyEnabled enabled and disabled, and it makes no difference. Tapping a notification causes the app to open, but does not trigger a callback.

@robingenz
Copy link
Copy Markdown
Member

@jaco-terbraak Which plugin version do you use? I just tested this recently with the latest version and it worked. So I want to find out the real problem.

@jaco-terbraak
Copy link
Copy Markdown
Author

@jaco-terbraak Which plugin version do you use? I just tested this recently with the latest version and it worked. So I want to find out the real problem.

I'm using:

"@capacitor-firebase/messaging": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/@capacitor-firebase/messaging/-/messaging-1.2.0.tgz",
      "integrity": "sha512-n1chaK4Z3vTCxiu4mgVByfTlsTtpI496cX1tavjY0Nh4RZ4ZZqWlwbBSqBQhPLm/7qtIXJ+IZ5yNrA1QUlKWvg=="
    },

As there's multiple people saying it works for them, I'm assuming the problem is on my end. However I've now spent multiple days tracking down the issue, and I've run out of places to look. It doesn't help though that I don't have a ton of iOS experience. It would be useful to find out what the issue is, so we can document it for others facing the same problem.

@jaco-terbraak
Copy link
Copy Markdown
Author

This is what my AppDelegate.swift looks like:

import UIKit
import Capacitor
import Firebase

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

  var window: UIWindow?


  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.
    FirebaseApp.configure()
      
    UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { _, _ in }
          
    // We can call this without depending on the above result
    UIApplication.shared.registerForRemoteNotifications()
      
    return true
  }

  func applicationWillResignActive(_ application: UIApplication) {
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
  }

  func applicationDidEnterBackground(_ application: UIApplication) {
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
  }

  func applicationWillEnterForeground(_ application: UIApplication) {
    // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
  }

  func applicationDidBecomeActive(_ application: UIApplication) {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
  }

  func applicationWillTerminate(_ application: UIApplication) {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
  }

  func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
    // Called when the app  was launched with a url. Feel free to add additional processing here,
    // but if you want the App API to support tracking app url opens, make sure to keep this call
    return CAPBridge.handleOpenUrl(url, options)
  }

  func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
    // Called when the app was launched with an activity, including Universal Links.
    // Feel free to add additional processing here, but if you want the App API to support
    // tracking app url opens, make sure to keep this call
    return CAPBridge.handleContinueActivity(userActivity, restorationHandler)
  }

  override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesBegan(touches, with: event)

    let statusBarRect = UIApplication.shared.statusBarFrame
    guard let touchPoint = event?.allTouches?.first?.location(in: self.window) else { return }

    if statusBarRect.contains(touchPoint) {
      NotificationCenter.default.post(CAPBridge.statusBarTappedNotification)
    }
  }

  func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    NotificationCenter.default.post(name: .capacitorDidRegisterForRemoteNotifications, object: deviceToken)
  }

  func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
    #if arch(i386) || arch(x86_64)
        print("APNS Device Token retrieval error: It's because the device is simulator")
    #else
        print("APNS Device Token retrieval error:", error.localizedDescription)
    #endif
  
    NotificationCenter.default.post(name: .capacitorDidFailToRegisterForRemoteNotifications, object: error)
  }

  func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    NotificationCenter.default.post(name: Notification.Name.init("didReceiveRemoteNotification"), object: completionHandler, userInfo: userInfo)
  }
}

@robingenz
Copy link
Copy Markdown
Member

@jaco-terbraak Okay, this issue should be fixed in v1.2.0: a6a0720 (listener did not retain the values).
Could you please double check if you really using v1.2.0?
Please run npm ci and try it again.

If the problem persists, could you please provide a minimal, reproducible example so i can debug the issue?

@jaco-terbraak
Copy link
Copy Markdown
Author

jaco-terbraak commented Nov 28, 2022

@alexookah and @robingenz, thanks for bearing with me.

It appears I still had @capacitor/push-notifications installed, which installs the CapacitorPushNotifications pod, which apparently interferes with this mechanism. After removing this pod, everything works again. Apologies for looking in the wrong place.

Would it be worth mentioning this in the docs? Imho it's an easy mistake to make.

@robingenz
Copy link
Copy Markdown
Member

@jaco-terbraak Glad it works now! In that case I'll close this PR now.

I will try this myself and install the Capacitor Push Notification plugin in addition to this plugin to check what the real problem is.

@robingenz robingenz closed this Nov 28, 2022
@dahLucky
Copy link
Copy Markdown

dahLucky commented Dec 3, 2022

@alexookah and @robingenz, thanks for bearing with me.

It appears I still had @capacitor/push-notifications installed, which installs the CapacitorPushNotifications pod, which apparently interferes with this mechanism. After removing this pod, everything works again. Apologies for looking in the wrong place.

Would it be worth mentioning this in the docs? Imho it's an easy mistake to make.

I agree it would make sense to mention this issue in the docs.

We ran into the same issue after migrating from @capacitor/push-notifications. It took us quite some time to locate this iOS-specific issue as we also started looking at the wrong place

@robingenz
Copy link
Copy Markdown
Member

Thanks, I just added a note to the messaging docs: 80d428d

@jaco-terbraak jaco-terbraak deleted the fix/tapping-notifications branch December 3, 2022 13:26
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Dec 4, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants