繁体   English   中英

如何从 Xamarin Forms 中的图库中 select 多张图片并保存到所需的文件路径?

[英]How to select multiple images from gallery in Xamarin Forms and save to desired file path?

我有以下代码来打开图库。

var imageIntent = new Intent(
Intent.ActionPick);
imageIntent.SetType("image/*");
mageIntent.PutExtra(Intent.ExtraAllowMultiple, true);
imageIntent.SetAction(Intent.ActionGetContent);
StartActivityForResult(
Intent.CreateChooser(imageIntent, "Select photo"), 1);

我坚持使用以下代码,即 MainActivity.cs 中的 OnActivityResult

protected override void OnActivityResult(int requestCode, Android.App.Result resultCode, Intent data)
    {
        base.OnActivityResult(requestCode, resultCode, data);

        if((requestCode==1)&&(resultCode==Result.Ok))
        {
            if(data!=null)
            {
                ClipData clipData = data.ClipData;
                if(clipData!=null)
                {
                    for (int i = 0; i < clipData.ItemCount; i++)
                    {
                        ClipData.Item item = clipData.GetItemAt(i);
                        Android.Net.Uri selectedImage = item.Uri;

                        //How to convert Android.Net.Uri to a image file?


                    }
                }
            }
        }
    }

Android.Net.Uri 是我以前从未见过的,路径就像content/android/document/documents/31857。 是的,我可以从画廊 select 多张照片,但我只是不知道如何将 Android.Net.Uri 转换为合法的图像文件? 我的最终目标是将所选图像保存到我想要的文件路径,如 storage/emulated/0... 或者有没有更好的方法来 select 多个图像并保存到所需的文件? 谢谢你。

您可以使用依赖服务

在表单中创建界面

namespace xxx
{
    public interface IPhotoPickerService
    {
        Task<Dictionary<string,Stream>> GetImageStreamAsync();
    }
}

在 iOS 中

[assembly: Dependency (typeof (PhotoPickerService))]
namespace xxx.iOS
{
    public class PhotoPickerService : IPhotoPickerService
    {
        TaskCompletionSource<Dictionary<string, Stream>> taskCompletionSource;
        UIImagePickerController imagePicker;

        Task<Dictionary<string, Stream>> IPhotoPickerService.GetImageStreamAsync()
        {
            // Create and define UIImagePickerController
            imagePicker = new UIImagePickerController
            {
                SourceType = UIImagePickerControllerSourceType.PhotoLibrary,
                MediaTypes = UIImagePickerController.AvailableMediaTypes(UIImagePickerControllerSourceType.PhotoLibrary)
            };

            // Set event handlers
            imagePicker.FinishedPickingMedia += OnImagePickerFinishedPickingMedia;
            imagePicker.Canceled += OnImagePickerCancelled;

            // Present UIImagePickerController;
            UIWindow window = UIApplication.SharedApplication.KeyWindow;
            var viewController = window.RootViewController;
            viewController.PresentModalViewController(imagePicker, true);

            // Return Task object
            taskCompletionSource = new TaskCompletionSource<Dictionary<string, Stream>>();
            return taskCompletionSource.Task;
        }

       

        void OnImagePickerFinishedPickingMedia(object sender, UIImagePickerMediaPickedEventArgs args)
        {
            UIImage image = args.EditedImage ?? args.OriginalImage;

            if (image != null)
            {
                // Convert UIImage to .NET Stream object
                NSData data;
                if (args.ReferenceUrl.PathExtension.Equals("PNG") || args.ReferenceUrl.PathExtension.Equals("png"))
                {
                    data = image.AsPNG();
                }
                else
                {
                    data = image.AsJPEG(1);
                }
                Stream stream = data.AsStream();

                UnregisterEventHandlers();

                Dictionary<string, Stream> dic = new Dictionary<string, Stream>();
                dic.Add(args.ImageUrl.ToString(), stream);

                // Set the Stream as the completion of the Task
                taskCompletionSource.SetResult(dic);
            }
            else
            {
                UnregisterEventHandlers();
                taskCompletionSource.SetResult(null);
            }
            imagePicker.DismissModalViewController(true);
        }

        void OnImagePickerCancelled(object sender, EventArgs args)
        {
            UnregisterEventHandlers();
            taskCompletionSource.SetResult(null);
            imagePicker.DismissModalViewController(true);
        }

