React-native-push-notification: PushNotification.requestPermissions needs documentation

Created on 30 Apr 2017  路  18Comments  路  Source: zo0r/react-native-push-notification

PushNotification.requestPermissions is missing documentation. Investigating the code suggests that this method returns a promise but the promise never seems to resolve or reject. Would someone with knowledge around this be willing to add documentation for this?

Most helpful comment

@a-koka This sadly does not work. the Promise does not wait for requestPermissions(), which itself is a buggy Promise that needs fixing from the react-native core.

All 18 comments

馃憤 I'm also not clear on how this works. What's "PushNotificationsHandler.requestPermissions"?

@RWOverdijk The idea behind PushNotificationsHandler.requestPermissions is to control when to prompt the user to allow/deny push notifications. Since you get only one chance to do this, it is often preferred to not do this upon app load.

I dropped it :) I'm now requesting permissions on auth.

@a-koka do you have any example code for implementing this?

+1

Sure, I'm more than happy to share my implementation below @philwilks . Notice how Android doesn't require you to request permissions.

      new Promise(resolve => {
        if (Platform.OS === 'ios') {
          PushNotification.checkPermissions(({ alert, badge, sound }) => {
            if (!alert || !badge || !sound) {
              PushNotification.requestPermissions();
            }
            resolve();
          });
        } else {
          resolve();
        }
      }).then(() => {
        PushNotification.cancelAllLocalNotifications();
        PushNotification.localNotificationSchedule(yourNotificationObject);
      });

@a-koka This sadly does not work. the Promise does not wait for requestPermissions(), which itself is a buggy Promise that needs fixing from the react-native core.

So how reliable is this, if we the promise chain has a bug? Any update on this?

I recently migrated to Firebase which works very reliably. I realize this requires adding Firebase to your project which isn't ideal for everyone but I just wanted to share a working solution here.

await firebase.messaging().requestPermission();

@a-koka Nice to know! Are you using react-native-firebase?

Yes, react-native-firebase seems to work like a charm.

So what I'm hearing is that if we requestPermissions as part of our authentication, we have no way of knowing whether permission was granted or rejected before the auth occurs, because the Promise isn't working, right? This leaves us in a weird state where we can't inform the server of the user's Device ID during initial authentication.

Edit: I see this is a problem with RN's PushNotificationIOS module, not this project's. For reference, it's a listed Issue: https://github.com/facebook/react-native/issues/20821

It seems there IS a way of knowing the permission status when using PushNotification.requestPermissions; it seems that when granted the response is an object with alert, badge and sound keys with value 1 and when rejected the value is 0. Here's my code (thanks @a-koka for sharing your implementation!):

handleCheckNotificationPermissions = () => {
    if (Platform.OS === "ios") {
      PushNotification.checkPermissions(({ alert, badge, sound }) => {
        if (!alert || !badge || !sound) {
          PushNotification.requestPermissions()
            .then(grant => {
              if (grant.alert && grant.badge && grant.sound) {
                this.setState({ permissionGranted: true });
                this.handleObtainDeviceToken();
              } else {
                this.setState({ permissionError: true });
              }
            })
        } else {
          this.setState({ permissionGranted: true });
          this.handleObtainDeviceToken();
        }
      })
    } else {
      this.setState({ permissionGranted: true });
    }
  };

This works as expected :) my problem now is that I'm getting the following warnings:

"Attempted to invoke '0' (method ID) on 'BlobModule' (NativeModule name) with an invalid bridge.!
!Attempted to invoke '1' (method ID) on 'WebSocketModule' (NativeModule name) with an invalid bridge."
"Attempted to invole '5' (method ID) on 'WebSocketModule' (NativeModule name) with an invalid
bridge."
"Attempted to invole '0' (method ID) on 'AppState' (NativeModule name) with an invalid bridge."
"Attempted to invole '1' (method ID) on 'AppState' (NativeModule name) with an invalid bridge."

Does this library still not have a method to check if the permissions were denied?

This is important for iOS as you can't prompt again. It would be nice to move this into the library rather than write our own custom code for it. As it isn't clear how it works I will be experimenting with it till I get my code right.

It would be nice if it could handle both Android and iOS permission status.

Is there a way to contribute to this library knowing JavaScript only?

Another solution to add promises to the PushNotificationIOS.checkPermissions is:

function checkPermissions() {
  return new Promise(resolve => PushNotificationIOS.checkPermissions(resolve));
}

And then use:

checkPermissions.then(permissions => {
  console.log('Permissions: ', permissions);
});

// or...

const permissions = await checkPermissions();
console.log('Permissions: ', permissions);

This seems to be working perfectly on 5.x. Permissions are requested only the first time the switch is pressed. (We have a notification reminder switch that is only enable-able if the permissions are available.)

  const handleSwitchPress = async () => {
    if (Platform.OS === "ios") {
      await PushNotification.requestPermissions();
    }
    PushNotification.checkPermissions(permissions => {
      if (permissions.alert !== true) {
        Alert.alert(
          "2MR does not have permission to show you an alert.  Please add this permission in your OS settings and try again."
        );
        setReminderSwitchState(false);
      } else {
        setReminderSwitchState((prev: boolean) => !prev);
      }
    });
  };

Probably will improve this by adding a button that performs Linking.openSettings();.

requestPermissions do not return until the user have used the browser UI to either allow or deny the request. That's why the promise doesn't seem to complete.

Was this page helpful?
0 / 5 - 0 ratings