Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android check shows that Notifications can be requested, but it is not requestable #828

Closed
itsramiel opened this issue Dec 5, 2023 · 2 comments
Assignees

Comments

@itsramiel
Copy link

Bug summary

When I request notification permission and deny the dialog twice, then check returns that I can still request, but request returns that user denied and cannot be requested again, so they conflict with each other.

I tried to use check and request apis and checkNotifications and requestNotifications api

Library version

4.0.0

Environment info

System:
  OS: macOS 14.0
  CPU: (16) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
  Memory: 602.55 MB / 16.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 18.17.1
    path: ~/.nvm/versions/node/v18.17.1/bin/node
  Yarn:
    version: 1.22.19
    path: ~/.nvm/versions/node/v18.17.1/bin/yarn
  npm:
    version: 9.6.7
    path: ~/.nvm/versions/node/v18.17.1/bin/npm
  Watchman:
    version: 2023.10.09.00
    path: /usr/local/bin/watchman
Managers:
  CocoaPods:
    version: 1.14.2
    path: /Users/ramiel/.rbenv/shims/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 23.0
      - iOS 17.0
      - macOS 14.0
      - tvOS 17.0
      - watchOS 10.0
  Android SDK: Not Found
IDEs:
  Android Studio: 2022.1 AI-221.6008.13.2211.9619390
  Xcode:
    version: 15.0.1/15A507
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 11.0.15
    path: /usr/local/opt/openjdk@11/bin/javac
  Ruby:
    version: 2.7.6
    path: /Users/ramiel/.rbenv/shims/ruby
npmPackages:
  "@react-native-community/cli": Not Found
  react:
    installed: 18.2.0
    wanted: 18.2.0
  react-native:
    installed: 0.72.7
    wanted: 0.72.7
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: false
iOS:
  hermesEnabled: true
  newArchEnabled: false

Steps to reproduce

request notification permissions twice and deny them, then check for permissions and you'll get that DENIED instead of expected BLOCKED

Here is a video:

Screen.Recording.2023-12-05.at.10.11.45.PM.mov

Reproducible sample code

import {View, Button} from 'react-native';
import {
  check,
  checkNotifications,
  PERMISSIONS,
  request,
  requestNotifications,
  RESULTS,
} from 'react-native-permissions';

function App() {
  return (
    <View
      style={{
        flex: 1,
        alignItems: 'center',
        justifyContent: 'center',
        gap: 32,
      }}>
      <Button
        title="check notifications"
        onPress={checkNotificationPermission}
      />
      <Button
        title="request notifications"
        onPress={requestNotificationPermission}
      />
      <Button
        title="check notifications2"
        onPress={checkNotificationPermission2}
      />
      <Button
        title="request notifications2"
        onPress={requestNotificationPermission2}
      />
    </View>
  );
}

export default App;

function checkNotificationPermission() {
  checkNotifications().then(({status}) => {
    switch (status) {
      case RESULTS.UNAVAILABLE:
        console.log(
          'This feature is not available (on this device / in this context)',
        );
        break;
      case RESULTS.DENIED:
        console.log(
          'The permission has not been requested / is denied but requestable',
        );
        break;
      case RESULTS.LIMITED:
        console.log('The permission is limited: some actions are possible');
        break;
      case RESULTS.GRANTED:
        console.log('The permission is granted');
        break;
      case RESULTS.BLOCKED:
        console.log('The permission is denied and not requestable anymore');
        break;
    }
  });
}

function requestNotificationPermission() {
  requestNotifications(['alert', 'sound', 'badge']).then(({status}) => {
    switch (status) {
      case RESULTS.UNAVAILABLE:
        console.log(
          'This feature is not available (on this device / in this context)',
        );
        break;
      case RESULTS.DENIED:
        console.log(
          'The permission has not been requested / is denied but requestable',
        );
        break;
      case RESULTS.LIMITED:
        console.log('The permission is limited: some actions are possible');
        break;
      case RESULTS.GRANTED:
        console.log('The permission is granted');
        break;
      case RESULTS.BLOCKED:
        console.log('The permission is denied and not requestable anymore');
        break;
    }
  });
}

function checkNotificationPermission2() {
  check(PERMISSIONS.ANDROID.POST_NOTIFICATIONS).then(result => {
    switch (result) {
      case RESULTS.UNAVAILABLE:
        console.log(
          'This feature is not available (on this device / in this context)',
        );
        break;
      case RESULTS.DENIED:
        console.log(
          'The permission has not been requested / is denied but requestable',
        );
        break;
      case RESULTS.LIMITED:
        console.log('The permission is limited: some actions are possible');
        break;
      case RESULTS.GRANTED:
        console.log('The permission is granted');
        break;
      case RESULTS.BLOCKED:
        console.log('The permission is denied and not requestable anymore');
        break;
    }
  });
}

function requestNotificationPermission2() {
  request(PERMISSIONS.ANDROID.POST_NOTIFICATIONS).then(result => {
    switch (result) {
      case RESULTS.UNAVAILABLE:
        console.log(
          'This feature is not available (on this device / in this context)',
        );
        break;
      case RESULTS.DENIED:
        console.log(
          'The permission has not been requested / is denied but requestable',
        );
        break;
      case RESULTS.LIMITED:
        console.log('The permission is limited: some actions are possible');
        break;
      case RESULTS.GRANTED:
        console.log('The permission is granted');
        break;
      case RESULTS.BLOCKED:
        console.log('The permission is denied and not requestable anymore');
        break;
    }
  });
}
@itsramiel itsramiel added the bug Something isn't working label Dec 5, 2023
@zoontek
Copy link
Owner

zoontek commented Dec 6, 2023

Hi 👋 This is expected, it cannot be known on Android before requested.

If you check the Android permission flow, you see that there's no way it returns blocked before calling request. That's also why the builtin module (PermissionsAndroid) return a boolean for check, and a status for request.

Note that you have this warning in the check README documentation:

Screenshot 2023-12-06 at 09 49 20

Consider this:

  • Before showing the screen that require the permission, check it
  • If it's granted, mount the screen that use it
  • If it's blocked, display a screen that explain that the user will have to go to settings to enable it (+ show a button that call openSettings) (will never ne visible on Android, but could be on iOS)
  • If it's denied, display a screen with a button to perform a request. After that, if it's granted -> mount the screen that use it. If it's blocked -> Display an alert or the blocked screen before encouraging going to the settings (using openSettings)

The UX is great on iOS, good enough on Android given the platform limitations

@zoontek zoontek closed this as completed Dec 6, 2023
@itsramiel
Copy link
Author

Thank you for the explanation!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants