【问题标题】:How do i request permissions when not on the UI thread?不在 UI 线程上时如何请求权限?
【发布时间】:2020-04-16 14:24:21
【问题描述】:

我目前使用的是最新版本的 Xamarin.Forms (4.5.0.617) 和 Xamarin.Essentials (1.5.2)。

我有一个依赖注入服务,它负责访问电话联系人,它实际上是 Xamarin.Essentials 权限代码的包装器。我需要保证代码在 UI 线程上执行以避免异常。我已经了解了以下代码,但是,它并没有像我预期的那样工作。在我的应用程序中,权限弹出窗口出现并为我提供了允许/拒绝选项,但是 RequestAsync 之后的所有代码都无法执行,就像从未正式返回响应一样。下次我运行该应用程序时,它会立即运行(因此推测后台的权限已正确记录)。

public async Task<bool> RequestAccessPhoneContacts()
{
    PermissionStatus status = PermissionStatus.Denied;

    status = await MainThread.InvokeOnMainThreadAsync<PermissionStatus>(async () =>
    {
        return await Permissions.RequestAsync<Permissions.ContactsRead>();
    });

    return (status == PermissionStatus.Granted);
}

我不确定我尝试将代码强制到 UI 线程上的方式是否引起了问题,或者我是否错误地使用了异步代码......或者(最不可能)它是否是Xamarin.Essentials 权限代码中的错误。我目前只在 Android 上看到过这种行为,但我还没有在其他任何人上测试过。

任何帮助都非常感谢:)

谢谢!

【问题讨论】:

  • 我认为您不需要在 MainThread 中调用 RequestAsync。你有什么例外?
  • 这是我收到的异常 - Xamarin.Essentials.PermissionException: '必须在主线程上调用权限请求。' {Xamarin.Essentials.PermissionException:必须在主线程上调用权限请求。在 Xamarin.Essentials.Permissions+BasePlatformPermission.RequestAsync () [0x0020d] 在 d:\a\1\s\Xamarin.Essentials\Permissions\Permissions.android.cs:118 }

标签: android xamarin.forms xamarin.essentials


【解决方案1】:

原来我在设置时没有正确遵循文档。

将其添加到我的主要活动中后,一切都恢复了生机。

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

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

此信息来自我在 Xamarin.Essentials github 上提出的一个错误 - https://github.com/xamarin/Essentials/issues/1227

【讨论】:

  • 你可以标记这个答案,这将帮助更多有同样问题的人:)。
  • 对不起,这对我不起作用。默认 Xamarin 应用程序模板已在 MainActivity.cs 中包含此 OnRequestPermissionsResult() 方法,但这根本没有帮助。 :-(
【解决方案2】:

当我使用 Xamarin.Essentials 调用当前位置时,我遇到了类似的问题。我得到了这个例外:

Xamarin.Essentials.PermissionException: '必须在主线程上调用权限请求。'

&this帮我解决了。

  1. 从主线程调用当前位置

     private Task<Location> GetLastKnownLocation()
     {
         var locationTaskCompletionSource = new TaskCompletionSource<Location>();
    
         Device.BeginInvokeOnMainThread(async () =>
         {
             locationTaskCompletionSource.SetResult(await Geolocation.GetLastKnownLocationAsync());
         });
    
         return locationTaskCompletionSource.Task;
     }
    
  2. 并在 Try catch 块中调用上述方法并使用 configure await false

     private async Task ExecuteGetGeoLocationCommand()
     {
         try
         {
             var location = await GetLastKnownLocation().ConfigureAwait(false);
    
         }
         catch (FeatureNotSupportedException fnsEx) {} 
         catch (Exception ex){}
     }
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-11
    • 2015-11-24
    • 2017-03-01
    • 2022-01-16
    • 1970-01-01
    相关资源
    最近更新 更多