How to create map tiles from OpenStreetMap offline, display it on Android?

24,530

Solution 1

I'm currently developing (my first) Android application using the OpenStreetMap (OSM) API, so while I can't help you with the JSOM, I can try to help with the OSM part:

Assuming that you want to create a new activity in your android application that simply displays a OSM map, you might start with something like this:

package example.stackoverflow.osmdroid;

import android.app.Activity;
import android.os.Bundle;

import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.MapView;

public class YourMap extends Activity {
    // The MapView variable:
    private MapView m_mapView;

    // Default map zoom level:
    private int MAP_DEFAULT_ZOOM = 15;

    // Default map Latitude:
    private double MAP_DEFAULT_LATITUDE = 38.535350;

    // Default map Longitude:
    private double MAP_DEFAULT_LONGITUDE = -121.753807;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Specify the XML layout to use:
        setContentView(R.layout.osm_map);

        // Find the MapView controller in that layout:
        m_mapView = (MapView) findViewById(R.id.mapview);

        // Setup the mapView controller:
        m_mapView.setBuiltInZoomControls(true);
        m_mapView.setMultiTouchControls(true);
        m_mapView.setClickable(true);
        m_mapView.setUseDataConnection(false);
        m_mapView.getController().setZoom(MAP_DEFAULT_ZOOM);
        m_mapView.getController().setCenter(
            new GeoPoint(MAP_DEFAULT_LATITUDE, MAP_DEFAULT_LONGITUDE));
        m_mapView.setTileSource(TileSourceFactory.MAPNIK);
    } // end onCreate()
} // end class YourMap

Where your osm_map.xml layout may look something like this:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

        <org.osmdroid.views.MapView
            android:id="@+id/mapview"
            android:layout_width="match_parent" 
            android:layout_height="match_parent"
            android:enabled="true"      
            android:clickable="true"
        />  
</RelativeLayout>

As for the actual map tiles, there is a really cool program called Mobile Atlas Creator, which allows you to generate the necessary map tiles for the offline Android map implemented above.

Once you have the application installed, and you want to create a new atlas, you'll be asked to select your "desired altas format." When this pops up, select "Osmdroid zip."

Once everything loads, select a region on the map that you would like to create tiles for, select the zoom levels you want tiles for, and hit the "Add Selection" button in the column on the left, followed by "Create Atlas."

Oh, and depending on the source, you may need to check the "Create/Adjust Map tiles" checkbox to force the tiles to be exported as PNGs -- does anyone know if it's possible to use JPG with OSM?

Once the ZIP has been generated, I renamed it to "Mapnik.zip" and moved it to a newly created folder called "tiles" in my Eclipse Android project workspace. In order to get it working, I also had to open the zip file, and rename the top level folder from something like "Google Earth" (depending on the map source you used), to "Mapnik," in order for the tile to display in my Android application.

In order to actually load the tiles onto your phone, however, you'll need to use the ADB tool from the terminal. In your ADB tool directory, you'll want to run something like this (each line is a new command):

./adb shell rm -r /sdcard/osmdroid/
./adb shell mkdir /sdcard/osmdroi/
./adb push ~/path/to/your/mapnik.zip /sdcard/osmdroid

Depending on the size of the map and the speed of the phone's memory bus, this last step may take a several minutes to an hour to complete. Once done, your map should work -- I hope!

As I mentioned, this is the first time I've used the OSM API, so I'm by no means an expert on it, and I can only comment on what worked for me.

Hope this will help you get started!

EDIT:

I didn't have a chance to actually run the code that I wrote up yesterday, so I didn't catch a few of the errors. I just created a new project in Eclipse, dumped my code in there, fixed a few things and got it up and running. All changes that I made are reflected in the code above! I forgot several of the basic import statements, and I forgot to add permissions to the manifest.xml file.

The last few lines of my manifest.xml now look like this:

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> 
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>

And you also might want to add this to the manifest, although certainly not critical:

<supports-screens 
    android:anyDensity="true"
    android:resizeable="false"
    android:largeScreens="true"
    android:normalScreens="true"
/>

Add this right after the <uses-sdk ... /> part.

Furthermore, be sure to import the following two JAR libraries:

osmdroid-android-3.0.3.jar // Or whatever version you're using...

and

slf4j-android-1.5.8.jar // Or whatever the latest version is...

Without this last JAR, my code kept crashing until I remembered to include it.

Make sure to modify the default coordinates so that they point to a location that you actually have map tiles for, otherwise you're not going to see much of anything, aside from a white canvas.

Sorry for not running the code on my end first!

Solution 2

Here is a step by step solution:

In brief:

1- You must download map tiles using Mobile Atlas Creator. I have explained the steps HERE

2- Move the resulting zip-file to /mnt/sdcard/osmdroid/ on your device.

3- Adding osmdroid-android-XXX.jar and slf4j-android-1.5.8.jar into build path your project

4- Adding MapView: You can add a MapView to your xml layout

<org.osmdroid.views.MapView
    android:id="@+id/mapview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tilesource="Mapnik"
    />

Or create a MapView programmatically:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
    mResourceProxy = new ResourceProxyImpl(inflater.getContext().getApplicationContext());
    mMapView = new MapView(inflater.getContext(), 256, mResourceProxy);
    return mMapView;
}

Don't forget to add these permissions to your Manifest:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> 
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

This is a good Sample Project. Hope it Helps ;)

Important

As @Scai mentioned: recently Open Street Map announced that this tool is not good and had some problems:

This tool results in heavy traffic for the OSM tile servers and is likely to be blocked. Please don't use it.

