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

OneSignal.Notifications.hasPermission() is returning false always [Bug]: #1640

Closed
3 tasks done
rakshitbharat opened this issue Jan 31, 2024 · 31 comments
Closed
3 tasks done

Comments

@rakshitbharat
Copy link

rakshitbharat commented Jan 31, 2024

What happened?

OneSignal.Notifications.hasPermission()
is returning false always

Steps to reproduce?

just use 
OneSignal.Notifications.hasPermission()

What did you expect to happen?

OneSignal.Notifications.hasPermission()
this should give true or false based on real world

React Native OneSignal SDK version

5

Which platform(s) are affected?

  • iOS
  • Android

Relevant log output

No response

Code of Conduct

  • I agree to follow this project's Code of Conduct
@Salmankhan033
Copy link

Same issue with me.
when we true from the phone setting then it also returns false

@ChromeQ
Copy link

ChromeQ commented Feb 1, 2024

This has also been mentioned here with a solution workaround: #1506 (comment)

Good to see this issue raised on it's own rather than bundled into feedback for v5.

@rakshitbharat
Copy link
Author

rakshitbharat commented Feb 1, 2024

This has also been mentioned here with a solution workaround: #1506 (comment)

Good to see this issue raised on it's own rather than bundled into feedback for v5.

Thanks for highlighting but this issue is opened when no solution/workaround ever worked for me.

@ChromeQ
Copy link

ChromeQ commented Feb 1, 2024

@rakshitbharat if you want to provide a bit more detail including the relevant files or a minimal reproducible repo I am happy to take a look for you and see if the workarounds can work for you.

@rakshitbharat
Copy link
Author

Thanks for replying, but it's very simple
At any stage you use this function with latest react native .73 then you will get false.

But the strange part is, you will get false only on 2nd time when you open the application.

When you give permission first time you will get true,,,, ya but again if you quite the application then you will never ever get true/false based on real situation about permission for the application.

@nan-li
Copy link
Contributor

nan-li commented Feb 1, 2024

Hi @rakshitbharat @Salmankhan033 @ChromeQ,

Are you are asking for hasPermission very early in the app startup? Then, if you check for it a little while later, it is correct?

If that is your situation, this is an issue we have identified with help from reporters on our Cordova SDK. It is due to the SDK not setting the correct value yet that early in the app process, but we will be adding async method to retrieve it.

If that is not your scenario, can you please share more details?

@ChromeQ
Copy link

ChromeQ commented Feb 1, 2024

@nan-li yes that is exactly the situation, the method always returns false when requested early in the app startup process, and my workaround of adding a setTimeout will then return the correct value.

An async method would be good but ideally it should be returning the correct value synchronously too if possible. Thanks

@rakshitbharat
Copy link
Author

No it is user based, I also want to add that this is happening to our latest build in which we are using this liberary from version 4,
So our app and we both are experienced with this library.

Also want to add our current build with this library v4 working in production without any issue, and yes again after updating to v5 with this is happening.

@Salmankhan033
Copy link

Salmankhan033 commented Feb 1, 2024

@nan-li I used async to get the hasPermission .
When I decline the permission and add manually from the phone settings then it also return the hasPermission false.
I reload many time but it return false but permission is on in settings

@rakshitbharat
Copy link
Author

@Salmankhan033
Agree with you,
This function is not working excepted way.
And it's very urgent for me to resolve this issue.
The problem is we are using Onesignal paid version and it's in production
Otherwise we have changed to any other work around.

@Salmankhan033
Copy link

@rakshitbharat Can you suggest any other platforms for sending notifications because it seems like onesignal is not really working as its supposed to, we have a very simple need: if the user has notifications enabled send the one_signal_id in the header otherwise the header is empty but it seems that it does not want to work like this on all devices, so please if you know a different solution or another workaround for this issue please let us know, thank you for dealing with this as well!

@rakshitbharat
Copy link
Author

@Salmankhan033 I am sure you are asking because you are also having something in production like me brother,
It's very responsible think you asked to me,
Alternative is >>MoEngage<<

:::Again, I don't have production experience with >>MoEngage<<:::

@ChromeQ
Copy link

ChromeQ commented Feb 1, 2024

@rakshitbharat

this is happening to our latest build in which we are using this liberary from version 4

The latest version is v5 so please at least try upgrading to the latest version and perhaps you will solve your issue, and start experiencing the one this issue is tracking. Let's please focus on one problem as described and multiple people have reported here and in the #1506

@ChromeQ
Copy link

ChromeQ commented Feb 1, 2024

@nan-li I used async to get the hasPermission . When I decline the permission and add manually from the phone settings then it also return the hasPermission false. I reload many time but it return false but permission is on in settings

How do you mean you "used async"? The method is not async so I'm curious what you tried, but it sounds like it didn't work anyway.
Can you please confirm if you are using v5 and try wrapping the call to hasPermission in a setTimeout with 500ms, mine works with zero but will be keen to see if yours works as expected with the timeout.

@Salmankhan033
Copy link

