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

[Bug]: Inconsistent behavior with Notifications.requestPermission(true) when user prompted to change settings #968

Open
3 tasks done
kpturner opened this issue Jan 27, 2024 · 16 comments

Comments

@kpturner
Copy link

kpturner commented Jan 27, 2024

What happened?

If I call Notifications.requestPermission(true) on iOS or Android 13, and the call deems that it is necessary to prompt the user, two things happen:

  1. It prompts for permission or
  2. If 1) has already been previously prompted, it will prompt the user to change their settings

If 2) takes place, then the call to the function exits as soon as the user clicks the "Settings" button and returns false - so you do not actually know if the user allowed notifications in their settings or not.

On Android 12, the function does not exit when the user clicks "Settings". In fact it does not return until the user has visited their settings, changed them and then return control to the app. At that point the function exits, but always returns false regardless of what the user did.

So it seems impossible to know if the user has allowed notifications in their settings or not after calling requestPermission(true)

With Android 13 and iOS you can at least have a listener on the permissionChange event which fires when the user changes the permission in the settings. The same does not work with Android 12. The event does fire (seemingly inconsistently) but provides completely the wrong value - always false even though permission has been granted.

Steps to reproduce?

Described above

What did you expect to happen?

I expect Android 12 and 13 and iOS to behave consistently.

Ideally, the requestPermission(true) call would only return when the user has changed their settings, and will provide the correct value.

Also, the permissionChange event should fire consistently in Android 12 and provide the correct value.

OneSignal Cordova SDK version

5.0.4

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
@louis123562
Copy link

I can confirm this behaviour. I am not even able to subscribe anymore on Android, it always unsubscribes when calling optIn() or requestPermission()

@kpturner
Copy link
Author

I can confirm this behaviour. I am not even able to subscribe anymore on Android, it always unsubscribes when calling optIn() or requestPermission()

When you say it unsubscribes you, do you mean that your subscription disappears from the dashboard or it gets flagged as "opted-out"? Is this Android 12 or 13 by the way?

@louis123562
Copy link

louis123562 commented Jan 29, 2024

It unsubscribes every time, i tested android 13 (sdk 33) only.

It updates the timestamp of 'Last unsubscribed' every time i call requestPermission(true) or requestPermission() or optIn(). Very annoing.
image

It only shows "Permission not granted" when i uninstall the app, install it and call requestPermission(true), then deny it.

@kpturner
Copy link
Author

Have you called login()?

@louis123562
Copy link

What login function?
OneSignal.???.login() ?

@kpturner
Copy link
Author

kpturner commented Jan 29, 2024

Yes I am just trying to see if I can match those symptoms (which seem even more buggy than the ones I reported) but my sequence of events is:
OneSignal.initialize()
OneSignal.login()
and then, if I somehow managed to find out if the user has granted permission or not
OneSignal.User.pushSubscription.optIn()

But if I can get the same result as you then things are even worse than I reported here.

@kpturner
Copy link
Author

kpturner commented Jan 29, 2024

As an aside, you should be aware of this issue too: #918
which renders most of the functions (that should be async and are not) to return incorrect values when the app starts (which is often when you most need them):
OneSignal.User.pushSubscription.optedIn
OneSignal.User.pushSubscription.id
OneSignal.Notifications.hasPermission
and add this in for good measure: #967

But that aside, when I do this

OneSignal.initialize()
OneSignal.login()
OneSignal.User.pushSubscription.optIn()

I do end up with this, but it takes quite a while to update correctly in the dashboard
image

@nan-li
Copy link
Contributor

nan-li commented Jan 29, 2024

Hi @kpturner, thank you for reporting, I was able to reproduce the behavior with calling requestPermission() in combination with the Settings prompt.

We will investigate a solution.

@nan-li
Copy link
Contributor

nan-li commented Jan 29, 2024

Hi @louis123562, can you tell me more about your issue?

When you prompt for permission but before a choice is made, the SDK may believe permission is not granted yet and send an update to the server causing the "Last Unsubscribed" date to be updated on the dashboard. (This is related to the issue reported by @kpturner that we will investigate.) Then when a choice is made on the permission prompt, a subsequent request is sent with that selection.

