Skip to content
This repository has been archived by the owner on Apr 3, 2023. It is now read-only.

RequestPermissionsAsync call fails on the first install #93

Closed
rizamarhaban opened this issue Apr 20, 2018 · 3 comments
Closed

RequestPermissionsAsync call fails on the first install #93

rizamarhaban opened this issue Apr 20, 2018 · 3 comments

Comments

@rizamarhaban
Copy link

ISSUE

public async Task<...some message wrapper...> CheckLocationAccessPermissions()
{
    var status = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Location);
    if (status != PermissionStatus.Granted)
    {
        if (await CrossPermissions.Current.ShouldShowRequestPermissionRationaleAsync(Permission.Location))
        {
            return // ... some message...;
        }

        // This line never success executing and not continuing, its just jump out from this method
        var results = await CrossPermissions.Current.RequestPermissionsAsync(Permission.Location);
        // never reach this code below
        if (results.ContainsKey(Permission.Location)) status = results[Permission.Location];
    }

    if (status == PermissionStatus.Granted)
    {
        if (!CrossGeolocator.IsSupported) return //... some message...;
    }
    else if (status != PermissionStatus.Unknown)
    {
        if (status == PermissionStatus.Denied) return //... some message if denied...;

        return //... some message...;
    }
}

Every time the code reaches,

    var status = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Location);

It just jump out from the method and did not continue method execution. The dialog manage to be opened, but when we select When In Use, Don't Allow, it never return any results or continue the method.

HOWEVER, once the app is closed and start again. The,

    var status = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Location);

returns the correct value. So, the bug behavior only happen on the first clean install of the app.

Info.plist

    <key>NSLocationWhenInUseUsageDescription</key>
    <string>This app needs access location when open.</string>

No background location updates.

Bug Information

Version Number of Plugin: 4.2.0
Device Tested On: iPhone 6S
Simulator Tested On: iPhone X (Simulator)
Version of VS: 2017 (15.6.3)
Version of Xamarin: 4.9.0.752, Xamarin.iOS SDK 11.8.1.28
Versions of other things you are using:

Steps to reproduce the Behavior

  1. Delete the app from device.
  2. Clean build the app.
  3. Deploy or Debug the app.
  4. Execute the CheckLocationAccessPermissions() method.

Expected Behavior

Should return back to the method

Actual Behavior

Jumps out from the method and there are no return back to the method.

@rizamarhaban
Copy link
Author

rizamarhaban commented Apr 23, 2018

This might help for someone facing this issue.

After doing some hacking, we finally have this solution with the help from @Xamariners. This is NOT a solution but is just a work around for iOS. You might want to use Device.RuntimePlatform == Device.iOS for this workaround, although it also probably works on Android. Enjoy!

PermissionStatus status = PermissionStatus.Unknown;

var result = await RetryHelpers.Retry(async () =>
{
    IPermissions permission = CrossPermissions.Current;
    status = await permission.CheckPermissionStatusAsync(Permission.Location);
    if (status != PermissionStatus.Granted)
    {
        var results = await permission.RequestPermissionsAsync(Permission.Location);

        //Best practice to always check that the key exists
        if (results.ContainsKey(Permission.Location))
            status = results[Permission.Location];
    }

    return status == PermissionStatus.Granted;

}, 5000, 3);

if (result)
    { /* yay...!!! do stuff here... like get location... */ }

Where RetryHelpers.Retry(...) is this,

public static class RetryHelpers
{
    public static async Task<bool> Retry(Func<Task<bool>> action, int interval, int retryCount = 3)
    {
        bool flag = false;
        List<Exception> source = new List<Exception>();
        TimeSpan delay = TimeSpan.FromMilliseconds((double)interval);
        for (int index = 0; index < retryCount; ++index)
        {
            try
            {
                flag = await action();
                if (flag)
                    return true;
                Task.Delay(delay).Wait();
            }
            catch (Exception ex)
            {
                if (source.All<Exception>((Func<Exception, bool>)(x => x.Message != ex.Message)))
                    source.Add(ex);
                Task.Delay(delay).Wait();
            }
        }
        if (!flag && !source.Any<Exception>())
            return false;
        if (source.Count<Exception>() == 1)
            throw source[0];
        if (source.Count<Exception>() > 1)
            throw new AggregateException((IEnumerable<Exception>)source);
        return flag;
    }
}

@thargan
Copy link

thargan commented Jun 3, 2018

I have this issue in the latest code in Android

@brep
Copy link

brep commented Jan 22, 2021

This issue is still affecting us on iOS even with the posted workaround

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants