maui icon indicating copy to clipboard operation
maui copied to clipboard

CaptureAsync() doesn't save Maps content

Open Davidoutz opened this issue 2 years ago • 12 comments

Description

When trying to capture the content of a map in a screenshot, the map output is transparent - despite the other elements being properly captured (buttons, etc.).

In Xamarin.Forms, I used to go with Map.TakeSnapshot() to achieve it.

image

Steps to Reproduce

From scratch:

  1. Create new .net MAUI app
  2. Add Microsoft.Maui.Controls.Maps package
  3. Setup Maps in MauiProgram.cs and AndroidManifest.xml
  4. Add a map element named "map" on a page (top half)
  5. Add an image named "screenshot" (bottom half)
  6. Add a button with a click event
  7. Set the click event content to
    private async void Button_Clicked(object sender, EventArgs e)
    {
        IScreenshotResult screen = await map.CaptureAsync();
        Stream stream = await screen.OpenReadAsync();
        var image = ImageSource.FromStream(() => stream);
        screenshot.Source = image;
    }
  1. Run the app and hit the button
  2. Expected result: The image "screenshot" should show the map Current result: Only the Google logo and the zoom buttons are shown, the map content being transparent (we can see the background)

From the existing repository

  1. Download repository
  2. Go to AndroidManifest and update the API Key with one of your own,
  3. Run the app and hit the "Take screenshot and see below" button
  4. See the image output

Link to public reproduction project repository

https://github.com/Davidoutz/MapsScreenshotBug

Version with bug

7.0 (current)

Last version that worked well

Unknown/Other

Affected platforms

Android, I was not able test on other platforms

Affected platform versions

Android 11

Did you find any workaround?

Not yet

Relevant log output

No response

Davidoutz avatar Jan 24 '23 09:01 Davidoutz

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

ghost avatar Jan 25 '23 19:01 ghost

Working on ios 16.2

Davidoutz avatar Jan 28 '23 00:01 Davidoutz

Verified this issue with Visual Studio Enterprise 17.7.0 Preview 2.0. Can repro on Android platform with sample project. https://github.com/Davidoutz/MapsScreenshotBug image

homeyf avatar Jul 11 '23 07:07 homeyf

So there is still no fix coming?

WoistdasNiveau avatar Aug 27 '23 17:08 WoistdasNiveau

need this too... Are there any known workarounds?

baaaaif avatar Sep 11 '23 15:09 baaaaif

Any solution for this problem

codeinapt avatar Dec 06 '23 15:12 codeinapt

Any update on this, still can't get this to work on Android

ajay-mundi avatar Jan 31 '24 15:01 ajay-mundi

Are athere any updates?

WoistdasNiveau avatar Mar 31 '24 15:03 WoistdasNiveau

bumping this because I need it working

SupermindPT avatar Apr 28 '24 22:04 SupermindPT

While you are waiting I would recommend you try out this library https://github.com/themronion/Maui.GoogleMaps. I am not 100% sure screenshotting works as I haven't tried it but as a whole it runs beautifully. I currently use the syncfusion maps library and I am able to screenshot that. Hoping to move over to the first library I suggested soon for all my mapping related functionality though.

ajay-mundi avatar Apr 28 '24 23:04 ajay-mundi

Actually I got it working

While you are waiting I would recommend you try out this library https://github.com/themronion/Maui.GoogleMaps. I am not 100% sure screenshotting works as I haven't tried it but as a whole it runs beautifully. I currently use the syncfusion maps library and I am able to screenshot that. Hoping to move over to the first library I suggested soon for all my mapping related functionality though.

That library does seem like it solves the problem.

After playing with the GoogleMaps view native code, I managed to get it working.

You just have to implement the ISnapshotReadyCallback interface and invoke _googleMap.Snapshot() to take a screenshot of the Google Maps view. Easy to implement.

EDIT: More information here: Capture screenshot of GoogleMap on Android API V2

SupermindPT avatar Apr 28 '24 23:04 SupermindPT

Solution I implemented to taking screenshots as described by @SupermindPT

Note that if you do not have a valid google maps api key, the TakeScreenShot function will hang.

#if ANDROID
using Android.Gms.Maps;
using Android.Graphics;
#endif

public class CustomMap : Microsoft.Maui.Controls.Maps.Map
{
#if ANDROID
    public Task<byte[]> TakeScreenShot()
    {
        var tcs = new TaskCompletionSource<byte[]>();
        
        GoogleMap NativeMap = ((MapHandler)this.Handler).Map as GoogleMap;
        NativeMap.Snapshot(new DelegateSnapshotReadyCallback(snapshot =>
        {
            var stream = new MemoryStream();
            snapshot.Compress(Bitmap.CompressFormat.Png, 0, stream);
            tcs.SetResult(stream.ToArray());
        }));

        return tcs.Task;
    }
#endif
}

#if ANDROID
    internal sealed class DelegateSnapshotReadyCallback : Java.Lang.Object, GoogleMap.ISnapshotReadyCallback
    {
        private readonly Action<Bitmap> _handler;

        public DelegateSnapshotReadyCallback(Action<Bitmap> handler)
        {
            _handler = handler;
        }

        public void OnSnapshotReady(Bitmap snapshot)
        {
            _handler?.Invoke(snapshot);
        }
    }
#endif

The map is then simply referenced in XAML, with the local namespace import not shown.

<local:CustomMap x:Name="map">
</local:CustomMap>

Gevand avatar May 24 '24 03:05 Gevand

I am having a problem with this method in two places, one with a map and the other with a SkiaSharp library. Confirming it is not just a map related issue. The problem is only on Android and the method seems to work as intended on iOS.

Android 14.0 API 34

SOMUCHDOG avatar Sep 04 '24 19:09 SOMUCHDOG