mapbox-unity-sdk
mapbox-unity-sdk copied to clipboard
[Android] DeviceLocationProvider FineLocation PermissionRequest will never finish on first startup
- Mapbox SDK version: 2.1.1
- Build-Target: Android (v11)
On the first clean launch of your android mapbox application using DeviceLocationProvider your app will never startup. You will have to grant finelocation-permission and afterwards kill the process/tab to restart the application with already given permission. This is caused by a while-loop in DevicelocationProvider which can't finish in any case.
Steps to reproduce:
- Uninstall app from device (or clean cache/AppData alternatively)
- Start the application
- You will be asked for fine location access permission
- Allow the permission
- Result --> Nothing will happen after step 4
Whats wrong ?
DeviceLocationProvider.cs
//request runtime fine location permission on Android if not yet allowed #if UNITY_ANDROID if (!_locationService.isEnabledByUser) { UniAndroidPermission.RequestPermission(AndroidPermission.ACCESS_FINE_LOCATION); //wait for user to allow or deny while (!_gotPermissionRequestResponse) { yield return _wait1sec; } } #endif
but how will _gotPermissionRequestResponse possibly set to true ?
thats defined at the following lines:
`#if UNITY_ANDROID private bool _gotPermissionRequestResponse = false;
private void OnAllow() { _gotPermissionRequestResponse = true; }
private void OnDeny() { _gotPermissionRequestResponse = true; }
private void OnDenyAndNeverAskAgain() { _gotPermissionRequestResponse = true; }
#endif`
Unfortunately these callbacks are never used by any caller.
I think the idea was using the following method signature for the request:
public static void RequestPermission(AndroidPermission permission, Action onAllow = null, Action onDeny = null, Action onDenyAndNeverAskAgain = null)
in this case above code would change to:
#if UNITY_ANDROID if (!_locationService.isEnabledByUser) { UniAndroidPermission.RequestPermission(AndroidPermission.ACCESS_FINE_LOCATION,OnAllow,OnDeny,OnDenyAndNeverAskAgain); //wait for user to allow or deny while (!_gotPermissionRequestResponse) { yield return _wait1sec; } } #endif
But even this will not work in my case on Android 11 -_-
At this point i stopped the investigation and implemented the permissionrequest using Unity's builtin class: https://docs.unity3d.com/ScriptReference/Android.Permission.RequestUserPermission.html
This needs to be called in front of starting LocationProvider manually (will start with awake call). By the way it would be really convient to have function like this for the LocationProvider:
- StartLocationProvider
- StopLocationProvider
- bool autoStart
otherwise you will have to control the initial start via the gameobjects activeState.
Here is the temporary solution for android permission until the fix the problem. Here is the updated DeviceLocationProvider script.
private void OnAllow(string permissionName) { _gotPermissionRequestResponse = true; } private void OnDeny(string permissionName) { _gotPermissionRequestResponse = true; } private void OnDenyAndNeverAskAgain(string permissionName) { _gotPermissionRequestResponse = true; }
#if UNITY_ANDROID
if (!_locationService.isEnabledByUser) {
var callback = new PermissionCallbacks();
callback.PermissionDenied += OnAllow;
callback.PermissionGranted += OnDeny;
callback.PermissionDeniedAndDontAskAgain += OnDenyAndNeverAskAgain;
Permission.RequestUserPermission(Permission.FineLocation, callback);
//wait for user to allow or deny
while (!_gotPermissionRequestResponse) { yield return _wait1sec; }
}
#endif
Thank you, Nemanja-95, your solution works like a charme!