Salmankhan033 commented Feb 1, 2024

@rakshitbharat

this is happening to our latest build in which we are using this liberary from version 4

The latest version is v5 so please at least try upgrading to the latest version and perhaps you will solve your issue, and start experiencing the one this issue is tracking. Let's please focus on one problem as described and multiple people have reported here and in the #1506

I tested on v5.0.1 and v5.0.1, but same issue

@rakshitbharat
Copy link
Author

rakshitbharat commented Feb 1, 2024

@rakshitbharat

this is happening to our latest build in which we are using this liberary from version 4

The latest version is v5 so please at least try upgrading to the latest version and perhaps you will solve your issue, and start experiencing the one this issue is tracking. Let's please focus on one problem as described and multiple people have reported here and in the #1506

Using latest,
And again l
Highlighting I am using this library from last 1year also also used v4
The same project is now in upgrade to v5
And in the same project we are having problem with the same code which is used with v4
With v4 everything working fine with v5 this true/false issue occurred.

@rakshitbharat
Copy link
Author

@nan-li I used async to get the hasPermission . When I decline the permission and add manually from the phone settings then it also return the hasPermission false. I reload many time but it return false but permission is on in settings

How do you mean you "used async"? The method is not async so I'm curious what you tried, but it sounds like it didn't work anyway. Can you please confirm if you are using v5 and try wrapping the call to hasPermission in a setTimeout with 500ms, mine works with zero but will be keen to see if yours works as expected with the timeout.

Not working with timeout.

@ChromeQ
Copy link

ChromeQ commented Feb 1, 2024

Are you also calling the method from inside a React.useEffect? This was my setup and adding the timeout worked as a workaround/hack. I'm just trying to understand why we are experiencing the total opposite return values. If you could share some code that would make things a bit easier to compare and reproduce on my end.

@rakshitbharat
Copy link
Author

rakshitbharat commented Feb 1, 2024

I am dam sure, because I am using this since it was v4
v5 always giving false.

Also about code, it's not more we directly use this function to get the status in use effect which was/is working great with v4 but not working with v5

@ChromeQ
Copy link

ChromeQ commented Feb 1, 2024

The method hasPermission has only been part of react-native-onesignal since v5, v4 did not so you could not have been using it since v4.
I'm not sure I understand your last sentence but I am not trying to be difficult, I am genuinely trying to understand your setup and seeing your code will help me try to help you. We're both trying to get to a root cause to help the devs make the correct fix.

@rakshitbharat
Copy link
Author

So, let me show up v4 code and v5 code both from this repo,
I am away from my computer.
Will reply ASAP

@rakshitbharat
Copy link
Author

rakshitbharat commented Feb 1, 2024

so i came up with working and very stable work around not like time out but really good and stable
@Salmankhan033 maybe you can use this for now and resolve this issue,
much love from India brother...

This code is not working properly

// Define an asynchronous function named `checkNotificationPermissions`
const checkNotificationPermissions = async () => {
  // Initialize a variable `r` with `false`. This will hold the result of the permission check.
  let r = false;

  // Check if the application has the necessary permissions to display notifications using OneSignal.
  // If it does (`OneSignal.Notifications.hasPermission()` returns `true`), set `r` to `true`.
  if (OneSignal.Notifications.hasPermission()) {
    r = true;
  }

  // Call the `setNotificationPermissionGiven` function with `r` as an argument.
  // This function is not defined in the provided code, but it presumably updates the state or performs some other action to record the permission status.
  setNotificationPermissionGiven(r);

  // Return the value of `r`.
  // This allows the caller of `checkNotificationPermissions` to know whether the permission was granted or not.
  return r;
};

this is working properly code
but before adding this code you have to install one open source library which is made dedicated to check permissions
library is

"react-native-push-notification": "^8.1.1",
after installing you can add below code

import PushNotification from 'react-native-push-notification';

// Define an asynchronous function named `checkNotificationPermissions`
const checkNotificationPermissions = async () => {
  // Create a new Promise that wraps the `PushNotification.checkPermissions` function.
  // This function is asynchronous and uses a callback to return its result.
  const permissionStatus = await new Promise(resolve => {
    // Call `PushNotification.checkPermissions` with a callback function
    PushNotification.checkPermissions(s => {
      // The callback function checks if the `alert` permission is granted.
      // If it is (`s.alert === true`), it resolves the Promise with `true`.
      // If it's not, it resolves the Promise with `false`.
      if (s.alert === true) {
        resolve(true);
      } else {
        resolve(false);
      }
    });
  });

  // Call the `setNotificationPermissionGiven` function with `permissionStatus` as an argument.
  // This function is not defined in the provided code, but it presumably updates the state or performs some other action to record the permission status.
  setNotificationPermissionGiven(permissionStatus);

  // Return the `permissionStatus`.
  // This allows the caller of `checkNotificationPermissions` to know whether the permission was granted or not.
  return permissionStatus;
};

@ChromeQ
Copy link

ChromeQ commented Feb 1, 2024

