Xamarin Essentials MediaPicker 无法在 iOS 上运行

问题描述 投票:0回答:4

我在 Xamarin Forms 5 应用程序上使用 Xamarin Essentials MediaPicker (v1.7.3),它只是冻结并最终导致 iOS 上的应用程序崩溃,但在 Android 上运行得非常好。

我的应用程序使用

MVVM
模式,因此我有一个
ImageButton
连接到我的视图模型中的方法,该方法的代码如下所示:

async Task Add_Image_Tapped()
{
   try
   {
      var photosPermission = await Permissions.CheckStatusAsync<Permissions.Photos>();
      var cameraPermission = await Permissions.CheckStatusAsync<Permissions.Camera>();

      if (photosPermission != PermissionStatus.Granted || photosPermission != PermissionStatus.Restricted)
         photosPermission = await Permissions.RequestAsync<Permissions.Photos>();

      if (cameraPermission != PermissionStatus.Granted || cameraPermission != PermissionStatus.Restricted)
         cameraPermission = await Permissions.RequestAsync<Permissions.Camera>();

      if ((photosPermission == PermissionStatus.Granted
         || photosPermission == PermissionStatus.Restricted)
         && (cameraPermission == PermissionStatus.Granted
         || cameraPermission == PermissionStatus.Restricted))
         await HandleImagePicker();
   }
   catch(Exception e)
   {
      throw new Exception(e.Message);
   }
}

如果权限检查正常,下面是处理图像拾取的方法:

private async Task HandleImagePicker()
{
   try
   {
      var filePath = string.Empty;
      var fileName = string.Empty;

      MainThread.BeginInvokeOnMainThread(() => {

         var result = MediaPicker.PickPhotoAsync(new MediaPickerOptions
         {
            Title = "Pick Image"
         }).Result;

         if (result == null)
            return;

         filePath = result.FullPath;
         fileName = result.FileName;

      });

      if (!string.IsNullOrEmpty(filePath) && !string.IsNullOrEmpty(fileName))
      {
         // Do something with the image
      }
   }
   catch(Exception e)
   {
      throw new Exception(e.Message);
   }
}

我正在使用

Xamarin Forms 5.0.0.2401
Xamarin Community Toolkit 2.0.2
Xamarin Essentials 1.7.3
。我的
Info.plist
中还具有以下权限:

<key>NSCameraUsageDescription</key>
<string>MyApp would like to access your camera</string>
<key>NSMicrophoneUsageDescription</key>
<string>MyApp would like to access your microphone</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>MyApp would like to access your photo library</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>MyApp would like to access your photo library</string>

我还在

AppDelegate
FinishedLaunching()
方法中初始化Xamarin Essentials,如下所示:

Xamarin.Essentials.Platform.Init(() => new UIViewController());

知道这里可能有什么问题吗?

更新:

上面的代码反映了我根据使用主线程等建议进行更改后的当前代码。

目前,如果我在 Mac 上的 iOS 模拟器上运行该应用程序,它实际上会永远挂起。永远不会引发异常或崩溃。

如果我在真实设备(即 iPhone Xs)上运行它,它会挂起相当长一段时间并最终使整个应用程序崩溃。

如前所述,它在 Android 上运行得非常好。

ios xamarin xamarin.forms xamarin-essentials
4个回答
2
投票

这里有一些建议

  1. 尝试将方法签名恢复为原始签名。

    private async void Image_Picker_Tapped(object sender, EventArgs e){}
    
  2. Try Catch
    包裹你的代码,看看是否有错误信息。

  3. 调用时请勿设置任何参数

    PickPhotoAsync
    .

    var result = await MediaPicker.PickPhotoAsync();
    
  4. 尝试在致电

    await Task.Delay(100)
    之前添加
    PickPhotoAsync


0
投票

您能否说明如何请求用户访问设备存储的权限。

建议 - 添加一种检查方法,用于每次尝试访问设备存储时进行权限检查。您可以使用 Permissions.CrossPermissions 插件。

它的示例看起来像 -

async Task Image_Picker_Tapped()
{
   if (await GetPhotoLibraryPermission())
   {
      var result = await MediaPicker.PickPhotoAsync(new MediaPickerOptions
      {
         Title = "Pick Image"
      };
   }
   // Handle the image
}
private async Task<bool> GetPhotoLibraryPermission()
        {
            PermissionStatus cameraPermissionStatus = await CrossPermissions.Current.CheckPermissionStatusAsync<CameraPermission>();
            if (cameraPermissionStatus != PermissionStatus.Granted)
            {
                cameraPermissionStatus = await CrossPermissions.Current.RequestPermissionAsync<CameraPermission>();
            }
            var storagePermissionStatus = await CrossPermissions.Current.RequestPermissionAsync<StoragePermission>();
            if (storagePermissionStatus != PermissionStatus.Granted)
            {
                storagePermissionStatus = await CrossPermissions.Current.RequestPermissionAsync<StoragePermission>();
            }
            return cameraPermissionStatus == PermissionStatus.Granted && storagePermissionStatus == PermissionStatus.Granted;
        }

0
投票

将 PickPhotoAsync 与

await
一起使用非常重要。

此代码可能将您原来的挂起换成了不同的挂起:

 var result = MediaPicker.PickPhotoAsync(new MediaPickerOptions
 {
    Title = "Pick Image"
 }).Result;

您需要切换到主线程启动一个

async
上下文。
鉴于您已经在
async
方法中,请使用较新的 MainThread 方法
InvokeOnMainThreadAsync
。并在调用中添加
async

// Have "await" and "async" here.
await Device.InvokeOnMainThreadAsync(async () => {
    ...
    // HAVE "await" here.
    var result = await MediaPicker.PickPhotoAsync(new MediaPickerOptions
    {
        Title = "Pick Image"
    });   // DON'T use ".Result".

await/async
,否
.Result


如果仍然挂起,请创建一个公共 github 存储库,其中包含一个显示挂起的简单项目,可以构建和运行该项目。


0
投票

由于完全相同的问题,我遇到了这个问题。问题出在这一行

Xamarin.Essentials.Platform.Init(() => new UIViewController());

删除它。

我添加它是为了解决另一个问题,并记得我何时看到有关它的行。删除它,解决了我的问题。

© www.soinside.com 2019 - 2024. All rights reserved.