LongHao Li
LongHao Li

Reputation: 35

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);
    }
}

Upvotes: 3

Views: 5066

Answers (1)

Cherry Bu - MSFT
Cherry Bu - MSFT

Reputation: 10346

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.

Upvotes: 3

Related Questions