Mapsui: Rotating a Forms map that contains a Pin crashes app

Created on 10 Mar 2019  路  16Comments  路  Source: Mapsui/Mapsui

Adding a single pin using code from PinSample.cs, the pin shows up on the map as expected. Zooming and panning the map works fine. But about 75% of the time, rotating the map hangs the app with very little interesting debug output (debug build). The other 25% of the time the map rotates around the pin as expected. Map rotation always works without the pin. Same behavior on Android and iOS. I'm rotating the map using touch, not programatically.

Position p = new Position(41.0f, -116.0f);
var pin = new Pin(mapView)
{
  Label = $"PinType.Pin {markerNum++}",
  Address = p.ToString(),
  Position = p,
  Type = PinType.Pin,
  Color = new Color(rnd.Next(0, 255) / 255.0, rnd.Next(0, 255) / 255.0, rnd.Next(0, 255) / 255.0),
  Transparency = 0.3f,
  Scale = rnd.Next(50, 130) / 100f
};
mapView.Pins.Add(pin);

Xamarin.Forms 3.5.0.129452
Mapsui.Forms v2.0.0-beta.22
Nokia 6.1 running Android 9
iPhone 6S running iOS 12.1.4

Debug output (Android):
at System.Threading.ThreadHelper.ThreadStart () [0x00014] in <58604b4522f748968296166e317b04b4>:0
at (wrapper runtime-invoke) object.runtime_invoke_void__this__ (object,intptr,intptr,intptr) [0x0004f] in <58604b4522f748968296166e317b04b4>:0

"Thread Pool Worker"
"Thread Pool Worker"
"Thread Pool Worker"
"Thread Pool Worker"
"Thread Pool Worker"
"Thread Pool Worker"
"Debugger agent"
"Thread Pool Worker"
"Thread Pool Worker"
"Thread Pool Worker"
"Finalizer"
""
"Thread Pool Worker"
"Thread Pool Worker"
"Thread Pool Worker"
Thread finished: #18
The thread 0x12 has exited with code 0 (0x0).
03-10 01:12:27.039 I/libc (29967): Requested dump for tid 29967 (ripping.CTForms)
Thread finished: #5
The thread 0x5 has exited with code 0 (0x0).

bug 馃悰 v2

All 16 comments

Thanks for the report.

You have this problem using code from the PinSample but you can not reproduce this problem with the PinSample itself, is that correct?

So, what is the difference between your project and the PinSample?

That's correct, I should have made that clear. First guess was a difference in component versions but ran into #630 so haven't finished that test. Will try your workaround but guessing now this isn't the issue. Maybe a difference in the way I've structured my app. Curious if anyone else has seen this behavior.

Ruled out component versions being the cause.

Found that if I double-tap anywhere on the map, subsequently rotating the map works 100% of the time. If I don't double-tap first, rotation always fails. The 25% success rate reported earlier could easily have been me tapping the screen for whatever reason. Sometimes it calms my nerves...

The Add Pin Sample is doing some things that I wasn't:

        public void Setup(IMapControl mapControl)
        {
            mapControl.Map = OsmSample.CreateMap();

            ((MapView)mapControl).UseDoubleTap = true;  // What does this do?
        }
        public static Map CreateMap()
        {
            var map = new Map
            {
                CRS = "EPSG:3857",
                Transformation = new MinimalTransformation()
            };
            return map;
        }

No change in behavior when I add these to my view's constructor:

            mapView.UseDoubleTap = true;
            mapView.Map.CRS = "EPSG:3857";
            mapView.Map.Transformation = new MinimalTransformation();

Guessing I'm just confused about the relationship between a mapControl and a mapView. My mapView is declared in XAML, I'm not explicitly creating a mapControl anywhere, and not sure I'd know what to do with it if I did.

First of all to the difference of MapControl and MapView. Mapsui has a MapControl object, which displays the Map on the screen. There are versions for Android, iOS, UWP, WPF and Xamarin.Forms. They all have the same functions on the different platforms. Or say better, they should. For Xamarin.Forms there is another object: MapView. It exposes bindings for properties, added WGS84 coordinates and has different predefined layers. It tries to mimic the Xamarin.Forms.Maps implementation. In the best case, it should be possible to replace a Xamarin.Forms.Maps code with Mapsui without changes.

Your question in the code:
((MapView)mapControl).UseDoubleTap = true; // What does this do?
For the Xamarin.Forms MapControl/MapView it is possible to decide, if you want to get events for a double tap or not. The reason is, that it makes all gesture events by its own. And if you want to detect double taps, you have to wait for some time after a first tap, if a second tap arrives or not. This makes the reactions of the component a little bit slow. So, if you don't want any double tap event, you could turn it off and have a faster reacting app.

For the bug, I have tried the "Add Pin Sample" on my Huawei P8 lite (2017) test device with Android 7.0 and haven't any problems. Turning the map around with 7 pins works perfect.

Thanks @charlenni for the background. That all makes sense to me so I'm still at a loss for an explanation for my problem. The sample app works fine for me too so I'm sure the problem is mine.

If I understand correctly, a mapView is all I should be dealing with in Xamarin.Forms; I don't need to instantiate a mapControl.

Does the fact that I can make it work by double-tapping the map before rotating it suggest anything to you? Seems like I'm missing something pretty fundamental...

Yes, it is correct, you don't need any MapControl for Xamarin.Forms. Btw. MapView have one.

Is it possible to see your code and perhaps test it?

Yes, I鈥檒l try to work up a sample that repros the problem.

Here's a project that repros the problem on Android: MapsuiFormsSample. It's based on the VS Master-Detail project template.
It doesn't repro on iOS, I think because for whatever reason the map doesn't rotate in this sample. Probably I'm not configuring it correctly. Pretty sure once the map is configured to rotate the problem will repro on iOS too.

It is the same problem as #606. Have to think about this.

Moved further discussion on Callouts to #635.

I will leave this open so we can test this once 606 is fixed.

You have this problem using code from the PinSample but you can not reproduce this problem with the PinSample itself, is that correct?

So, what is the difference between your project and the PinSample?

It looks like the difference between @klzig 's implementation and the PinSample is the same as in #606 : He is using a .net standard library instead of a shared code project.

This problem no longer repros for me on Android with 2.0.0-beta.24. However on iOS I get the following error when the map is shown, before a pin is added:

Unhandled Exception:
System.EntryPointNotFoundException: gr_context_make_gl occurred

I see the same behavior with a couple of (similar) apps, including MapsuiFormsSample.

Do you cleaned your builds (removed all old obj and bin folders of your whole project)?

That fixed it. I haven't had to remove the obj and bin folders in awhile...

This problem appears to be fixed! Will give another go at callouts next.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

othmaniav picture othmaniav  路  7Comments

ricardoboss picture ricardoboss  路  5Comments

kisslori picture kisslori  路  8Comments

lukaszpitulski picture lukaszpitulski  路  8Comments

lukaszpitulski picture lukaszpitulski  路  3Comments