2

I've looked at and tested extensively as this post. Below is the code for a screenshot button on PCL.

async void OnScreenshotButtonClicked(object sender, EventArgs args) {
    var imageSender = (Image)sender;
    var ScreenShot = DependencyService.Get<IScreenshotManager>().CaptureAsync();
    await DisplayAlert("Image Saved", "The image has been saved to your device's picture album.", "OK");
}

So my question is how to turn byte[] into an image and save it to a device...
For the life of me, I cannot figure out a way to save the image to the device. Any help would be greatly appreciated!!! Thanks!

Anas Alweish
  • 2,818
  • 4
  • 30
  • 44
  • instead of returning a byte[] from your DependencyService, just modify the code to do a File.WriteAllBytes() instead, and return the file path to the caller – Jason Apr 14 '17 at 01:23
  • The blog post link in this question is broken. Here is the [updated blog post link](https://danielhindrikes.se/index.php/2015/02/26/building-a-screenshotmanager-to-capture-the-screen-with-code/). – Chris Simeone Jan 27 '20 at 16:37

1 Answers1

0

Like Jason mentioned in the comments you can extend your code in the platform project by adding a File.WriteAllBytes(); line and save your file from right there.

Or you can decouple it and create another DependencyService. For instance create the IScreenshotService like: DependencyService.Get<IScreenshotService>().SaveScreenshot("MyScreenshot123", ScreenShot);

And create implementations like this:

PCL

public interface IScreenshotService
{
    SaveScreenshot(string filename, byte[] imageBytes);`
}

iOS

[assembly: Xamarin.Forms.Dependency(typeof(ScreenshotService_iOS))]
 
namespace YourApp.iOS
{
    public class ScreenshotService_iOS: IScreenshotService
    {
        public void SaveScreenshot(string filename, byte[] imageBytes)
        {
            var screenshot = new UIImage(NSData.FromArray(imageBytes));

            screenshot.SaveToPhotosAlbum((image, error) =>
            {
                // Catch any error here
                if(error != null)
                    Console.WriteLine(error.ToString());

                // If you want you can access the image here from the image parameter
            });
        }
    }
}

Android

[assembly: Xamarin.Forms.Dependency(typeof(Picture_Droid))]
 
namespace YourApp.Droid
{
    public class ScreenshotService_Android : IScreenshotService
    {
        public void SaveScreenshot(string filename, byte[] imageBytes)
        {
            var dir = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDcim);
            
            var pictures = dir.AbsolutePath;
            
            // You might want to add a unique id like GUID or timestamp to the filename, else you could be overwriting an older image

            string filePath = System.IO.Path.Combine(pictures, filename);

            try
            {
                // Write the image
                File.WriteAllBytes(filePath, imageData);

                // With this we add the image to the image library on the device
                var mediaScanIntent = new Intent(Intent.ActionMediaScannerScanFile);

                mediaScanIntent.SetData(Uri.FromFile(new File(filePath)));
                Xamarin.Forms.Forms.Context.SendBroadcast(mediaScanIntent);
            }
            catch(Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
    }
}

Don't forget to add the appropriate permissions on the Android app (probably WRITE_EXTERNAL_STORAGE is enough)

Lastly you could look at third-party libraries like Splat for example.

Gerald Versluis
  • 30,492
  • 6
  • 73
  • 100
  • Forgive me for being so blatant, but how do I extend my code in the platform project by adding a File.WriteAllBytes(); line and save my file from right there? –  Apr 14 '17 at 16:32
  • Basically you just take the code from the answer and incorporate it in the code you have now – Gerald Versluis Apr 14 '17 at 16:39
  • The compiler does not recognize 'File'.WriteAllBytes(); even with using System.IO; statement at the top –  Apr 14 '17 at 17:45
  • Did you also try `System.IO.File.WriteAllBytes`? There might be another `File` object in another namespace already. – Gerald Versluis Apr 15 '17 at 08:58
  • @GeraldVersluis can you co-operate me to figure out this issue https://stackoverflow.com/questions/54860385 – A.Goutam Mar 04 '19 at 11:32