Save a picture from camera to device gallery using Xamarin.Essentials 1.7 Media Picker and Xamarin Forms?

AG 521 Reputation points
2021-08-29T08:13:22.093+00:00

Hi,

how to save a picture from camera to device gallery using Xamarin.Essentials 1.7 Media Picker and Xamarin Forms for Android 11 and iOS camera roll?

The only two options I have found are FileSystem.AppDataDirectory and FileSystem.CacheDirectory

Thanks,
AG

Developer technologies | .NET | Xamarin
{count} votes

3 answers

Sort by: Most helpful
  1. JarvanZhang 23,971 Reputation points
    2021-08-30T07:04:29.413+00:00

    Hello @AG ,​

    Welcome to our Microsoft Q&A platform!

    how to save a picture from camera to device gallery using Xamarin.Essentials 1.7 Media Picker

    Xamarin.Essentials.MediaPicker doesn't provide the function to save the captured phto to the gallery.

    For this function, please try to save the file on each platform. Then call the function code in the shared project using DependencyService. Here is sample code, you could refer to:

       private async void Button_Clicked(object sender, EventArgs e)  
       {  
           var photo = await MediaPicker.CapturePhotoAsync();  
           var stream = await photo.OpenReadAsync();  
         
           MemoryStream ms = new MemoryStream();  
           stream.CopyTo(ms);  
           var bytes = ms.ToArray();  
         
           DependencyService.Get<ITestInterface>().StorePhotoToGallery(bytes, "test.png");  
       }  
         
       //platform implementation  
       [assembly: Xamarin.Forms.Dependency(typeof(TestImplementation))]  
       namespace TestApplication_5.Droid  
       {  
           public class TestImplementation : ITestInterface  
           {  
               public async void storePhotoToGallery(byte[] bytes, string fileName)  
               {  
                   Context context = MainActivity.Instance;  
                   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, bytes);  
                       var mediaScanIntent = new Intent(Intent.ActionMediaScannerScanFile);  
                       mediaScanIntent.SetData(Android.Net.Uri.FromFile(new Java.IO.File(path)));  
                       context.SendBroadcast(mediaScanIntent);  
                   }  
                   catch (Exception ex)  
                   {  
                   }  
               }  
           }  
       }  
    

    For the iOS implementation, you could refer to: https://stackoverflow.com/a/60630182/11083277

    You could also MediaPlugin instead. It provides the SaveToAlbum option when taking the new photo.

       var file = await CrossMedia.Current.TakePhotoAsync(new StoreCameraMediaOptions  
       {  
           SaveToAlbum = true  
       });  
    

    Best Regards,

    Jarvan Zhang


    If the response is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    2 people found this answer helpful.

  2. AG 521 Reputation points
    2021-09-08T08:17:31.903+00:00

    Hi @JarvanZhang

    I have created a test Solution name SaveImageToGallery and in SaveImageToGallery.Android I have created an interface

    public interface ISaveToGallery  
    {  
        void storePhotoToGallery(byte[] bytes, string fileName);  
    }  
    

    I have created a SaveToGallery class that inherits the interface

    public class SaveToGallery : ISaveToGallery  
    {  
        public async void storePhotoToGallery(byte[] bytes, string fileName)  
        {  
            Context context = MainActivity.Instance;  
            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, bytes);  
                var mediaScanIntent = new Intent(Intent.ActionMediaScannerScanFile);  
                mediaScanIntent.SetData(Android.Net.Uri.FromFile(new Java.IO.File(path)));  
                context.SendBroadcast(mediaScanIntent);  
            }  
            catch (Exception ex)  
            {  
            }  
        }  
    }  
    

    I am receiving an error "'MainActivity' does not contain a definition for 'Instance'" for the line "Context context = MainActivity.Instance;"

    For the line "Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryPictures)" I am receiving the warning "'Environment.GetExternalStoragePublicDirectory(string?)' is obsolete: 'deprecated'

    For the line Intent.ActionMediaScannerScanFile I am receiving the warning "'Intent.ActionMediaScannerScanFile' is obsolete: 'deprecated'"

    For iOS, I would like to use Xamarin.Essentials 1.7 Media Picker and not CrossMedia from https://github.com/jamesmontemagno/MediaPlugin as it is obsolete and not maintain anymore.

    Regards,
    AG

    0 comments No comments

  3. JarvanZhang 23,971 Reputation points
    2021-09-08T09:55:52.643+00:00

    I am receiving an error "'MainActivity' does not contain a definition for 'Instance'" for the line "Context context = MainActivity.Instance

    I created a static instance in the MainActivity class like below.

    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
        public static MainActivity Instance { get; set; }
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            Instance = this;
            ...
            LoadApplication(new App());
        }
    }
    

    I am receiving the warning "'Intent.ActionMediaScannerScanFile' is obsolete: 'deprecated'"

    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, bytes);
    MediaScannerConnection.ScanFile(Android.App.Application.Context, new string[] { path }, null, null);
    

    I am receiving the warning "'Environment.GetExternalStoragePublicDirectory(string?)' is obsolete: 'deprecated

    This method is deprecated on Android 10, try using ContentResolver to store the image on Android 10 instead. Here is a similar thread using native code, you could refer to:
    https://stackoverflow.com/a/63777157/11083277


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.