我在 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 上运行得非常好。
这里有一些建议
尝试将方法签名恢复为原始签名。
private async void Image_Picker_Tapped(object sender, EventArgs e){}
用
Try Catch
包裹你的代码,看看是否有错误信息。
调用时请勿设置任何参数
PickPhotoAsync
.
var result = await MediaPicker.PickPhotoAsync();
尝试在致电
await Task.Delay(100)
之前添加 PickPhotoAsync
。
您能否说明如何请求用户访问设备存储的权限。
建议 - 添加一种检查方法,用于每次尝试访问设备存储时进行权限检查。您可以使用 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;
}
将 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 存储库,其中包含一个显示挂起的简单项目,可以构建和运行该项目。
由于完全相同的问题,我遇到了这个问题。问题出在这一行
Xamarin.Essentials.Platform.Init(() => new UIViewController());
删除它。
我添加它是为了解决另一个问题,并记得我何时看到有关它的行。删除它,解决了我的问题。