@rakshitbharat where do you have the checkNotificationPermissions function? Is this inside a react component? Is that react component rendered on app start or is it conditional on a click or other condition?

@rakshitbharat
Copy link
Author

@rakshitbharat where do you have the checkNotificationPermissions function? Is this inside a react component? Is that react component rendered on app start or is it conditional on a click or other condition?

It's a react component and with the new solution with the new library suggested by me that works perfectly now for me.

@ChromeQ
Copy link

ChromeQ commented Feb 2, 2024

In that case can you try to replace your whole checkNotificationPermissions function above with the following and try again:

    // Set the `permissionGranted` on first load based on device permission
    useEffect(() => {
      const setInitialPermission = () => {
        const granted = OneSignal.Notifications.hasPermission(); // this will be a boolean
        console.log('INITIAL PERMISSION', granted);
      };

      // FIXME: Hack to get correct value from `hasPermission()`
      // @see https://github.com/OneSignal/react-native-onesignal/issues/1506#issuecomment-1706332448
      // setInitialPermission(); // <-- this line will always be false
      setTimeout(setInitialPermission, 0); // <-- which is why this fix should get around it
    }, []); // <-- Make sure there are no dependencies so it loads on component mount as early as possible

I'm really keen to see the same outcome as I am seeing, cos I've re-read all your comments and it is a little inconsistent and your code examples didn't use the proposed workarounds.
You should not need another package to get the correct value, your 2nd code example for that is also flawed with unnecessary wrapping of promises, but you won't need it so hopefully the above snippet will work for you and you can remove a dependency (which is always better)

@rakshitbharat
Copy link
Author

rakshitbharat commented Feb 2, 2024

In that case can you try to replace your whole checkNotificationPermissions function above with the following and try again:

    // Set the `permissionGranted` on first load based on device permission
    useEffect(() => {
      const setInitialPermission = () => {
        const granted = OneSignal.Notifications.hasPermission(); // this will be a boolean
        console.log('INITIAL PERMISSION', granted);
      };

      // FIXME: Hack to get correct value from `hasPermission()`
      // @see https://github.com/OneSignal/react-native-onesignal/issues/1506#issuecomment-1706332448
      // setInitialPermission(); // <-- this line will always be false
      setTimeout(setInitialPermission, 0); // <-- which is why this fix should get around it
    }, []); // <-- Make sure there are no dependencies so it loads on component mount as early as possible

I'm really keen to see the same outcome as I am seeing, cos I've re-read all your comments and it is a little inconsistent and your code examples didn't use the proposed workarounds. You should not need another package to get the correct value, your 2nd code example for that is also flawed with unnecessary wrapping of promises, but you won't need it so hopefully the above snippet will work for you and you can remove a dependency (which is always better)

In App.js component I will plainly put your code and forward the output ASAP, I can understand you want to be on the same page.

@jennantilla
Copy link
Contributor

Hello everyone! Just wanted to reiterate @nan-li that we are working on making hasPermission async which will ensure that the correct permission status is returned. We will be sure to update you here as soon as the release is ready. Thanks for your patience!

@rakshitbharat
Copy link
Author

Screenshot 2024-02-03 at 3 09 05 PM

@ChromeQ

now no doubt to use my work around mentioned in this thread to use >>>react-native-push-notification<<< at least for urgency

@jennantilla
Copy link
Contributor

Hello everyone! Thank you so much for your patience. Just a heads up that we have updated our SDK to allow for an async permission getter. Please upgrade to 5.1.0. If anyone is still having issues after the update, please let us know!

@ChromeQ
Copy link

ChromeQ commented Mar 21, 2024

I can confirm this is working exactly as intended, thanks @jennantilla 🎉

useEffect(() => {
      const setInitialPermission = async () => {
        const granted = OneSignal.Notifications.hasPermission();
        const granted2 = await OneSignal.Notifications.getPermissionAsync();
        console.log('IS GRANTED', granted, granted2);

        setPermissionGranted(granted);
      };

      // FIXME: Hack to get correct value from `hasPermission()`
      // @see https://github.com/OneSignal/react-native-onesignal/issues/1506#issuecomment-1706332448
      // setTimeout(setInitialPermission, 0);
      setInitialPermission();
    }, []);
# output
 LOG - IS GRANTED false true

@sipotat
Copy link

sipotat commented Mar 31, 2024

I'm using the latest version (5.1.0) with getPermissionAsync and still getting the right answer on the first time and then the same answer, no matter if the permission has changed.

useEffect(() => {
    const checkPremission = () => {
      OneSignal.Notifications.canRequestPermission().then(
        setCanRequestPermissions,
      );
      OneSignal.Notifications.getPermissionAsync().then(setHasPermission);
    };

    checkPremission();

    OneSignal.User.pushSubscription.addEventListener('change', () => {
      checkPremission();
    });
    return () => {
      OneSignal.User.pushSubscription.removeEventListener(
        'change',
        checkPremission,
      );
    };
  }, []);

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

6 participants