ionic-team / capacitor

Build cross-platform Native Progressive Web Apps for iOS, Android, and the Web ⚑️
https://capacitorjs.com
MIT License
11.46k stars 977 forks source link

bug: capacitor v3 Push Notifications not working [UPDATED: working, suggested documentation changes] #4333

Closed santekotturi closed 3 years ago

santekotturi commented 3 years ago

Bug Report

Capacitor Version

πŸ’Š   Capacitor Doctor  πŸ’Š

Latest Dependencies:

  @capacitor/cli: 2.4.7
  @capacitor/core: 2.4.7
  @capacitor/android: 2.4.7
  @capacitor/ios: 2.4.7

Installed Dependencies:

  @capacitor/cli: 3.0.0-rc.0
  @capacitor/core: 3.0.0-rc.0
  @capacitor/android: 3.0.0-rc.0
  @capacitor/ios: 3.0.0-rc.0

[success] iOS looking great! πŸ‘Œ

Platform(s)

Current Behavior

Registering push notifications return tokens that don't work with Firebase Cloud Messaging

⚑️  [log] - [NOTIFICATIONS] TOKEN OBJECT:  {"value":"869BBC83FC800D83F3AE62DBE674D33C5FA067586D791F6292CA6C4EB836353F"}
⚑️  [log] - [NOTIFICATIONS] Push reg success, token:  869BBC83FC800D83F3AE62DBE674D33C5FA067586D791F6292CA6C4EB836353F

Expected Behavior

Describe what the behavior should be. Tokens used to be in format: eUh8TJmSCI0:APA91bHmp_2cZElJnKyRG9F-zZfGm6fa_Krv_MOy7z_2o2ZOo18VroSCxgAdUbWMSpwkMnkaTexViIHD-JygOflv_WvWisXsmbawbM_fNDenFuzDC....

Code Reproduction

  1. Call .register():
    PushNotifications.requestPermissions().then(         <==== USING THE NEW requestPermissions() instead of requestPermission()
          (result: {receive: PermissionState}) => {
            console.log('[NOTIFICATIONS] permission: ', result);
            if (result.receive === 'granted') {
              // Register with Apple / Google to receive push via APNS/FCM
              PushNotifications.register().then(
                () => {
                  console.log('[NOTIFICATIONS] register complete. Token will appear in success listener ');
                  resolve('success');
    ....
  2. Listen for the success event:
    PushNotifications.addListener(
      'registration',
      async (token: Token) => {
        console.log('[NOTIFICATIONS] Has current user: ', user.UID);
        console.log('[NOTIFICATIONS] TOKEN OBJECT: ', token);
        console.log('[NOTIFICATIONS] Push reg success, token: ', token.value);
        ....

Other Technical Details

using the v3 plugin:

import {
  PushNotifications,
  PushNotificationSchema,
  Token,
  ActionPerformed,
} from '@capacitor/push-notifications';

npm --version output: 6.14.11

node --version output: v12.16.1

pod --version output (iOS issues only): 1.10.1

Additional Context

Here's the cap sync output:

$ npx cap sync ios
[warn] Using the iOS project root for the public directory is deprecated.
       Please follow the Upgrade Guide to move public inside the iOS target directory:
       https://capacitorjs.com/docs/v3/updating/3-0#move-public-into-the-ios-target-directory
βœ” Copying web assets from www to ios/App/public in 1.35s
βœ” Creating capacitor.config.json in ios/App/App in 1.41ms
βœ” copy ios in 1.38s
βœ” Updating iOS plugins in 5.08ms
[info] Found 10 Capacitor plugins for ios:
       @capacitor-community/firebase-analytics@1.0.0-alpha.0
       @capacitor/app@0.3.6
       @capacitor/camera@0.4.3
       @capacitor/device@0.5.6
       @capacitor/geolocation@0.4.3
       @capacitor/haptics@0.3.6
       @capacitor/keyboard@0.5.6
       @capacitor/push-notifications@0.3.6
       @capacitor/share@0.5.3
       @capacitor/splash-screen@0.3.6
βœ” Updating iOS native dependencies with pod install in 10.49s
βœ” update ios in 10.59s
[info] Sync finished in 11.98s

AppDelegate.swift:

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

  func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
    NotificationCenter.default.post(name: .capacitorDidFailToRegisterForRemoteNotifications, object: error)
  }

#endif

Perhaps unrelated but the warning about the public folder not inside App/App seems misleading because in XCode I see: image

santekotturi commented 3 years ago

On the backend, here's the output from firebase admin messaging:

Sending message:  {"notification":{"title":"Dev2 sent a new support message:","body":"does it work now"},"token":"869BBC83FC800D83F3AE62DBE674D33C5FA067586D791F6292CA6C4EB836353F" }

The registration token is not a valid FCM registration token {"code":"messaging/invalid-argument"}

santekotturi commented 3 years ago

Ok, this seems to fix it:

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        Messaging.messaging().apnsToken = deviceToken
        InstanceID.instanceID().instanceID { (result, error) in
                  if let error = error {
                    NotificationCenter.default.post(name: .capacitorDidFailToRegisterForRemoteNotifications, object: error)
                  } else if let result = result {

                    NotificationCenter.default.post(name: .capacitorDidRegisterForRemoteNotifications, object: result.token)
                  }
              }
    }

    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
      NotificationCenter.default.post(name: .capacitorDidFailToRegisterForRemoteNotifications, object: error)
    }

I'm not expert in this level of the stack and I've just hacked this together from what was working with the new syntax.

I'd really appreciate it if someone could confirm that I can pass object: result.token instead of object: deviceToken to NotificationCenter.default.post(name: , object: ) without crashing things... πŸ™πŸΌ

jcesarmobile commented 3 years ago

@capacitor/push-notifications use APNS on iOS

if you want to use FCM we have a guide about how to do it, it has been updated for Capacitor 3

https://capacitorjs.com/docs/v3/guides/push-notifications-firebase#add-initialization-code

it includes how to pass the FCM token

ghost commented 3 years ago

It might be helpful to include a link to the above guide in the Capacitor 3 upgrade guide. I use firebase notifications in my iOS app and it caused issues when I followed along to the changes for notifications in AppDelegate.swift

ionitron-bot[bot] commented 1 year ago

Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Capacitor, please create a new issue and ensure the template is fully filled out.