来自 Xamarin Forms 的 Geolocation GetLastKnownLocationAsync() 权限异常 - 调用失败并且没有权限提示

Geolocation GetLastKnownLocationAsync() permission exception from Xamarin Forms - call fails and no permission prompt

GetLocationAsync 在我的 Xamarin.Forms 应用上失败。

我有最新的 Xamarin.Essentials nuget 包。

我已经在 info.plist 中设置了必要的权限。

从我的 ViewModel 调用它。

调用超级简单:

var location = await Geolocation.GetLastKnownLocationAsync();

但它既失败又未能提示用户权限对话框,即使我的 info.plist 已正确设置: NSLocationWhenInUseUsageDescription 插入原因

我问和回答这个问题是因为它让人头疼,而且我不确定要搜索什么或问题是什么。

我的各种搜索指出了许多相关问题,但没有真正解决主要问题。

我得到的最接近的实际上是 Essentials github 页面上的这个问题: https://github.com/xamarin/Essentials/issues/634

这个答案的灵感来自 Xamarin/Azure 布道者 Brandon Minnick --> 看看他的项目,他在其中处理类似情况 code:

那么我们可以从上面得到什么?如果您查看上下文,他会以 MVVM 样式将他的视图与他的 ViewModel 连接起来。但是,各种库要求从主线程调用某些方法。这就是问题的本质,这就是这段代码可以解决的问题。

因此,为了采用上述代码解决问题中提到的地理定位问题,我做了以下操作:

Task<Xamarin.Essentials.Location> GetLocationFromPhone()
{

    var locationTaskCompletionSource = new TaskCompletionSource<Xamarin.Essentials.Location>();

    Device.BeginInvokeOnMainThread(async () =>
    {
        locationTaskCompletionSource.SetResult(await Geolocation.GetLastKnownLocationAsync());
    });

    return locationTaskCompletionSource.Task;
}

我在任务中使用我的 ViewModel 中的上述内容。类似于以下内容。

async Task ExecuteGetGeoLocationCommand()
{
    try
    {
        var locationFromPhone = await GetLocationFromPhone().ConfigureAwait(false);

        if (locationFromPhone is null)
            return;

        _location = locationFromPhone;

        if (_location != null)
        {
            Console.WriteLine($"Latitude: {_location.Latitude}, Longitude {_location.Longitude}, Altitude: {_location.Altitude}");
        } 
        else
        {
            Console.WriteLine($"Exiting geolocation");
        }
        catch (FeatureNotSupportedException fnsEx)
        {
        }
        catch (Exception ex)
        {
        }
    }
}

希望对其他人有所帮助!

如果您正在使用 Xamarin.Essentials 并且系统没有提示您在 Android 上获得许可,请确保您已将所有必要的代码添加到 Android 主 Activity.

详情见https://docs.microsoft.com/en-us/xamarin/essentials/get-started?tabs=windows%2Candroid

来自文档:

protected override void OnCreate(Bundle savedInstanceState) {
    //...
    base.OnCreate(savedInstanceState);
    Xamarin.Essentials.Platform.Init(this, savedInstanceState); // add this line to your code, it may also be called: bundle
    //...

public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
    Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);

    base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}