Closed darajava closed 3 months ago
I don't think this is a bug. It looks like it triggers another activity, thus causing the state to change, and then it returns to the Flutter activity, causing the state to change again. It all just happens really fast.
Potentially this could be avoided by checking the permission status before attempting to trigger the system permission dialog.
But why should it trigger another activity when nothing will show up to the user? A modal does not appear at all, and therefore it's not logical to expect a state change. (It's not logical to expect one even if a modal did show up, since it's an overlay. Apple does it this way). This caused a really bad and subtle bug for me, and I think there is no harm checking the permission in that function.
Before I go into this further, note that requestNotificationsPermission()
isn't a check but request. This is in response to what was mentioned in step 1 of the original message. To check, the method to use would be areNotificationsEnabled()
.
To summarise though, this isn't a bug with the plugin. Lifecycle changes happening are outside the control of the plugin. What the plugin does is calls native APIs of the platform and what happens afterwards is due to how the native platform behaves. Were you to write the Android code yourself via Java or Kotlin, you'll experience the same behaviour with activities being resumed. A comparison with iOS isn't apt either as they're different platforms with different behaviours. In saying that, I'm not sure what your point about Apple was when I've seen the resume lifecycle event fire after a selection is made through the iOS permission prompt.
This caused a really bad and subtle bug for me, and I think there is no harm checking the permission in that function.
When a user has denied permissions, it is actually possible for the dialog to be shown again that implementing this logic would prevent this from happening. This is covered in the official Android documentation and is where developers need to understand how the target platform behaves. This is a prerequisite before looking at this plugin even so that developers what can/can't be done for their app. Back the permissions prompt though, this can be seen this up to two times. That is, they can deny it once, be shown a prompt again and that's it. Implementing a check to avoid showing a prompt after it's been denied would prevent the ability to show the prompt again and go against the official best practices/recommendations. This excludes the check if permissions rationale can be optionally be shown (note: I believe the permission_handler
provides a way to check this if you need it
This also means the steps mentioned in the original post aren't necessarily correct. Given you hadn't mentioned the dialog in the original post, I suspect what you're actually referring to when the user has denied the permissions twice and tried to make a request again when it should be known at this point that it would not show a prompt at all. To my point earlier, the resume lifecycle event happening at this point is also consistent with what happens if you invoked the same logic via Java/Kotlin yourself. If you are indeed referring to the scenario where user has denied twice then that comes down to application-specific logic to handle this scenario much like how Android provides a workflow that is for applications to follow in the link shared earlier. In other words, similar to what @bleonard252 said, it sounds like your app is missing logic to avoid making requests again. The other thing to consider is if you have logic on the resume lifecycle event that is better placed elsewhere e.g. initState()
so it's only fired once. The last point may not be applicable but thought I'd mentioned
Describe the bug
To Reproduce 1) Check for notification permission on Android, where permission was already rejected.
requestNotificationsPermission
on Android returns false, a dialog does not show, but a state change is triggered.Observe trigger in following code:
Expected behavior It should not trigger a state change.
Sample code to reproduce the problem As above