Search code examples
imagexamarinxamarin.formsxamarin.androidxamarin.ios

Xamarin Forms save image from an url into device's gallery


I am working on Xamarin Forms (with iOS and Android). What I want to do is to allow users to download image from an url by using DependencyService. I tried run in IOS emulator and the image did save into the emulator but does not show up in the gallery. Appreciate help in that and following is my code:

In ViewModel:

public void DownloadImage()
{
    IFileService fileSvc = DependencyService.Get<IFileService>();

    WebClient wc = new WebClient();
    byte[] bytes = wc.DownloadData(ImgUrl);
    Stream stream = new MemoryStream(bytes);

    fileSvc.SavePicture(DateTime.Now.ToString(), stream, "temp");
}

In Xamarin.iOS

public void SavePicture(string name, Stream data, string location = "temp")
{
    var documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
    string imageFilename = Path.Combine(documentsPath, "Images", location);
    Directory.CreateDirectory(imageFilename);

    string filePath = Path.Combine(documentsPath, name);

    byte[] bArray = new byte[data.Length];
    using (FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate))
    {
        using (data)
        {
            data.Read(bArray, 0, (int)data.Length);
        }
        int length = bArray.Length;
        fs.Write(bArray, 0, length);
    }
}

In Xamarin.Droid

public void SavePicture(string name, Stream data, string location = "temp")
{
    var documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
    documentsPath = Path.Combine(documentsPath, "Images", location);
    Directory.CreateDirectory(documentsPath);

    string filePath = Path.Combine(documentsPath, name);

    byte[] bArray = new byte[data.Length];
    using (FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate))
    {
        using (data)
        {
            data.Read(bArray, 0, (int)data.Length);
        }
        int length = bArray.Length;
        fs.Write(bArray, 0, length);
    }
}

Solution

  • If you Want to save image into Gallery, please follow the code below.

    Firstly, create Create the IMediaService Interface in PCL.

    public interface IMediaService
    {
        void SaveImageFromByte(byte[] imageByte,string filename);
    }
    

    Then implement this interface in Platform-specific Xamarin.Android Project

    public  class MediaService : IMediaService
    {
        Context CurrentContext => CrossCurrentActivity.Current.Activity;
        public void SaveImageFromByte(byte[] imageByte, string filename)
        {
            try
            {
                Java.IO.File storagePath = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryPictures);
                string path = System.IO.Path.Combine(storagePath.ToString(), filename);
                System.IO.File.WriteAllBytes(path, imageByte);
                var mediaScanIntent = new Intent(Intent.ActionMediaScannerScanFile);
                mediaScanIntent.SetData(Android.Net.Uri.FromFile(new Java.IO.File(path)));
                CurrentContext.SendBroadcast(mediaScanIntent);
            }
            catch (Exception ex)
            {
    
            }
        }
    }
    

    implement this interface in Platform-specific Xamarin.iOS Project

    public class MediaService : IMediaService
    {
        public void SaveImageFromByte(byte[] imageByte,string fileName)
        {
            var imageData = new UIImage(NSData.FromArray(imageByte));
            imageData.SaveToPhotosAlbum((image, error) =>
            {
                //you can retrieve the saved UI Image as well if needed using  
                //var i = image as UIImage;  
                if (error != null)
                {
                    Console.WriteLine(error.ToString());
                }
            });
        }
    }
    

    For accessing the CurrentContext Install the NuGet Package (Plugin.CurrentActivity) from NuGet Package Manager, also check for the external storage permission.