aws-amplify / amplify-js

A declarative JavaScript library for application development using cloud services.
https://docs.amplify.aws/lib/q/platform/js
Apache License 2.0
9.44k stars 2.13k forks source link

React Native v6 push notification troubles with iOS - getLaunchNotification not called #13000

Open stefoid opened 9 months ago

stefoid commented 9 months ago

Before opening, please confirm:

JavaScript Framework

React Native

Amplify APIs

Push Notifications

Amplify Version

v6

Amplify Categories

notifications

Backend

None

Environment information

``` # Put output below this line System: OS: macOS 14.2.1 CPU: (6) x64 Intel(R) Core(TM) i5-8500B CPU @ 3.00GHz Memory: 70.38 MB / 16.00 GB Shell: 3.2.57 - /bin/bash Binaries: Node: 18.0.0 - ~/.nvm/versions/node/v18.0.0/bin/node Yarn: 1.22.11 - /usr/local/bin/yarn npm: 8.6.0 - ~/.nvm/versions/node/v18.0.0/bin/npm Watchman: 2023.02.13.00 - /usr/local/bin/watchman Browsers: Chrome: 121.0.6167.160 Safari: 17.2.1 npmPackages: @aws-amplify/react-native: ^1.0.16 => 1.0.16 @aws-amplify/rtn-push-notification: ^1.2.16 => 1.2.16 @babel/core: ^7.20.12 => 7.22.1 @babel/runtime: ^7.20.13 => 7.22.3 @bam.tech/react-native-image-resizer: ^3.0.5 => 3.0.7 @intercom/intercom-react-native: ^5.1.0 => 5.3.1 @openspacelabs/react-native-zoomable-view: 2.1.1 => 2.1.1 @react-native-async-storage/async-storage: ^1.21.0 => 1.21.0 (1.18.1) @react-native-community/art: ^1.2.0 => 1.2.0 @react-native-community/cli: ^10.0.0 => 10.2.2 (10.2.0) @react-native-community/cli-platform-android: ^10.0.0 => 10.2.0 @react-native-community/datetimepicker: ^3.4.3 => 3.5.2 @react-native-community/eslint-config: ^3.2.0 => 3.2.0 @react-native-community/masked-view: ^0.1.11 => 0.1.11 @react-native-community/netinfo: ^9.0.0 => 9.3.10 @react-native-community/slider: ^3.0.3 => 3.0.3 @react-native-firebase/analytics: ^17.5.0 => 17.5.0 @react-native-firebase/app: ^17.3.2 => 17.5.0 @react-native-firebase/crashlytics: ^17.3.2 => 17.5.0 @react-native-firebase/perf: ^17.3.2 => 17.5.0 @react-native-google-signin/google-signin: ^7.2.2 => 7.2.2 @react-native-picker/picker: ^1.16.8 => 1.16.8 @react-navigation/material-bottom-tabs: ^6.2.12 => 6.2.15 @react-navigation/material-top-tabs: ^6.6.0 => 6.6.2 @react-navigation/native: ^6.0.8 => 6.1.6 @react-navigation/stack: ^6.2.0 => 6.3.16 @sayem314/react-native-keep-awake: ^1.1.0 => 1.1.0 @segment/analytics-react-native: ^2.12.0 => 2.15.0 @segment/sovran-react-native: ^0.4.4 => 0.4.5 (1.0.4) @shopify/flash-list: ^1.5.0 => 1.6.3 @tsconfig/react-native: ^2.0.2 => 2.0.3 @types/jest: ^29.2.1 => 29.5.2 @types/react: ^18.0.24 => 18.2.8 @types/react-test-renderer: ^18.0.0 => 18.0.0 HelloWorld: 0.0.1 SignatureCaptureExample: 0.0.1 aws-amplify: ^6.0.16 => 6.0.16 aws-amplify/adapter-core: undefined () aws-amplify/analytics: undefined () aws-amplify/analytics/kinesis: undefined () aws-amplify/analytics/kinesis-firehose: undefined () aws-amplify/analytics/personalize: undefined () aws-amplify/analytics/pinpoint: undefined () aws-amplify/api: undefined () aws-amplify/api/server: undefined () aws-amplify/auth: undefined () aws-amplify/auth/cognito: undefined () aws-amplify/auth/cognito/server: undefined () aws-amplify/auth/enable-oauth-listener: undefined () aws-amplify/auth/server: undefined () aws-amplify/datastore: undefined () aws-amplify/in-app-messaging: undefined () aws-amplify/in-app-messaging/pinpoint: undefined () aws-amplify/push-notifications: undefined () aws-amplify/push-notifications/pinpoint: undefined () aws-amplify/storage: undefined () aws-amplify/storage/s3: undefined () aws-amplify/storage/s3/server: undefined () aws-amplify/storage/server: undefined () aws-amplify/utils: undefined () babel-jest: ^29.2.1 => 29.5.0 babel-plugin-transform-remove-console: ^6.9.4 => 6.9.4 bson: 4.4.0 => 4.4.0 (4.7.2) cobrowse-sdk-react-native: ^2.11.2-unredaction.0 => 2.16.0 deprecated-react-native-prop-types: ^4.0.0 => 4.1.0 (2.3.0, 3.0.1) eslint: ^8.19.0 => 8.42.0 eslint-plugin-react-hooks: ^4.6.0 => 4.6.0 example: 0.0.1 i18n-js: ^3.8.0 => 3.9.2 jest: ^29.2.1 => 29.5.0 libphonenumber-js: ^1.10.19 => 1.10.33 libphonenumber-js/build: undefined () libphonenumber-js/core: undefined () libphonenumber-js/max: undefined () libphonenumber-js/max/metadata: undefined () libphonenumber-js/min: undefined () libphonenumber-js/min/metadata: undefined () libphonenumber-js/mobile: undefined () libphonenumber-js/mobile/examples: undefined () libphonenumber-js/mobile/metadata: undefined () linkify-html: ^4.1.1 => 4.1.2 linkifyjs: ^4.1.1 => 4.1.2 lodash: ^4.17.15 => 4.17.21 metro-react-native-babel-preset: 0.73.8 => 0.73.8 (0.73.9) moment: ^2.24.0 => 2.29.4 moment-timezone: ^0.5.40 => 0.5.43 mustache: ^3.0.1 => 3.2.1 patch-package: ^6.5.1 => 6.5.1 prettier: ^2.4.1 => 2.8.8 prop-types: ^15.6.0 => 15.8.1 react: 18.2.0 => 18.2.0 react-content-loader: ^6.2.0 => 6.2.1 react-content-loader/native: undefined () react-native: 0.71.4 => 0.71.4 react-native-actions-sheet: ^0.8.21 => 0.8.29 react-native-animated-dots-carousel: ^1.0.2 => 1.0.2 react-native-background-fetch: 4.1.8 => 4.1.8 react-native-btr: ^2.2.0 => 2.2.0 react-native-camera: ^3.0.0 => 3.44.3 react-native-compressor: ^1.8.15 => 1.8.16 react-native-config: ^1.5.1 => 1.5.1 react-native-device-info: ^10.8.0 => 10.11.0 (0.9.9, 10.3.0) react-native-document-picker: ^8.1.3 => 8.2.1 react-native-drop-shadow: ^0.0.6 => 0.0.6 react-native-exit-app: ^1.1.0 => 1.1.0 react-native-fast-image: ^8.5.8 => 8.6.3 react-native-file-viewer: ^2.0.0 => 2.1.5 react-native-floating-action: ^1.22.0 => 1.22.0 react-native-fs: ^2.18.0 => 2.20.0 react-native-geocoder-reborn: ^0.9.0 => 0.9.0 react-native-geolocation-service: 5.0.0 => 5.0.0 react-native-gesture-handler: ^2.9.0 => 2.10.2 react-native-get-random-values: ^1.10.0 => 1.10.0 react-native-google-places-autocomplete: ^1.8.0 => 1.9.0 react-native-gradle-plugin: ^0.71.15 => 0.71.18 react-native-hyperlink: 0.0.22 => 0.0.22 react-native-image-crop-picker: ^0.39.0 => 0.39.0 react-native-inappbrowser-reborn: ^3.7.0 => 3.7.0 react-native-iphone-x-helper: ^1.3.1 => 1.3.1 react-native-keyboard-accessory: ^0.1.16 => 0.1.16 react-native-keyboard-aware-scroll-view: ^0.9.5 => 0.9.5 react-native-localize: ^2.2.3 => 2.2.6 react-native-map-link: ^2.11.2 => 2.11.3 react-native-maps: 1.7.1 => 1.7.1 react-native-modal: 13.0.1 => 13.0.1 react-native-orientation-locker: ^1.5.0 => 1.5.0 react-native-pager-view: ^6.1.4 => 6.2.0 react-native-paper: ^5.0.1 => 5.8.0 react-native-permissions: ^3.10.0 => 3.10.1 react-native-rate: ^1.2.12 => 1.2.12 react-native-responsive-fontsize: ^0.5.1 => 0.5.1 react-native-safe-area-context: ^4.5.0 => 4.5.3 react-native-screens: 3.14.0 => 3.14.0 react-native-section-list-get-item-layout: ^2.2.3 => 2.2.3 react-native-share: ^10.0.1 => 10.0.1 react-native-signature-capture: ^0.4.9 => 0.4.12 react-native-snap-carousel: 4.0.0-beta.6 => 4.0.0-beta.6 react-native-svg: ^13.7.0 => 13.9.0 react-native-tab-view: ^3.5.0 => 3.5.1 react-native-tracking-transparency: ^0.1.2 => 0.1.2 react-native-vector-icons: ^9.2.0 => 9.2.0 react-native-video: ^5.2.1 => 5.2.1 react-native-virtualized-view: ^1.0.0 => 1.0.0 react-native-vision-camera: ^3.6.4 => 3.6.4 react-native-webview: 11.23.1 => 11.23.1 react-native-xml2js: ^1.0.3 => 1.0.3 react-number-format: ^4.9.3 => 4.9.4 react-redux: 8.0.5 => 8.0.5 react-test-renderer: 18.2.0 => 18.2.0 realm: ^12.5.0 => 12.6.0 redux: 4.2.1 => 4.2.1 redux-thunk: 2.4.2 => 2.4.2 rn-fetch-blob: ^0.10.16 => 0.10.16 sp-react-native-in-app-updates: ^1.3.1 => 1.3.1 typescript: 4.8.4 => 4.8.4 uuid: 9.0.0 => 9.0.0 (8.3.2) npmGlobalPackages: corepack: 0.10.0 ios-deploy: 1.12.1 npm: 8.6.0 react-native-cli: 2.0.1 ```