Are you seeing it does not update in the dashboard after you give permission in the permission prompt?

@kpturner
Copy link
Author

Just top be clear on the Android 12 situation: If you are prompted to change your settings, even if you allow them, hasPermission will continue to return false until you restart the app. It is an absolute nightmare!

@louis123562
Copy link

louis123562 commented Jan 30, 2024

Hi @louis123562, can you tell me more about your issue?

When you prompt for permission but before a choice is made, the SDK may believe permission is not granted yet and send an update to the server causing the "Last Unsubscribed" date to be updated on the dashboard. (This is related to the issue reported by @kpturner that we will investigate.) Then when a choice is made on the permission prompt, a subsequent request is sent with that selection.

Are you seeing it does not update in the dashboard after you give permission in the permission prompt?

I just tested on Android 14, it behaves the same as Android 13.

When removing permission manually in Android settings, then going back into the app, call requestPermission(true), the dialog comes up. If i then look at the OneSignal dashboard, it says "Permission Not Granted" with the current timestamp; so it was updated when the dialog came up.

After accepting to receive notifications in the dialog, the Subscriptions Status is empty, and the Last Subscribed is set with the timestamp when touch "accept" in the dialog. Weird!

Calling optIn() at any time has no effect at all.

This also behaves the same, if the app is reinstalled and/or permissions where not granted yet. For my understanding, it is currently not possible to get any Android to subscribe. All my Android subscriptions either have the Subscription Status empty with a Last Unsubscribed timestamp, or Permission not Granted.

This is not great. With this, i am not able to reach any of my android users.

@kpturner
Copy link
Author

@louis123562 it is worth noting that apparently optIn does not update the dashboard straight away. It updates a flag locally straight away, but the requests to the OneSignal dashboard (server) are batched up and sent periodically. I am not sure what triggers them to be sent but it is not immediate. Obviously this does not explain your scenario though.

@kpturner
Copy link
Author

kpturner commented Feb 5, 2024

I think @louis123562 is possibly experiencing the same issue as I describe here: #967

I can call optIn over an over again and yet the date last unsubscribed data on the dashboard is the only thing that changes, and it still shows "User Opted Out"

