Как мне запросить разрешения, когда я не в потоке пользовательского интерфейса?

В настоящее время я использую последнюю версию Xamarin.Forms (4.5.0.617) и Xamarin.Essentials (1.5.2).

У меня есть внедренная служба зависимости, которая отвечает за доступ к телефонным контактам, она фактически является оболочкой для кода разрешений Xamarin.Essentials. Мне нужно гарантировать, что код выполняется в потоке пользовательского интерфейса, чтобы избежать исключений. Я дошел до приведенного ниже кода, однако он не работает так, как я ожидал. В моем приложении появляется всплывающее окно с разрешениями и предлагает мне выбор разрешить / запретить, но затем весь код после того, как 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);
}

Я не уверен, вызвал ли я проблему с тем, как я пытаюсь принудительно вставить код в поток пользовательского интерфейса, или я неправильно использую асинхронный код ... или (что менее вероятно), это ошибка в код разрешений Xamarin.Essentials. На данный момент я видел такое поведение только на Android, но не тестировал его ни на одном другом.

Любая помощь очень ценится :)

Благодарность!


person Brooky    schedule 16.04.2020    source источник
comment
Я не думаю, что вам нужно вызывать RequestAsync в MainThread. Какие исключения бывают?   -  person Jack Hua    schedule 17.04.2020
comment
Это полученное мной исключение - Xamarin.Essentials.PermissionException: «Запрос разрешения должен быть вызван в основном потоке». {Xamarin.Essentials.PermissionException: запрос разрешения должен быть вызван в основном потоке. в Xamarin.Essentials.Permissions + BasePlatformPermission.RequestAsync () [0x0020d] в d: \ a \ 1 \ s \ Xamarin.Essentials \ Permissions \ Permissions.android.cs: 118}   -  person Brooky    schedule 17.04.2020


Ответы (2)


Оказывается, я не следил должным образом за документацией при настройке.

После добавления этого в мою основную деятельность все возвращается к жизни.

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);
}

Эта информация появилась из-за того, что я поднял ошибку на github Xamarin.Essentials - https://github.com/xamarin/Essentials/issues/1227

person Brooky    schedule 17.04.2020
comment
Вы можете отметить этот ответ, который поможет большему количеству людей с той же проблемой :). - person Jack Hua; 20.04.2020
comment
Извините, у меня это не работает. Шаблон приложения Xamarin по умолчанию уже содержит этот метод OnRequestPermissionsResult () в MainActivity.cs, но это совсем не помогает. :-( - person dmitry_bond; 23.07.2020

У меня была аналогичная проблема, когда я позвонил в текущее местоположение с помощью Xamarin.Essentials. У меня такое исключение:

Xamarin.Essentials.PermissionException: «Запрос разрешения должен быть вызван в основном потоке».

& это помогло мне решить.

  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){}
     }
    
person Shameem    schedule 10.07.2021