Amplify-js: OpenUrl with PushNotification ?

Created on 23 Nov 2018  路  13Comments  路  Source: aws-amplify/amplify-js

Hi everybody,
We are using react native.
We would like to open an URL when we receive a Push Notification, we could see the push on the PushNotification.onNotification Event when the push arrives to the phone but we can not open the corresponding URL when the user Tap the Notification Message.

we are using:

"@aws-amplify/pushnotification": "^1.0.17",
"aws-amplify": "^1.1.9",
"react": "16.6.0-alpha.8af6728",
"react-native": "0.57.4",

iOS and Android.

Any ideas?

Thanks!

Push Notifications React Native feature-request

Most helpful comment

The problem ls when you have Many notifications, then the user tap any of them and the app May be open a different link.

All 13 comments

@powerful23 I don't think this is a bug, I think that the Amplify library is not completed yet and so there is no way to catch that TAP on the message. At least do you know what Do I have to do in order to open the URL when the user TAP the message? Any ideas? May be is is something I have to add to the manifest and catch on RN ?

Thanks!

@matamicen as for now we do not have the feature in our library so I will mark this as feature request. As a work around can you try do it by using the Linking module from react-native: https://facebook.github.io/react-native/docs/linking to open the url you received from notification?

I run into the same situation where I want to open URL when user taps the notification message.

My workaround is:
1 - when PushNotification.onNotification triggered, save the link using AsyncStorage
2 - when the app comes into "active" mode for the first time (meaning when user click on the notification), open the link on the browser using Linking.openURL(), then empty the AsyncStorage value afterward

Would be a lot better if we can have something like PushNotification.onNotificationTapped from the library : ).

My implementation:

import {
    Platform,
    Linking,
    AppState
} from 'react-native'

import {
    storageSet,
    storageGet
} from '../../helpers/Storage'

const NOTIFICATION_LINK = '@notificationLink'

componentDidMount() {
        AppState.addEventListener('change', this._handleAppStateChange)

        // Processing notification
        PushNotification.onNotification((notification) => {
            /**
             * Upon received a notification,
             * If App is in active mode, do nothing,
             * If App is in background, save it to AsyncStorage
             * @type {*}
             */
            const link = this._getNotificationLink(notification)
            if (link && AppState.currentState !== 'active') storageSet(NOTIFICATION_LINK, link)

            // required on iOS only (see fetchCompletionHandler docs: https://facebook.github.io/react-native/docs/pushnotificationios.html)
            if (Platform.OS === 'ios') {
                notification.finish(PushNotificationIOS.FetchResult.NoData)
            }
        })
}

/**
     * Detect AppState changing to active, then open notification link if any
     *
     * @param nextAppState
     * @private
     */
    _handleAppStateChange = (nextAppState) => {
        if (nextAppState === 'active') {
            this._openNotificationLink()
        }
    }

/**
     * Open notification link in browser
     *
     * @private
     */
    _openNotificationLink = () => {
        storageGet(NOTIFICATION_LINK)
            .then(link => {
                if (link) {
                    Linking.openURL(link)
                        .then(storageSet(NOTIFICATION_LINK, ''))
                        .catch(error => console.log('Error opening notification', error))
                }
            })
    }

/**
     * Extract link from notification, if any
     *
     * @param notification
     * @returns {*}
     * @private
     */
    _getNotificationLink(notification) {
        if (Platform.OS === 'ios') {
            const notificationData = notification.getData()
            if (typeof notificationData['data'] !== 'undefined') {
                if (typeof notificationData['data']['pinpoint'] !== 'undefined') {
                    if (typeof notificationData['data']['pinpoint'].deeplink !== 'undefined') {
                        return notificationData['data']['pinpoint'].deeppink
                    }
                }
            }
        } else if (Platform.OS === 'android') {
            if (typeof notification.data !== 'undefined') {
                if (typeof notification.data['pinpoint.url'] !== 'undefined') {
                    return notification.data['pinpoint.url']
                }
            }
        }

        return null
    }

My storageHelper:

// file `../../helpers/Storage.js`
import { AsyncStorage } from 'react-native'

const storageSet = async (key, value) => {
    try {
        await AsyncStorage.setItem(key, value)
    } catch (e) {
        console.log(`Error setting ${key} to ${value}`)
    }
}

const storageGet = async (key) => {
    try {
        return await AsyncStorage.getItem(key)
    } catch (e) {
        console.log(`Error getting ${key}`)
    }
}

export {
    storageGet,
    storageSet
}

The problem ls when you have Many notifications, then the user tap any of them and the app May be open a different link.

@matamicen Right, this temporary workaround will just pick up the latest notification link.

how about using onTappedNotification ?

I had a similar issue with what you describe as "The problem ls when you have Many notifications, then the user tap any of them and the app May be open a different link." for an unrelated thing. Looks like with the newer version of the pushnotification package you may now use

// get the notification data when notification is opened
PushNotification.onNotificationOpened((notification) => {
    console.log('the notification is opened', notification);
});

https://aws-amplify.github.io/docs/js/push-notifications#working-with-the-api

This helped be certain that I am retrieving data from the exact notification that was clicked.

PushNotification.onNotificationOpened() is exactly what I'm looking for.
But I'm having trouble picking the package versions and it doesn't work well for me :|

@brettnovak would you mind sharing your dependencies version?

My non-working dependencies stack:

"dependencies": {
    "@aws-amplify/analytics": "^1.2.10",
    "@aws-amplify/auth": "^1.2.15",
    "@aws-amplify/pushnotification": "^1.0.22",
    "aws-amplify": "^1.1.19",
    "react": "16.6.3",
    "react-native": "0.57.8",
    "react-native-app-auth": "^4.0.0",
    "react-native-gesture-handler": "^1.0.10",
    "react-native-picker-select": "^5.1.0",
    "react-native-vector-icons": "^6.1.0",
    "react-navigation": "^3.0.4"
  },

This last function, onNotificationOpened() is currently only supported on Android.

PushNotification.ts:

    PushNotification.prototype.onNotificationOpened = function (handler) {
        if (typeof handler === 'function') {
            // check platform
            if (react_native_1.Platform.OS === 'android') {
                this.addEventListenerForAndroid(REMOTE_NOTIFICATION_OPENED, handler);
            }
        }
    };

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@matamicen from @brettnovak's call out above, this seems to suit your use case. Im going to resolve this issue. Please feel free to open it if this is not what your are looking for. Thanks!

@sammartinez since onNotificationOpened() is supported only on Android, how notifications can be handled on iOS when application has been closed? Thanks for hint!

Used PushNotificationIOS.getInitialNotification() from @react-native-community/push-notification-ios

PushNotificationIOS.getInitialNotification()
  .then(notification => {
    if (notification) {
      ...
    }
  })
Was this page helpful?
0 / 5 - 0 ratings