android - Xamarin MediaPicker CapturePhotoAsync 在按下 "Ok"按钮后重新启动应用程序并抛出无提示错误

标签 android xamarin xamarin.forms

我在使用 XamarinEssentials.MediaPicker CapturePhotoAsync() 方法时遇到错误。我的应用程序的一些用户一直在经历无声崩溃,在接受拍摄的照片后,没有立即将任何内容记录到应用程序中心,而是重新启动应用程序。 (错误视频附在 here )。请注意,该视频是由持有小米红米 Note 9S 的用户拍摄的,我无权访问该设备。我无法在我测试过的任何设备上重现此错误。不处于开发模式或 Release模式。

显然这是 MediaPicker 代码内部的一些错误,消耗了设备的所有可用 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();
        }
    }

最佳答案

迄今为止,任何 Xamarin 照片捕捉库均未修复此错误。这是由于回调Task存储在内存中,因此当Android决定需要在相机应用程序位于前台时释放资源时,应用程序将关闭,并且回调将丢失。

当用户拍摄照片后,应用程序将恢复,但在 OnActivityResult 中无法回调代码来处理照片。目前看来没有任何方法可以处理这种情况。

关于android - Xamarin MediaPicker CapturePhotoAsync 在按下 "Ok"按钮后重新启动应用程序并抛出无提示错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69744468/

相关文章:

android - 前置摄像头 - 保存前正确镜像和旋转

java - OnClickListener 不适用于 ImageView

c# - 如何通过单击 Xamarin 4 中的 TableView 单元格打开 TableView

android - Xamarin——支持 9 补丁?

c# - Xamarin.Forms 不可点击的 ListView(移除选择涟漪效应)

c# - Android 按钮边框颜色渐变

android - 使用 Intent 通过 whatsapp 发送消息

android - 无法使用 IntelliJ IDEA 在 Android L 上访问 SQLite

ios - 上传录音到ftp

xaml - ScrollView 中的 Xamarin Center StackLayout