Taking a Screenshot in Xamarin.Forms

There may be a few occasions when you want to take a screenshot of your app, such as for sending to support. Xamarin.Forms doesn’t have this functionality; hence we will have to create a custom renderer for iOS and Android to capture the screen.

Interface and Dependency Injection

If we want to use this in our class library, we will need to create an interface to use, then use DependencyService or another IoC framework. If you are using a Shared project, you won’t need this. See Dependency Injection, if you require more information on this pattern.

public interface IScreenshotService
{
    byte[] Capture();
}

Android

Place this code, in your Android project.

public namespace MyMobileApp
{
    public class ScreenshotService : IScreenshotService
    {
        private readonly Activity _currentActivity;
        public void SetActivity(Activity activity) => _currentActivity = activity;

        public byte[] Capture()
        {
            var rootView = _currentActivity.Window.DecorView.RootView;

            using (var screenshot = Bitmap.CreateBitmap(
                                    rootView.Width,
                                    rootView.Height,
                                    Bitmap.Config.Argb8888))
            {
                var canvas = new Canvas(screenshot);
                rootView.Draw(canvas);

                using (var stream = new MemoryStream())
                {
                    screenshot.Compress(Bitmap.CompressFormat.Png, 90, stream);
                    return stream.ToArray();
                }
            }
        }
    }
}

In your MainActivity.cs, add in the following code to register your service. In here, we need to pass through the current activity.

DependencyService.Register<ScreenshotService>();

DependencyService.Get<ScreenshotService>().SetActivity(this);

iOS

Place this code in your iOS project.

[assembly: Dependency(typeof(ScreenshotService))]
public namespace MyMobileApp 
{
    public class ScreenshotService : IScreenshotService
    {
        public byte[] Capture()
        {
            var capture = UIScreen.MainScreen.Capture();
            using (NSData data = capture.AsPNG())
            {
                var bytes = new byte[data.Length];
                Marshal.Copy(data.Bytes, bytes, 0, Convert.ToInt32(data.Length));
                return bytes;
            }
        }
    }
}

Usage

Now you can use this service anywhere in your app. Simply use this code to get an instant screenshot of your app.

var screenshotData = DependencyService.Get<IScreenshotService>().Capture();

You can then either save this to file storage, which you can see in the second section of the Configuration Files instructions.

If you want to display the screenshot, you can assign it to a property in your ViewModel.

private byte[] _image;
public byte[] Image
{
    get => _image;
    set
    {
        _image = value;
       OnPropertyChanged(); // Or whatever MVVM framework method you might use.
    }
}

 

Then use a ByteToImageConverter.

public class BytesToImageConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null)
            return null;

        return ImageSource.FromStream(() => new MemoryStream((byte[])value));
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => throw new NotImplementedException();
}

To finally display your image in XAML, add the converter to your resource dictionary.

<ContentPage.Resources>
    <ResourceDictionary>
        <converters:BytesToImageConverter x:Key="BytesToImage" />
    </ResourceDictionary>
</ContentPage.Resources>

Then use with an image, bound to your ViewModel property.

<Image Source="{Binding Image, Converter={StaticResource BytesToImage}}" Aspect="AspectFill" />


XAMARIN WEEKLY NEWSLETTER

Subscribe to a hand-picked round up of the best Xamarin development links every week. Published every Friday. Free.

Signup to Weekly Xamarin

* I do not maintain or run this newsletter, but I do recommend it.

Related Posts

Microsoft MVP | Xamarin MVP | Xamarin Forms Developer | Build Flutter

2 Comments

  1. Wally McClure

    Great. Always love these little items. Been doing the screenshot thing within an app for a while, but I just love these little explanations. Keep it up!

    Wally

  2. Andrew Herrick

    Appreciate these kind of posts as well! Keep them rolling little nuggets of Forms goodness!