question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

How to show an offline mapsforge map initially/immediately when the app starts?

See original GitHub issue

Issue Type

[x] Question [x] Bug [ ] Improvement [ ] Build system related [ ] Performance [x] Documentation

Description and/or steps/code to reproduce the problem

Download the attached zip file “OsmDroidMapsforge_problem_showing_map_initially.zip” (680 kb) with a small Android project, including three small mapsforge maps (.map files) in an assets folder which should become copied into the tablet when running the app. Unzip it and open it with Android Studio and run the app in a USB connected Android device.

Environment

Android Studio 3.3.1. I have tested the app in the attached zip file with two tablets (Android 4.4 and 7.1). The below described behaviour is the same for both those tablets.

If it’s a bug, version(s) of android this affects:

All versions probably (at least 4.4 and 7.1 which I have tested)

Version of osmdroid the issue relates to:

osmdroid 6.0.3 and mapsforge 0.8.0

Problem

The problem is: How can you show a map with mapsforge files immediately when the app starts (i.e. without delaying with any further interaction such as e.g. clicking a button)? It seems necessary with some kind of delay, for example triggering a dialog when the user can select a map file. (while some things need to finish in the background I suppose?)

In the attached example code, it does not work when trying to show the map immediately, but there is also a workaround with some delay in a thread, and when that code is used then it works. See the comments below at the end of the onCreate method.

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        MapsForgeTileSource.createInstance(this.getApplication());

        Context ctx = getApplicationContext();
        Configuration.getInstance().load(ctx, PreferenceManager.getDefaultSharedPreferences(ctx));

        setContentView(R.layout.activity_main);
        mMapView = (MapView) findViewById(R.id.map);

        // Here is the relevant part:
        //showOfflineMaps(); // this does NOT work
        // However, the following works, but WHY ?
        showMapsforgeMapsDelayed(); // this method invokes the above method "showOfflineMaps" from a thread
    }
	
    private void showOfflineMaps() {
        final File[] maps = assetsFileHelper.getAllMapsforgeFilesInOsmDroidDirectory();

        XmlRenderTheme theme = null;
        MapsForgeTileSource fromFiles = MapsForgeTileSource.createFromFiles(maps, theme, "rendertheme-v4");
        MapsForgeTileProvider forge = new MapsForgeTileProvider(
                new SimpleRegisterReceiver(getApplicationContext()),
                fromFiles, null);

        mMapView.setTileProvider(forge);

        mMapView.getController().setZoom(fromFiles.getMinimumZoomLevel());
        mMapView.zoomToBoundingBox(fromFiles.getBoundsOsmdroid(), true);
    }
	
    private void showMapsforgeMapsDelayed() {
        final int milliseconds = 100; // 100 milliseconds seems to be enough for the maps to become displayed without having to click the GUI button
        final FragmentActivity activity = this;
        final Thread thread = new Thread(new Runnable() {
            public void run() {
                try {
                    Thread.sleep(milliseconds);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                activity.runOnUiThread(new Runnable(){
                    @Override
                    public void run() {
                        showOfflineMaps();
                    }
                });
            }
        });
        thread.start();
    }

The following page has a section “Code setup”: https://github.com/osmdroid/osmdroid/wiki/Mapsforge

I suspect that some of that setup code is triggering something in the background but it will not have finished soon enough when the activity is created. Maybe something is missing in that documentation? Maybe there is some callback method that should be implemented to do something when everything needed has really finished in the background, rather than adding a delay as I did in the attached code example? OsmDroidMapsforge_problem_showing_map_initially.zip

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:5

github_iconTop GitHub Comments

1reaction
monsieurtanukicommented, Feb 20, 2019

@TomasJohansson Fair enough, I’ve just fixed the osmdroid vs. Mapsforge doc too.

I understand that the View.post syntax can be a bit annoying, but I’m not 100% convinced by your suggestion as there are other map set up cases (e.g. centering the map) that would need the same “AfterLayoutHasCompleted” additional methods.

The best we can do I guess is to be more explicit in the doc and in the code samples.

0reactions
TomasJohanssoncommented, Feb 20, 2019

Okay, so it is not specific for Mapsforge only, but it is applicable for Mapsforge code. Therefore, IMHO, the documentation code example for mapsforge could also be more clear about this, since it is currently written as if it is okay to invoke the methods in sequence. (with “mMapView.getController()…” and then “mMapView.zoomToBoundingBox…” directly after)

I suppose it is a very common situation that you want to zoom automatically to the bounding box. (or is it not?) If so, would it not be desirable to make the setup code easier i.e. with less verbose code, so that you can invoke those methods in sequence in an onReady method? I mean, the osmdroid developers might add a convenience methods to be able to do something like this:

protected void onCreate(Bundle savedInstanceState) {
	...
    mMapView.getController().setZoom(fromFiles.getMinimumZoomLevel());
    mMapView.zoomToBoundingBoxAfterLayoutHasCompleted(fromFiles.getBoundsOsmdroid(), true);
}
public class MapView extends ViewGroup implements IMapView, MultiTouchObjectCanvas<Object> {
    ...
    public void zoomToBoundingBoxAfterLayoutHasCompleted(final BoundingBox boundingBox, final boolean animated) {
        final MapView mMapView = this;
        post(
            new Runnable() {
                @Override
                public void run() {
                    mMapView.zoomToBoundingBox(boundingBox, animated);
                }
            }
        );
    }
}

Okay I can close the issue since there is a solution i.e. use the post method. Thank you.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Develop Offline Maps in Android with Mapsforge - YouTube
This video shows you how to show offline map files in Android using Mapsforge.Source code: https://github.com/djnotes/my- offline - map.
Read more >
Offline map using mapsforge in android - Stack Overflow
You will need two things: a program that allows you to use the mapsforge library. Concerning this, you can stick with the program...
Read more >
Download areas & navigate offline - Google Maps Help
Step 1: Download a map to use offline ; On your Android phone or tablet, open the Google Maps app Maps . ;...
Read more >
Offline Map Tutorial - c:geo User Guide
The c:geo map downloader can be started in two ways: From the map view by opening the map selector and tapping on <Download...
Read more >
OSM Dashboard Offline for OpenTracks - F-Droid
It shows a selected track with start- and endpoints on a map from OpenStreetMap based on the Mapsforge library. The default is an...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found