        void UnregisterEventHandlers()
        {
            imagePicker.FinishedPickingMedia -= OnImagePickerFinishedPickingMedia;
            imagePicker.Canceled -= OnImagePickerCancelled;
        }

        
    }
}

在安卓中

在主活动中

public class MainActivity : FormsAppCompatActivity
{
    ...
    // Field, property, and method for Picture Picker
    public static readonly int PickImageId = 1000;

    public TaskCompletionSource<Dictionary<string,Stream>> PickImageTaskCompletionSource { set; get; }

    protected override void OnActivityResult(int requestCode, Result resultCode, Intent intent)
    {
        base.OnActivityResult(requestCode, resultCode, intent);

        if (requestCode == PickImageId)
        {
            if ((resultCode == Result.Ok) && (intent != null))
            {
                Android.Net.Uri uri = intent.Data;
                Stream stream = ContentResolver.OpenInputStream(uri);

                Dictionary<string, Stream> dic = new Dictionary<string, Stream>();
                dic.Add(uri.ToString(), stream);
                // Set the Stream as the completion of the Task
                PickImageTaskCompletionSource.SetResult(dic);
            }
            else
            {
                PickImageTaskCompletionSource.SetResult(null);
            }
        }
    }
}
[assembly: Dependency(typeof(PhotoPickerService))]
namespace xxx.Droid
{
    public class PhotoPickerService : IPhotoPickerService
    {
        public Task<Dictionary<string,Stream>> GetImageStreamAsync()
        {
            // Define the Intent for getting images
            Intent intent = new Intent();
            intent.SetType("image/*");
            intent.SetAction(Intent.ActionGetContent);

            // Start the picture-picker activity (resumes in MainActivity.cs)
            MainActivity.Instance.StartActivityForResult(
                Intent.CreateChooser(intent, "Select Picture"),
                MainActivity.PickImageId);

            // Save the TaskCompletionSource object as a MainActivity property
            MainActivity.Instance.PickImageTaskCompletionSource = new TaskCompletionSource<Dictionary<string,Stream>>();

            // Return Task object
            return MainActivity.Instance.PickImageTaskCompletionSource.Task;
        }
    }
}

调用它

Dictionary<string, Stream> dic = await DependencyService.Get<IPhotoPickerService>().GetImageStreamAsync();

Stream stream;
string path;

foreach ( KeyValuePair<string, Stream> currentImage in dic )
{
   stream = currentImage.Value;

   // save it    

}

谢谢你的帮助。 以下是我为需要帮助的人提供的最终解决方案。

private string GetPathToImage(Android.Net.Uri uri)
    {
        string doc_id = "";
        using (var c1 = ContentResolver.Query(uri, null, null, null, null))
        {
            c1.MoveToFirst();
            string document_id = c1.GetString(0);
            doc_id = document_id.Substring(document_id.LastIndexOf(":") + 1);
        }

        string path = null;

        // The projection contains the columns we want to return in our query.
        string selection = Android.Provider.MediaStore.Images.Media.InterfaceConsts.Id + " =? ";
        using (var cursor = ContentResolver.Query(Android.Provider.MediaStore.Images.Media.ExternalContentUri, null, selection, new string[] { doc_id }, null))
        {
            if (cursor == null) return path;
            var columnIndex = cursor.GetColumnIndexOrThrow(Android.Provider.MediaStore.Images.Media.InterfaceConsts.Data);
            cursor.MoveToFirst();
            path = cursor.GetString(columnIndex);
        }
        return path;
    }

之后就可以为所欲为了,加油! 取自: 获取图库图像 Xamarin 的路径?

下面是从 Xamarin 中的图库中选取多张照片的 iOS 实现。作为调用 Task<List<byte[]>> PickPhotos() 的结果,您将获得字节 arrays 的列表。 Android 实现在 Montemagno 的跨媒体插件中运行良好,但 iOS 存在问题。 这应该解决它。 我正在使用新的 PHPickerViewController 来完成这项工作。 还包括一个本机图像大小调整器例程,以在需要时缩小照片的尺寸。

    public class PhotoService 
{
    public override async Task<List<byte[]>> PickPhotos()
    {
        var imagePicker = new PHPickerViewController(new PHPickerConfiguration
        {
            Filter = PHPickerFilter.ImagesFilter,
            SelectionLimit = 50,
        });
        var window = UIApplication.SharedApplication.KeyWindow;
        var vc = window.RootViewController;
        while (vc.PresentedViewController != null)
        {
            vc = vc.PresentedViewController;
        }
        var tcs = new TaskCompletionSource<Task<List<byte[]>>>();

        imagePicker.Delegate = new PPD
        {
            CompletedHandler = res => tcs.TrySetResult(PickerResultsToMediaFile(res))
        };
        await vc.PresentViewControllerAsync(imagePicker, true);
        var resultTask = await tcs.Task;
        var result = await resultTask;
        await vc.DismissViewControllerAsync(true);
        imagePicker?.Dispose();
        return result;
    }