Describe the bug

These problems are specific to iOS. Android works perfectly as documented

issues 1: when clicking a push notification while the app is terminated, once the app starts up, onNotificationOpened is called. getLaunchNotification returns nothing 2: onTokenReceived is never called

I should note that I am migrating from V5 to V6 following your guide. For V5, I experienced other issues with iOS that prompted me to try out V6. However, onTokenRecieved was working for V5. With just a namechange for V6 and its stopped working.

Expected behavior

  1. getLaunchNotification should be called. onNotificationOpened should not be called

  2. onTokenRecieved should be called

Reproduction steps

apart from the setup code below, both handling permissions (a copy paste of your example permission function) and getLaunchNotification are called later when the app has done its own initialization.

Thats all I can think of.

Code Snippet

// Put your code below this line.
import { initializePushNotifications, getPermissionStatus, onTokenReceived, onNotificationReceivedInForeground, onNotificationOpened, getLaunchNotification, requestPermissions} from 'aws-amplify/push-notifications';

configure()
AppRegistry.registerComponent(appName, () => App);

function configure () {

    Amplify.configure({
        Notifications: {
            Push: {
                AWSPinpoint: {
                    appId: 'com.xxx,yyy',
                    region: 'ap-southeast-2'
                }
            }
        }
    });

    initializePushNotifications();

    onTokenReceived((token) => {
    console.log(token)
    });

    onNotificationReceivedInForeground((notification) => {
 console.log(notification)
    });

   onNotificationOpened((notification) => {
  console.log(notification)
    });
  }

Log output

``` // Put your logs below this line ```

aws-exports.js

No response

Manual configuration

No response

Additional configuration

No response

Mobile Device

No response

Mobile Operating System

No response

Mobile Browser

No response

Mobile Browser Version

No response

Additional information and screenshots

No response

stevenmathers commented 9 months ago

Update on this - I can get the device token. I missed the ...didRecieveToken... in the AppDelegate.m .

However, the issue with getLaunchNotification (iOS only) remains

nadetastic commented 9 months ago

Hi @stevenmathers thank you for opening this issue, I am currently taking a look at this and will provide an update soon. In the meantime let me know if you have any more context or new information.

nadetastic commented 8 months ago

HI @stevenmathers following up here - please note that calling getLaunchNotification can return a null result if:

Can you verify if any of these cases may be affecting you?

Additionally in the code snippet you shared, I don't see where you are calling getLaunchNotification(), if you are could you share the code snippet on how you are calling it?

stefoid commented 8 months ago

Hi.

Well, its not a very interesting snippet, but this is called one time only at a specific point in the app after the user has logged in.

startupNotification = await getLaunchNotification();

As I understand it, onNotificationOpened should not be called when the app is started from a terminated state by clicking on a push notification?

cwomack commented 7 months ago

@stefoid, can you share where you are calling getLaunchNotification()?

stefoid commented 7 months ago

Its being called after login and syncing of data from the backend, which could take a few seconds. Once the app reaches this point, I call getLaunchNotification for the first time, and once only.

cwomack commented 7 months ago

@stefoid, got it. Can you confirm that you're "killing" the app by swiping it away/closing it down? And is the app being relaunched by tapping the notifications that are coming in?

If all this is being done, can you confirm in this scenario that onNotificationOpened() is being triggered afterwards?

If background mode is enabled, then getLaunchNotification() may not fire in iOS. If this is the case, then you'd refer to the onNotificationOpened().

stefoid commented 7 months ago

yes to all the above. The identical JS code works perfectly in Android, as in getLaunchNotification() reliably returns the notification when the app has been launched from tapping the notification (as opposed to bringing it from background to the foreground).

cshfang commented 7 months ago

Hey @stefoid

Thanks for getting back to us so quickly. The reason for why the behavior of these APIs different on iOS vs Android is due to how the systems handle background tasks.

With background mode enabled in iOS, when a push notification arrives during a terminated state, it will actually fully wake and start your app in the background (and trigger onNotificationReceivedInBackground) without launching it to the foreground. Due to this behavior, when you now tap on a notification, your application is actually already awake and therefore it is the onNotificationOpened which gets triggered.

stefoid commented 7 months ago

So getLaunchNotification is N/A to iOS? I suggest documenting the difference in the API if it isnt already (apologies if I missed it)

cshfang commented 7 months ago

You're certainly right that we should improve documentation around the specific behavior with the background capabilities enabled. I will add this to our tasks queue.

In the meantime, the combination of getLaunchNotification and onNotificationOpened should hopefully satisfy your use cases.