Solution 3

Alternatively to map tiles you can also use vector data for your offline map, for example mapsforge or the Mapbox Android SDK. For more information consult the OSM wiki about offline OSM and Android libraries.

Share:
24,530
rahstame
Author by

rahstame

Got banned and don't kno9w what to do. **http://goo.gl/C1Kwu

Updated on July 27, 2022

Comments

  • rahstame
    rahstame almost 2 years

    What I want is to display a simple offline map using OpenStreetMap. I cannot find in the web the right tools to create map tiles and use it to display a map in Android. I have downloaded different resources but it seems that I don't have any idea where to start. I want to integrate images from OpenStreetMap using JOSM but i don't know if I can use it on Android.

    Can I use Mapnik? Your help will a great thank you.

  • rahstame
    rahstame over 12 years
    hi Sir Tim. You are truly awesome. Thank you for sharing your code and your ideas. I am really excited to try this out. Your procedure are very clear and very informative. Please update your status sir..thank you.
  • rahstame
    rahstame over 12 years
    I have this errors: [2011-10-05 22:22:58 - OsmNavigator] Dx 1 error; aborting [2011-10-05 22:22:58 - OsmNavigator] Conversion to Dalvik format failed with error 1 [2011-10-05 22:26:07 - YourMap] Dx UNEXPECTED TOP-LEVEL EXCEPTION: java.lang.IllegalArgumentException: already added: Lorg/osmdroid/tileprovider/tilesource/bing/BingMapTileSource‌​; [2011-10-05 22:26:07 - YourMap] Dx at com.android.dx.dex.file.ClassDefsSection.add(ClassDefsSectio‌​n.java:123) [2011-10-05 22:26:07 - YourMap] Dx at com.android.dx.dex.file.DexFile.add(DexFile.java:143)
  • Tim Severeijns
    Tim Severeijns over 12 years
    Hi rahstame, judging by the output you posted, you might be trying to include two JARs that share some of the same packages and classes; in other words, there is a conflict between some of your included JAR files. Take a look at the suggestions in this link.
  • rahstame
    rahstame over 12 years
    When I right click the project > properties > java build paths > libraries. Then I found out that there are diff libraries I used osmdroid-android-3.0.1.jar and osmdroid-android-3.0.5.jar. I deleted the 3.0.5.jar. Then I was able to compile but when I go to the emulator screen it displays "Sorry the application runs unexpectedly"
  • rahstame
    rahstame over 12 years
    I followed your steps: I have copy pasted your java code under the "package com.YourMap;" then I have unused imports "import org.osmdroid.tileprovider.tilesource.BitmapTileSourceBase;" I have also /res/layout/osm_map.xml. Then created a folder: /tiles/Mapnik.zip from Mobile Altas Creator
  • Tim Severeijns
    Tim Severeijns over 12 years
    I ran the code myself this time, and updated my post to reflect the necessary modifications. If this work, don't forget to accept my answer! Thank you.
  • rahstame
    rahstame over 12 years
    Yes I was able to update the codes and I be able to see the map. Thank you for compiling your code sir. I will accept your answer. But does this work offline. Like no internet connection possible to load the map. Like the map is already stored in the YourMap project then access it programmatically and be able to zoom in/ out? I want to get rid of this " <uses-permission android:name="android.permission.INTERNET" />"...Thank you.
  • Tim Severeijns
    Tim Severeijns over 12 years
    Excellent. Yup, that is indeed possible; the entire thing is accessible without an Internet connection. You should be able to get rid of android.permission.INTERNET -- I just grabbed a bunch of permissions from another project and copy/pasted it in this one, so not all of them are necessary! Good luck with the rest of the project, sir!
  • rahstame
    rahstame over 12 years
    Thank you sir Tim. I hope you'll also update your status in your project like this one.
  • Girish Bhutiya
    Girish Bhutiya about 12 years
  • direndd
    direndd almost 11 years
    I went through the process described in the answer but i couldn't go pass the step "Once everything loads, select a region on the map that you would like to create tiles for, select the zoom levels you want tiles for, and hit the "Add Selection" button in the column on the left, followed by "Create Atlas." " Once i select the "desired altas format" as "Osmdroid zip." it loads an outdoor map. How can i load the indoor map(which i created using JOSM) into the MOBAC? Thank you! :)
  • Tim Severeijns
    Tim Severeijns almost 11 years
    Diren, can you clarify what you mean by outdoor map versus indoor map? Also, please keep in mind that I have not worked with OpenStreetMap in almost two years, so I may not be able to answer your question.
  • MohanRaj S
    MohanRaj S over 9 years
    Hi Tim Severeijns: I Followed your code and implement it and test run the program but id shows in log cat following statement,Caused by: java.lang.ClassNotFoundException: Didn't find class "org.omsdroid.views.mapview" on path: DexPathList[[zip file "/data/app/com.next.osm_map_jan_27-1.apk"],nativeLibraryDire‌​ctories=[/data/app-l‌​ib/com.next.osm_map_‌​jan_27-1, /vendor/lib, /system/lib]],
  • Tim Severeijns
    Tim Severeijns over 9 years
    Hi MohanRaj, It's been years since I last looked at this code, so I can't say with any certainty what might be wrong, but have you tried going to Project > Clean in Eclipse to clean and rebuild the project? I would also double check your import paths, and your jar directory paths.
  • scai
    scai over 7 years
    Note that MOBAC is very bad for OSM tile servers and you are likely getting blocked. See wiki.openstreetmap.org/wiki/MOBAC for more information.