react-native-background-geolocation icon indicating copy to clipboard operation
react-native-background-geolocation copied to clipboard

iOS Location Permission Modal Pops Async to sdk start utility

Open GuptaAman08 opened this issue 1 year ago • 6 comments

Your Environment

  • Plugin version: 4.13.1
  • Platform: iOS
  • OS version: iOS 17.4
  • Device manufacturer / model: iOS Phone
  • React Native version (react-native -v): 0.71.18
  • Plugin config
{
      distanceFilter: 50,
      stopOnTerminate: true,
      startOnBoot: false,
      stopTimeout: 20,
      enableHeadless: false,
      heartbeatInterval: 60,
      locationAuthorizationRequest: 'WhenInUse',
      disableMotionActivityUpdates: false,
      extras: {},
      url: <server_url>,
      authorization: <function_that_returns_auth_token>,
      autoSync: true
}

Expected Behavior

Actually, i have a doubt related to iOS behaviour of this sdk. When the code execution control arrives at line that has code - await <your_sdk>.start(), a location permission modal pops up. From here I see different behaviours in Android vs iOS

  1. In case of Android, the control stops at that line unless some location permission is selected on that modal. Post that execution control will move to the next line
  2. In case of iOS, the execution control doesn't stops at that line and wait for the user/customer to enter some location permission on that modal. Rather thats something async in case of iOS, because of which the execution moves ahead and completed my function in which your SDK's start utility was called.

Actual Behavior

I am not sure, is that the right behaviour ???

Steps to Reproduce

  1. Start metro server and run an iOS build (react-native run-ios)
  2. Initialise the SDK by calling its ready method
  3. Ensure the you have some console.log after the line await <your_sdk>.start() in the function (suppose start_tracking) from where you will start the location tracking
  4. Call start_tracking and now observe that even though you dont select any permission on that location permission modal the function start_tracking will finish its execution. This is not the case in Android

GuptaAman08 avatar Aug 22 '24 06:08 GuptaAman08

@christocracy any answer ?? I am patiently waiting for last 3 days for this. can you help here please !!

GuptaAman08 avatar Aug 26 '24 12:08 GuptaAman08

Is there a problem?

iOS and Android operate differently.

christocracy avatar Aug 26 '24 12:08 christocracy

We were performing some action in the catch block. Since, in case of android we were getting error which is not the case in Iphone

GuptaAman08 avatar Aug 26 '24 12:08 GuptaAman08

What error?

christocracy avatar Aug 26 '24 12:08 christocracy

When you choose to Deny, location permission, in case of Android, the sdk throws error, which is not the case in iOS. For more description you can refer the Expected Behaviour section of the ticket

GuptaAman08 avatar Aug 26 '24 13:08 GuptaAman08

You should handle permission issues in .onProviderChange event.

christocracy avatar Aug 26 '24 13:08 christocracy

@christocracy sorry for reviving this, but I have basically the same issue. It would be good to have a consistent behaviour between the platforms (ability to use await to wait for the user response, not just the dialog opening), but it seems this is not being considered. So might I ask if it's possible to at least get an event to listen for when the user denies the "Always" option? To be clear: the user gives the "WhenInUse" permission, then does not grant "Always". I would like to do something when they finish giving/denying permissions, but the await does not work like that on ios and there's no event (that I'm aware of) that is triggered when the user denies "Always", so I basically have no way to do what I'd want to do.

As a side note: I noticed the sdk itself will try to get a location after .ready and fail immediately unless the user gives permissions in a couple of seconds.

ItaGuy avatar Sep 24 '24 13:09 ItaGuy

Have you read the APIs docs .onProviderChange, as I mentioned above? https://github.com/transistorsoft/react-native-background-geolocation/issues/2122#issuecomment-2310210177

christocracy avatar Sep 24 '24 13:09 christocracy

@christocracy thanks for the quick reply. Yes I did, however that event does not react to the user dismissing the dialog requesting "Always" (at least on ios). It does react to the user not giving "WhenInUse", but it's not really enough to cover all the user interactions. Users might click the wrong option by mistake (already happened even in internal testing) and not being able to react to that interaction is a hard limit for how the app can be aware of the user actions. As of now the only solution is start reacting when either they give or deny the "WhenInUse", but that still leads to errors in the location service and forces the app to act on a possibly incomplete state, because we have no way to know if the user will give or deny the "Always" permission (when they give it it's fine, but because there's no event for the dismiss we have no way to know if they have the dialog still open or closed it, forcing us to rely on "WhenInUse").

ItaGuy avatar Sep 24 '24 13:09 ItaGuy

If you more fine-grained permission management, I suggest you use a 3rd party plug-in specializing in permissions, such as react-native-permissions.

christocracy avatar Sep 24 '24 13:09 christocracy

will look into that, thanks. I get that this library will not consider implementing such functionalities right? Does this mean there's no way for a PR to add/extend the permissions management on ios to be considered and merged? With this I mean a PR either aligning the current Android and iOS behaviour, by making the await reliable to wait for the user response on the permissions dialogs OR extend one of the available events to react to the user dismissing the "Always" permission, so that the permission requests cycle is complete.

ItaGuy avatar Sep 24 '24 14:09 ItaGuy

Does this mean there's no way for a PR to add/extend the permissions management on ios to be considered and merged?

That's correct. You don't have access to the native source code.

christocracy avatar Sep 24 '24 14:09 christocracy

hey @christocracy, just wanted to report that the method requestPermission seems to be indeed reliable to wait for the user interactions, even though it is advised against as permissions are requested by default from methods that need location. It honestly seems odd, I would expect .start to also wait for the permission request (if not completed yet, eg: first start) before returning. I guess my problem is solved like that, but maybe the plugin does have the needed functionalities to align Android and iOS? I suppose (from what I read) that Android does indeed start the plugin but waits for the permission request to be consumed first, while iOS does not (it's very clear when calling .start and .onLocation fires an error while the "WhenInUse" dialog is still open), even though it seems to be possible to do so before tracking. Anyway thanks for your attention, I will be using .requestPermission for a more consistent experience for now, I hope it won't get deprecated.

ItaGuy avatar Sep 25 '24 14:09 ItaGuy