我在使用XamarinEssentials时遇到错误。MediaPicker CapturePhotoAsync()方法。我的一个应用程序的一些用户已经经历了无声崩溃,在接受拍摄的图片后,没有向appCenter记录任何内容就重新启动了应用程序。(视频的错误attatched here)。请注意,这个视频是由一个用户采取的持有夏米Redmi Note 9 s和我没有访问这个设备。我无法在我测试过的任何设备上重现这个错误。既不是在开发模式下,也不是在发布版本中。
看起来是MediaPicker代码内部的一些bug消耗了设备的所有可用RAM,迫使它重新启动。
我在网上看过很多其他的报道,但他们中的任何一个都会得出结论或解决方案。
有人能帮我解决这个问题吗?
提前感谢!
查找下面的整个代码涉及捕捉图片,也后处理它,涉及调整图像大小,旋转它,保存到画廊,也保存一个缩略图。
public async Task TakePicture(object param)
{
var permissionsOk = await VerifyPermissions();
if (!permissionsOk) return;
try
{
var options = new MediaPickerOptions
{
};
var photo = await MediaPicker.CapturePhotoAsync();
await LoadPhotoAsync(photo);
Console.WriteLine($"CapturePhotoAsync COMPLETED: {PhotoPath}");
}
catch (FeatureNotSupportedException fnsEx)
{
// Feature is not supported on the device
var properties = new Dictionary<string, string>
{
{ "Função:", "TakePicture" },
{ "Arquivo:", "VisitDetailsRegistrationViewModel"},
{ "Observação", "FeatureNotSupportedException"}
};
Crashes.TrackError(fnsEx, properties);
}
catch (PermissionException pEx)
{
// Permissions not granted
var properties = new Dictionary<string, string>
{
{ "Função:", "TakePicture" },
{ "Arquivo:", "VisitDetailsRegistrationViewModel"},
{ "Observação", "PermissionException"}
};
Crashes.TrackError(pEx, properties);
}
catch (Exception ex)
{
var properties = new Dictionary<string, string>
{
{ "Função:", "TakePicture" },
{ "Arquivo:", "VisitDetailsRegistrationViewModel"},
{ "Observação", "Exception"}
};
Crashes.TrackError(ex, properties);
}
}
async Task LoadPhotoAsync(FileResult photo)
{
// canceled
if (photo == null)
{
PhotoPath = null;
return;
}
var meta = ImageMetadataReader.ReadMetadata(await photo.OpenReadAsync());
var subIfd0Directory = meta.OfType<ExifIfd0Directory>().FirstOrDefault();
var orientation = subIfd0Directory?.GetDescription(ExifDirectoryBase.TagOrientation);
var rotationAngle = GetRotationAngle(orientation);
// save the file into local storage
var newFile = System.IO.Path.Combine(FileSystem.CacheDirectory, photo.FileName);
using (var stream = await photo.OpenReadAsync())
{
var imageByteArray = ReadFully(stream);
//var resizedImageByteArray = ResizeImage(imageByteArray, 2000, 2000, 92);
var rotatedImageByteArray = RotateImage(imageByteArray, rotationAngle, 92);
//var mediaService = DependencyService.Get<IMediaService>();
//mediaService.SaveImageFromByte(rotatedImageByteArray, photo.FileName);
using (MemoryStream ms = new MemoryStream(rotatedImageByteArray))
{
using (var newStream = File.OpenWrite(newFile))
{
await ms.CopyToAsync(newStream);
}
}
using (MemoryStream ms2 = new MemoryStream(rotatedImageByteArray))
{
try
{
await MediaGallery.SaveAsync(MediaFileType.Image, ms2, photo.FileName);
}
catch (Exception ex)
{
var properties = new Dictionary<string, string>
{
{ "Função:", "LoadPhotoAsync" },
{ "Arquivo:", "VisitDetailsRegistrationViewModel"},
{ "Observação", "Exception"}
};
Crashes.TrackError(ex, properties);
}
}
}
PhotoPath = newFile;
var thumbFile = System.IO.Path.Combine(FileSystem.CacheDirectory, "Thumb-"+photo.FileName);
using (var stream = await photo.OpenReadAsync())
{
var thumbByteArray = ReadFully(stream);
var resizedThumbByteArray = ResizeImage(thumbByteArray, 500, 500, 92);
var rotatedThumbByteArray = RotateImage(resizedThumbByteArray, rotationAngle, 92);
using (MemoryStream ms = new MemoryStream(rotatedThumbByteArray))
{
using (var newStreamThumb = File.OpenWrite(thumbFile))
await ms.CopyToAsync(newStreamThumb);
}
}
ThumbPath = thumbFile;
}
public int GetRotationAngle(string orientationText)
{
if (orientationText == null) return 90;
if (orientationText.Contains("90")) return 90;
else if (orientationText.Contains("180")) return 180;
else if (orientationText.Contains("270")) return 270;
else return 0;
}
public static byte[] ReadFully(Stream input)
{
byte[] buffer = new byte[16 * 1024];
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
return ms.ToArray();
}
}
public static byte[] RotateImage(byte[] imageData, float degrees, int quality)
{
Bitmap originalImage = BitmapFactory.DecodeByteArray(imageData, 0, imageData.Length);
var matrix = new Matrix();
matrix.PostRotate(degrees);
Bitmap rotatedBitmap = Bitmap.CreateBitmap(originalImage, 0, 0, originalImage.Width, originalImage.Height, matrix, true);
using (MemoryStream ms = new MemoryStream())
{
rotatedBitmap.Compress(Bitmap.CompressFormat.Jpeg, quality, ms);
return ms.ToArray();
}
}
public static byte[] ResizeImage(byte[] imageData, float width, float height, int quality)
{
// Load the bitmap
Bitmap originalImage = BitmapFactory.DecodeByteArray(imageData, 0, imageData.Length);
float oldWidth = (float)originalImage.Width;
float oldHeight = (float)originalImage.Height;
float scaleFactor = 0f;
if (oldWidth > oldHeight)
{
scaleFactor = width / oldWidth;
}
else
{
scaleFactor = height / oldHeight;
}
float newHeight = oldHeight * scaleFactor;
float newWidth = oldWidth * scaleFactor;
Bitmap resizedImage = Bitmap.CreateScaledBitmap(originalImage, (int)newWidth, (int)newHeight, false);
using (MemoryStream ms = new MemoryStream())
{
resizedImage.Compress(Bitmap.CompressFormat.Jpeg, quality, ms);
return ms.ToArray();
}
}
1条答案
按热度按时间2hh7jdfx1#
到目前为止,此漏洞尚未在任何Xamarin照片捕获库中修复。这是由于回调任务存储在内存中,因此当Android决定在相机应用处于前台时需要释放资源时,应用将关闭,回调将丢失。
当用户拍摄完照片后,应用会被恢复,但在OnActivityResult中,没有办法回调代码来处理照片。目前似乎没有任何方法来处理这种情况。