    private async Task<List<byte[]>> PickerResultsToMediaFile(PHPickerResult[] res)
    {
        var results = new List<byte[]>();
        var tcs = new TaskCompletionSource<NSObject>();
        foreach (var item in res)
        {
            try
            {
                var provider = item.ItemProvider;
                var suggestedName = provider.SuggestedName;
                var identifiers = provider?.RegisteredTypeIdentifiers;

                var identifier = (identifiers?.Any(i => i.StartsWith(UTType.LivePhoto)) ?? false)
                    && (identifiers?.Contains(UTType.JPEG) ?? false)
                    ? identifiers?.FirstOrDefault(i => i == UTType.JPEG)
                    : identifiers?.FirstOrDefault();
                if (string.IsNullOrWhiteSpace(identifier))
                    continue;
                var fileName = $"{provider?.SuggestedName}.{GetTag(identifier, UTType.TagClassFilenameExtension)}";
                var stream = (await provider.LoadDataRepresentationAsync(identifier))?.AsStream();
                byte[] bytes;
                using (MemoryStream ms = new MemoryStream())
                {
                    stream.CopyTo(ms);
                    bytes = ms.ToArray();
                }
                results.Add(bytes);
            }
            catch(Exception)
            {
                continue;
            }
        }
        return results;
    }
public override byte[] ResizeImage(byte[] imageData)
    {
        float width, height;
        UIImage originalImage = ImageFromByteArray(imageData);
        if (originalImage == null)
        {
            return imageData;
        }
        UIImageOrientation orientation = originalImage.Orientation;

        if (originalImage.Size.Width > originalImage.Size.Height)
        {
            if (originalImage.Size.Width > 1920)
            {
                width = 1920;
                height = 1920 * (float)originalImage.Size.Height / (float)originalImage.Size.Width;
            }
            else
            {
                width = (float)originalImage.Size.Width;
                height = (float)originalImage.Size.Height;
            }
        }
        else
        {
            if (originalImage.Size.Height > 1920)
            {
                height = 1920;
                width = 1920 * (float)originalImage.Size.Width / (float)originalImage.Size.Height;
            }
            else
            {
                width = (float)originalImage.Size.Width;
                height = (float)originalImage.Size.Height;
            }
        }

        //create a 24bit RGB image
        using (CGBitmapContext context = new CGBitmapContext(IntPtr.Zero,
                                             (int)width, (int)height, 8,
                                             4 * (int)width, CGColorSpace.CreateDeviceRGB(),
                                             CGImageAlphaInfo.PremultipliedFirst))
        {

            RectangleF imageRect = new RectangleF(0, 0, width, height);

            // draw the image
            context.DrawImage(imageRect, originalImage.CGImage);

            UIImage resizedImage = UIImage.FromImage(context.ToImage(), 0, orientation);

            // save the image as a jpeg
            return resizedImage.AsJPEG().ToArray();
        }
    }
    public UIImage ImageFromByteArray(byte[] data)
    {
        if (data == null)
        {
            return null;
        }

        UIImage image;
        try
        {
            image = new UIImage(Foundation.NSData.FromArray(data));
        }
        catch (Exception e)
        {
            Console.WriteLine("Image load failed: " + e.Message);
            return null;
        }
        return image;
    }
    protected internal static string GetTag(string identifier, string tagClass)
        => UTType.CopyAllTags(identifier, tagClass)?.FirstOrDefault();
}
class PPD : PHPickerViewControllerDelegate
{
    public Action<PHPickerResult[]> CompletedHandler { get; set; }

    public override void DidFinishPicking(PHPickerViewController picker, PHPickerResult[] results) =>
        CompletedHandler?.Invoke(results?.Length > 0 ? results : null);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM