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

Issue

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.

Answered By – Cherry Bu – MSFT

Leave a Comment