Mapsui: No Tiles are drawn at all on Android

Created on 9 Mar 2017  路  20Comments  路  Source: Mapsui/Mapsui

A suspect is the use of BruTile 0.20.0.

It does not occur on every deploy. Sometimes no tiles are shown after deploy and it stays that way. Other times the tiles show right away and it stays that way.

We should check if reverting to BruTile 0.19.0 fixes this issue.

bug 馃悰

Most helpful comment

The problem comes with the change from SKCanvasView to ViewGroup as base class of MapControl for Android. I checked this by replacing the MapControl.cs with the old one (no other files are touched) and it works perfect. Map is displayed correct. Going back to new one (with ViewGroup) and the map vanished.

Than I changed MapControl.RefreshGraphics to

    public void RefreshGraphics()
    {
        PostInvalidate();
        _canvas.Invalidate();
    }

so it invalidates the SKCanvasView too. And now the map is drawn correct again.

It seems, that PostInvalidate doesn't invalidate the SKCanvasView too. And why this only occures with Xamarin.Forms :(

All 20 comments

This is the commit is suspect:
https://github.com/BruTile/BruTile/commit/b3d2d197106d1c019fea1131ff30b7a20978f8cb

Maybe we should use ConfigureAwait(true) instead of false.

I'm not sure, that this is the problem.

To test, I use the PolygonSample code. This should draw a OsmTileLayer and a PolygonLayer. The result is an empty view filled with BackColor and only the attribution. No polygon is drawn.

Btw. TileFetcher gets data back. So I don't assume, that BruTile is the problem here.

Yes, you could also check out this thread where they ran into the issue: https://github.com/pauldendulk/Mapsui/issues/141

The problem comes with the change from SKCanvasView to ViewGroup as base class of MapControl for Android. I checked this by replacing the MapControl.cs with the old one (no other files are touched) and it works perfect. Map is displayed correct. Going back to new one (with ViewGroup) and the map vanished.

Than I changed MapControl.RefreshGraphics to

    public void RefreshGraphics()
    {
        PostInvalidate();
        _canvas.Invalidate();
    }

so it invalidates the SKCanvasView too. And now the map is drawn correct again.

It seems, that PostInvalidate doesn't invalidate the SKCanvasView too. And why this only occures with Xamarin.Forms :(

Had to do this for dragging and zooming too. Ended up with calling RefreshGraphics there too. And changed RefreshGraphics to

    public void RefreshGraphics()
    {
        InvalidateChild(this);
        PostInvalidate();
    }

    void InvalidateChild(ViewGroup parent)
    {
        int count = parent.ChildCount;
        View child;
        for (int i = 0; i < count; i++)
        {
            child = parent.GetChildAt(i);
            if (child is ViewGroup)
                InvalidateChild((ViewGroup)child);
            else
                child.PostInvalidate();
        }
    }

so all childrens will be updated too. With this changes, it works perfect again.

Perhaps my issue is not related to yours. I get this exceptions which does indicate it is related to the new BruTile in my case:

 {System.FieldAccessException: Field `System.Net.HttpWebRequest:ResendContentFactory' is inaccessible from method `System.Net.Http.HttpClientHandler/<SendAsync>c__async0:MoveNext ()'

  at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[TResult].Start[TStateMachine] (TStateMachine& stateMachine) [0x00031] in /Users/builder/data/lanes/3511/501e63ce/source/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs:471 
  at System.Net.Http.HttpClientHandler.SendAsync (System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) [0x0001f] in <6e92ad09d0bd49b996fe288564eee203>:0 
  at System.Net.Http.HttpMessageInvoker.SendAsync (System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) [0x00000] in /Users/builder/data/lanes/3511/501e63ce/source/mono/mcs/class/System.Net.Http/System.Net.Http/HttpMessageInvoker.cs:68 
  at System.Net.Http.HttpClient.<SendAsync>__BaseCallProxy0 (System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) <0xae8f4208 + 0x00067> in <6e92ad09d0bd49b996fe288564eee203>:0 
  at System.Net.Http.HttpClient+<SendAsyncWorker>c__async0.MoveNext () [0x00071] in /Users/builder/data/lanes/3511/501e63ce/source/mono/mcs/class/System.Net.Http/System.Net.Http/HttpClient.cs:272 
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in /Users/builder/data/lanes/3511/501e63ce/source/mono/mcs/class/referencesource/mscorlib/system/runtime/exceptionservices/exceptionservicescommon.cs:143 
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x00047] in /Users/builder/data/lanes/3511/501e63ce/source/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:187 
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x0002e] in /Users/builder/data/lanes/3511/501e63ce/source/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:156 
  at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x0000b] in /Users/builder/data/lanes/3511/501e63ce/source/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:128 
  at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1+ConfiguredTaskAwaiter[TResult].GetResult () [0x00000] in /Users/builder/data/lanes/3511/501e63ce/source/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:535 
  at System.Net.Http.HttpClient+<GetByteArrayAsync>c__async2.MoveNext () [0x00027] in /Users/builder/data/lanes/3511/501e63ce/source/mono/mcs/class/System.Net.Http/System.Net.Http/HttpClient.cs:301 
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in /Users/builder/data/lanes/3511/501e63ce/source/mono/mcs/class/referencesource/mscorlib/system/runtime/exceptionservices/exceptionservicescommon.cs:143 
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x00047] in /Users/builder/data/lanes/3511/501e63ce/source/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:187 
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x0002e] in /Users/builder/data/lanes/3511/501e63ce/source/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:156 
  at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x0000b] in /Users/builder/data/lanes/3511/501e63ce/source/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:128 
  at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1+ConfiguredTaskAwaiter[TResult].GetResult () [0x00000] in /Users/builder/data/lanes/3511/501e63ce/source/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:535 
  at BruTile.Web.HttpTileProvider.FetchTile (System.Uri arg) [0x0001b] in <8143eb6173764aa989e23c5eee250845>:0 
  at BruTile.Web.HttpTileProvider.GetTile (BruTile.TileInfo tileInfo) [0x00029] in <8143eb6173764aa989e23c5eee250845>:0 
  at BruTile.Web.HttpTileSource.GetTile (BruTile.TileInfo tileInfo) [0x00000] in <8143eb6173764aa989e23c5eee250845>:0 
  at Mapsui.Fetcher.FetchOnThread.FetchTile () [0x00013] in C:\code\github\Mapsui\Mapsui\Fetcher\FetchOnThread.cs:45 }