I have no idea how to actually get it to regsiter that the user is opted in - or why it thinks the subscription is unsubscribed :(

EDIT: I finally made it work by disallowing notifications on the device, then calling optIn which prompted me to allow notifications and THEN it updated the dashboard correctly.

@kpturner
Copy link
Author

Hi @louis123562, can you tell me more about your issue?

When you prompt for permission but before a choice is made, the SDK may believe permission is not granted yet and send an update to the server causing the "Last Unsubscribed" date to be updated on the dashboard. (This is related to the issue reported by @kpturner that we will investigate.) Then when a choice is made on the permission prompt, a subsequent request is sent with that selection.

Are you seeing it does not update in the dashboard after you give permission in the permission prompt?

Any update on this @nan-li ?

@jkasten2
Copy link
Member

@kpturner this issue sounds similar to this one:
OneSignal/OneSignal-Android-SDK#2106

Can you try the latest OneSignal SDK and test again? If you still see the same issue can you enable OneSignal VERBOSE logging and capture the logcat? Mainly looking for the REST API calls make to OneSignal.

@atwallis
Copy link

atwallis commented Oct 30, 2024

I am getting the similar behavior on Android 12 for v5.2.6 of the package. Here is my code. The subscription says "Permission denied" and there was never a popup request for permissions for me to accept when launching the app.

try {
	OneSignal.Debug.setLogLevel(LogLevel.Verbose);
	OneSignal.initialize(APP_ID);
	await OneSignal.Notifications.requestPermission(true);
	await OneSignal.login(USER_ID);
} catch (e) {
	console.error(e);
}
OneSignal.Notifications.addEventListener('click', async (e) => {
	const notification = e.notification;
	const url = notification.launchURL;
	console.log({
		notification,
		url
	});
});
image

If I remove the `requestPermission(true)` function on Android 12, I never see a permission request popup, but the OneSignal dashboard says that the user is now subscribed.

EDIT - 10/30/2024
I have been trying to reproduce this bug, but it seems once requestPermission function is removed from the code and the client shows "Subscribed" on the dashboard, if I go back and update the code to call requestPermission, it will continue to work.

I checked the LogCat output for when it said "Permission denied" on the dashboard and I saw this error. I have obfuscated some of the ids in the console output.

It seems like the login() may be the issue? I am not sure.

"status":"SUBSCRIBED","id":"e7bxxxxxxxxxxxxx"}
10-30 15:31:15.408 32412   356 E OneSignal: ]
10-30 15:31:15.408 32412   356 E OneSignal: java.lang.Exception: Unrecognized operation: {"name":"login-user","appId":"a8dxxxxxxxxxxxxxxxx","onesignalId":"local-b6cdxxxxxxxxxxxx","externalId":"12","existingOnesignalId":"ea38xxxxxxxxxxxxx","id":"06d1fxxxxxxxxxxxx"}
10-30 15:31:15.408 32412   356 E OneSignal:     at com.onesignal.user.internal.operations.impl.executors.LoginUserOperationExecutor.createUser(LoginUserOperationExecutor.kt:157)
10-30 15:31:15.408 32412   356 E OneSignal:     at com.onesignal.user.internal.operations.impl.executors.LoginUserOperationExecutor.loginUser(LoginUserOperationExecutor.kt:73)
10-30 15:31:15.408 32412   356 E OneSignal:     at com.onesignal.user.internal.operations.impl.executors.LoginUserOperationExecutor.execute(LoginUserOperationExecutor.kt:59)
10-30 15:31:15.408 32412   356 E OneSignal:     at com.onesignal.core.internal.operations.impl.OperationRepo.executeOperations$com_onesignal_core(OperationRepo.kt:232)
10-30 15:31:15.408 32412   356 E OneSignal:     at com.onesignal.core.internal.operations.impl.OperationRepo.processQueueForever(OperationRepo.kt:176)
10-30 15:31:15.408 32412   356 E OneSignal:     at com.onesignal.core.internal.operations.impl.OperationRepo.access$processQueueForever(OperationRepo.kt:25)
10-30 15:31:15.408 32412   356 E OneSignal:     at com.onesignal.core.internal.operations.impl.OperationRepo$processQueueForever$1.invokeSuspend(Unknown Source:14)
10-30 15:31:15.408 32412   356 E OneSignal:     at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
10-30 15:31:15.408 32412   356 E OneSignal:     at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:234)
10-30 15:31:15.408 32412   356 E OneSignal:     at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:166)
10-30 15:31:15.408 32412   356 E OneSignal:     at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:397)
10-30 15:31:15.408 32412   356 E OneSignal:     at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl(CancellableContinuationImpl.kt:431)
10-30 15:31:15.408 32412   356 E OneSignal:     at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$default(CancellableContinuationImpl.kt:420)
10-30 15:31:15.408 32412   356 E OneSignal:     at kotlinx.coroutines.CancellableContinuationImpl.resumeUndispatched(CancellableContinuationImpl.kt:518)
10-30 15:31:15.408 32412   356 E OneSignal:     at kotlinx.coroutines.ResumeUndispatchedRunnable.run(Executors.kt:186)
10-30 15:31:15.408 32412   356 E OneSignal:     at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:487)
10-30 15:31:15.408 32412   356 E OneSignal:     at java.util.concurrent.FutureTask.run(FutureTask.java:264)
10-30 15:31:15.408 32412   356 E OneSignal:     at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:307)
10-30 15:31:15.408 32412   356 E OneSignal:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
10-30 15:31:15.408 32412   356 E OneSignal:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
10-30 15:31:15.408 32412   356 E OneSignal:     at java.lang.Thread.run(Thread.java:1012)
10-30 15:31:15.410 32412   493 E OneSignal: Could not login user
10-30 15:31:15.611 32412   356 D OneSignal: [OpRepo] processQueueForever:ops:
10-30 15:31:15.611 32412   356 D OneSignal: null

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

5 participants