如何在显示 Xaml 中设置的地图之前请求位置权限。 Xamarin.Forms
How to Request Location permission before showing map set up in Xaml. Xamarin.Forms
我最近在 Xamarin.forms 中将 sdk 级别更新为 6.0。
我使用 Xaml 在页面上放置地图。因为我更新到 6.0 权限需要显示地图。我现在的问题是我不知道如何在应用程序尝试显示地图之前请求显示地图的权限。结果我得到了一个未处理的异常。
public MapPage()
{
Init();
InitializeComponent();
azureService = AzureService.defaultManager;
}
private async Task Init()
{
await RequestLocationPermission();
}
protected async override void OnAppearing()
{
base.OnAppearing();
MyMap.MoveToRegion(
MapSpan.FromCenterAndRadius(
new Position(0, 0),
Distance.FromMiles(10.0)));
}
private async Task RequestLocationPermission()
{
try
{
var status = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Location);
if (status != PermissionStatus.Granted)
{
if (await CrossPermissions.Current.ShouldShowRequestPermissionRationaleAsync(Permission.Location))
{
await DisplayAlert("Need location", "Gunna need that location", "OK");
}
var results = await CrossPermissions.Current.RequestPermissionsAsync(new[] { Permission.Location });
status = results[Permission.Location];
}
if (status == PermissionStatus.Granted)
{
}
else if (status != PermissionStatus.Unknown)
{
await DisplayAlert("Location Denied", "Can not continue, try again.", "OK");
}
}
catch (Exception ex)
{
}
}
如果地图是在 Xaml 中设置的,我如何在显示之前请求许可?
您的构造函数现在的设置方式是,您正在一个任务中启动权限请求,该任务将 运行 在一个单独的线程中。这意味着在用户授予权限之前 InitializeComponent() 可能 运行。问题是您不能使构造函数成为异步方法,因此没有简单的方法来解决这个问题。
为了不费力地完成这项工作,您可以将构造函数中的 InitializeComponent() 移动到 "if (status == PermissionStatus.Granted)" 块中。它可能看起来像这样:
if (status == PermissionStatus.Granted)
{
Device.BeginInvokeOnMainThread(() =>
{
InitializeComponent()
});
}
使用这种方法时,您必须小心在 OnAppearing() 中执行的操作,因为它可能会在 InitializeComponent() 之前被调用。如果此时您尝试访问任何 UI 组件,它将失败。
不过,我认为处理此问题的更好方法是将您的权限请求代码上移一级。换句话说,将它放在 class 中,您从中实例化此页面。然后,如果访问被授予,您可以显示此页面,或者如果访问被拒绝,则可以显示另一个没有地图的页面。这将带来更好的用户体验。
我最近在 Xamarin.forms 中将 sdk 级别更新为 6.0。 我使用 Xaml 在页面上放置地图。因为我更新到 6.0 权限需要显示地图。我现在的问题是我不知道如何在应用程序尝试显示地图之前请求显示地图的权限。结果我得到了一个未处理的异常。
public MapPage()
{
Init();
InitializeComponent();
azureService = AzureService.defaultManager;
}
private async Task Init()
{
await RequestLocationPermission();
}
protected async override void OnAppearing()
{
base.OnAppearing();
MyMap.MoveToRegion(
MapSpan.FromCenterAndRadius(
new Position(0, 0),
Distance.FromMiles(10.0)));
}
private async Task RequestLocationPermission()
{
try
{
var status = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Location);
if (status != PermissionStatus.Granted)
{
if (await CrossPermissions.Current.ShouldShowRequestPermissionRationaleAsync(Permission.Location))
{
await DisplayAlert("Need location", "Gunna need that location", "OK");
}
var results = await CrossPermissions.Current.RequestPermissionsAsync(new[] { Permission.Location });
status = results[Permission.Location];
}
if (status == PermissionStatus.Granted)
{
}
else if (status != PermissionStatus.Unknown)
{
await DisplayAlert("Location Denied", "Can not continue, try again.", "OK");
}
}
catch (Exception ex)
{
}
}
如果地图是在 Xaml 中设置的,我如何在显示之前请求许可?
您的构造函数现在的设置方式是,您正在一个任务中启动权限请求,该任务将 运行 在一个单独的线程中。这意味着在用户授予权限之前 InitializeComponent() 可能 运行。问题是您不能使构造函数成为异步方法,因此没有简单的方法来解决这个问题。
为了不费力地完成这项工作,您可以将构造函数中的 InitializeComponent() 移动到 "if (status == PermissionStatus.Granted)" 块中。它可能看起来像这样:
if (status == PermissionStatus.Granted)
{
Device.BeginInvokeOnMainThread(() =>
{
InitializeComponent()
});
}
使用这种方法时,您必须小心在 OnAppearing() 中执行的操作,因为它可能会在 InitializeComponent() 之前被调用。如果此时您尝试访问任何 UI 组件,它将失败。
不过,我认为处理此问题的更好方法是将您的权限请求代码上移一级。换句话说,将它放在 class 中,您从中实例化此页面。然后,如果访问被授予,您可以显示此页面,或者如果访问被拒绝,则可以显示另一个没有地图的页面。这将带来更好的用户体验。