Which seems related to this bug:
https://bugzilla.xamarin.com/show_bug.cgi?id=41133

Comment 53 mentions cycle 9. I did not have that yet. Downloading that now.
https://bugzilla.xamarin.com/show_bug.cgi?id=41133#c53

Tried 5 times before updating to cycle 9 and 4 out of 5 failed.
Tried 5 timer after the update, now 0 out of 5 fail.

41133 is also mentioned in the release notes. https://developer.xamarin.com/releases/android/xamarin.android_7/xamarin.android_7.1/ I think this one has caused a lot of obscure bugs for years.

This bug still seems to exist after updating Xamarin.Android to 7.1.0.41. The map works fine on UWP, but I'm having trouble getting the map to draw tiles on android. If I rotate the android tablet it forces a refresh and the tiles show up. I can zoom and pan but can't see the changes until I rotate the tablet causing a refresh.

I have tested adding the _canvas.Invalidate() call to MapControl.RefreshGraphics as charlenni suggested (and calling RefreshGraphics during pan/zoom operations). That does cause the tiles to be drawn, but it jitters too much on my tablet. I think there is a solution which will provide smoother results, but I haven't found it yet.

On my test device the tiles show directly and pan and zoom are smooth.

  • Did you test with the Mapsui sample or your own project? (could you try the Mapsui.Samples.Android please)
  • Did you delete all the bin and obj folders and do a clean build?
  • What kind of device are you using? Do you see the problem on other devices as well?

It was my own project, the sample works just fine.
I did delete the bin and obj folders, manually uninstall my old app, clean, and rebuild.
I have only tested on a Samsung tablet.

The primary thing I am doing different than the sample is Using Xamarin.Forms Renderers to make a PCL map control.

My project worked as a UWP app, but doesn't draw on Android. Since the Android sample is working with MBTiles I must have something wrong in my PCL/Xamarin.Forms Renderer code.

There is also an attempt at Xamarin.Forms by @tebben over here:
https://github.com/tebben/Mapsui/tree/XamarinForms
It is not a wrapper over the Mapsui controls but direct implementation using the SkiaSharp Forms component. It is noticeably slower on Android. Too slow for me.

Also interesting is this thread on Forms:
https://github.com/pauldendulk/Mapsui/issues/59

If I read MBTiles in your message: be carefull to use the right zoom factor, because MBTiles only contain special zoom levels and if you don't use this zoom levels, Mapsui dooesn't draw anything. Perhaps this is your problem.

Btw. normally Xamarin.Forms wrapper use the normal MapControl for this platform, nothing else. So, if your Mapsui.Sample.Android works, your Xamarin.Forms project should work too.

@charlenni. About the MBTiles zoom levels. The Schema of MbTilesTileSource (and any other ITileSource) should describe the content. So if you adjust the schema it should work for any MbTiles.

You need to next version of BruTile to be able to override the schema in the constructor because of this bug: https://github.com/BruTile/BruTile/issues/63

I have a fix for no tiles drawing on Android when using Xamarin Forms. It looks like there is a bug in Xamarin forms that keeps the MapControl from being drawn because it thinks there is nothing to draw.

To fix this I set a background color of transparent on the MapControl and override the OnDraw event. Even a transparent background is enough to make Xamarin honor the invalidate calls with OnDraw events.


public MapControl(Context context, IAttributeSet attrs) :
    base(context, attrs)
{
    SetBackgroundColor(Color.Transparent);
    Initialize();
}

protected override void OnDraw(Canvas canvas)
{
    base.OnDraw(canvas);
    _canvas.PostInvalidate();
}

Please consider adding this fix in Mapsui. If it would help I can create a pull request.

Thank you very much. The Forms code is not yet part of the Mapsui main project yet. I will give it attention after 1.0 (which should be there within weeks).

Perhaps @charlenni can take a look at this. He is maintaining the Forms fork.

Thanks @SimplexAuctor, your feedback proved very valuable working on issue #180.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

willy40 picture willy40  路  6Comments

lukaszpitulski picture lukaszpitulski  路  3Comments

Wil69 picture Wil69  路  5Comments

lukaszpitulski picture lukaszpitulski  路  5Comments

pauldendulk picture pauldendulk  路  7Comments