Xamarin MediaPicker CapturePhotoAsync在按下“确定”按钮后重新启动应用程序并引发无声错误

5cg8jx4n  于 2022-12-07  发布在  其他
关注(0)|答案(1)|浏览(164)

我在使用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();
        }
    }
2hh7jdfx

2hh7jdfx1#

到目前为止,此漏洞尚未在任何Xamarin照片捕获库中修复。这是由于回调任务存储在内存中,因此当Android决定在相机应用处于前台时需要释放资源时,应用将关闭,回调将丢失。
当用户拍摄完照片后,应用会被恢复,但在OnActivityResult中,没有办法回调代码来处理照片。目前似乎没有任何方法来处理这种情况。

相关问题