9

I'm looking for a way to use custom map tiles with the Google Map API V2 for Android.

I'm writing an application that will create it's own maps in real time with data that are comming from a robot.

The application need to show to the operator this map. The operator need to interact with this map, letting way points, etc.

I want to use the GoogleMap engine in order to do the same that this page :

http://cdn.mikecouturier.com/blog.mikecouturier.com/tilesgenerator/index.html

The problem is that he used the Javascript API when I want to use the Android API

Is there any way to use Custom tiles map on android with the Google Maps Engine?

I'm already looking at how to use ArcGIS but, i prefer using an API without paying for a license.

7

Yes, you can use custom tiles with Android Maps API v2 - you can see a fully working example in our OpenTripPlanner for Android app on Github. (You can also download the app directly from Google Play)

We support the following tile providers:

  • LyrkOpenStreetMap
  • MapQuestOpenStreetMap
  • Mapnik
  • CycleMap
  • Google (normal, satellite, hybrid, terrain)

Our CustomUrlTileProvider class can be seen here on Github, and I've also pasted it below:

public class CustomUrlTileProvider extends UrlTileProvider {

    private String baseUrl;

    public CustomUrlTileProvider(int width, int height, String url) {
        super(width, height);
        this.baseUrl = url;
    }

    @Override
    public URL getTileUrl(int x, int y, int zoom) {
        try {
            return new URL(baseUrl.replace("{z}", "" + zoom).replace("{x}", "" + x)
                    .replace("{y}", "" + y));
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        return null;
    }
}

And here's the code that switches between map tile providers, based on user preference:

/**
 * Changes the tiles used to display the map and sets max zoom level.
 *
 * @param overlayString tiles URL for custom tiles or description for
 *                      Google ones
 */
public void updateOverlay(String overlayString) {
    int tile_width = OTPApp.CUSTOM_MAP_TILE_SMALL_WIDTH;
    int tile_height = OTPApp.CUSTOM_MAP_TILE_SMALL_HEIGHT;

    if (overlayString == null) {
        overlayString = mPrefs.getString(OTPApp.PREFERENCE_KEY_MAP_TILE_SOURCE,
                mApplicationContext.getResources()
                        .getString(R.string.map_tiles_default_server));
    }
    if (mSelectedTileOverlay != null) {
        mSelectedTileOverlay.remove();
    }
    if (overlayString.startsWith(OTPApp.MAP_TILE_GOOGLE)) {
        int mapType = GoogleMap.MAP_TYPE_NORMAL;

        if (overlayString.equals(OTPApp.MAP_TILE_GOOGLE_HYBRID)) {
            mapType = GoogleMap.MAP_TYPE_HYBRID;
        } else if (overlayString.equals(OTPApp.MAP_TILE_GOOGLE_NORMAL)) {
            mapType = GoogleMap.MAP_TYPE_NORMAL;
        } else if (overlayString.equals(OTPApp.MAP_TILE_GOOGLE_TERRAIN)) {
            mapType = GoogleMap.MAP_TYPE_TERRAIN;
        } else if (overlayString.equals(OTPApp.MAP_TILE_GOOGLE_SATELLITE)) {
            mapType = GoogleMap.MAP_TYPE_SATELLITE;
        }
        mMap.setMapType(mapType);
        mMaxZoomLevel = mMap.getMaxZoomLevel();
    } else {
        if (overlayString.equals(getResources().getString(R.string.tiles_mapnik))) {
            mMaxZoomLevel = getResources().getInteger(R.integer.tiles_mapnik_max_zoom);
        } else if (overlayString.equals(getResources().getString(R.string.tiles_lyrk))) {
            mMaxZoomLevel = getResources().getInteger(R.integer.tiles_lyrk_max_zoom);
            tile_width = OTPApp.CUSTOM_MAP_TILE_BIG_WIDTH;
            tile_height = OTPApp.CUSTOM_MAP_TILE_BIG_HEIGHT;
        } else {
            mMaxZoomLevel = getResources().getInteger(R.integer.tiles_maquest_max_zoom);
        }

        mMap.setMapType(GoogleMap.MAP_TYPE_NONE);
        CustomUrlTileProvider mTileProvider = new CustomUrlTileProvider(
                tile_width,
                tile_height, overlayString);
        mSelectedTileOverlay = mMap.addTileOverlay(
                new TileOverlayOptions().tileProvider(mTileProvider)
                        .zIndex(OTPApp.CUSTOM_MAP_TILE_Z_INDEX));

        if (mMap.getCameraPosition().zoom > mMaxZoomLevel) {
            mMap.moveCamera(CameraUpdateFactory.zoomTo(mMaxZoomLevel));
        }
    }
}

Here's a screenshot of the MapQuest OpenStreetMap tiles: enter image description here

For more information on making your own tiles, see the Google documentation for TileOverlay as well as the OpenStreetMap wiki for "Creating your own tiles".

Specifically, the Google documentation says:

Note that the world is projected using the Mercator projection (see Wikipedia) with the left (west) side of the map corresponding to -180 degrees of longitude and the right (east) side of the map corresponding to 180 degrees of longitude. To make the map square, the top (north) side of the map corresponds to 85.0511 degrees of latitude and the bottom (south) side of the map corresponds to -85.0511 degrees of latitude. Areas outside this latitude range are not rendered.

At each zoom level, the map is divided into tiles and only the tiles that overlap the screen are downloaded and rendered. Each tile is square and the map is divided into tiles as follows:

  • At zoom level 0, one tile represents the entire world. The coordinates of that tile are (x, y) = (0, 0).

  • At zoom level 1, the world is divided into 4 tiles arranged in a 2 x 2 grid. ...

  • At zoom level N, the world is divided into 4N tiles arranged in a 2N x 2N grid.

Note that the minimum zoom level that the camera supports (which can depend on various factors) is GoogleMap.getMinZoomLevel and the maximum zoom level is GoogleMap.getMaxZoomLevel.

The coordinates of the tiles are measured from the top left (northwest) corner of the map. At zoom level N, the x values of the tile coordinates range from 0 to 2N - 1 and increase from west to east and the y values range from 0 to 2N - 1 and increase from north to south.

The formatted URLs that are used within OTP Android to reference each tile provider look like:

So, for the above providers the tile images are PNG files arranged in the directory structure indicated by the Google documentation. You would follow a similar format to create your own map tiles hosted on your own server. Note that these URLs/images must be publicly accessible to the mobile device (i.e., cannot be password protected).

  • Thank for your time. It is possible to use images fully created by me in a personal repository ? What is the format of that tile ? And the arborescence ? – MonkeyJLuffy Jul 9 '14 at 10:46
  • @MonkeyJLuffy I just added some information to the bottom of my answer for this. Please let me know if you still have questions after reading this. – Sean Barbeau Jul 9 '14 at 13:32
0

The most extensive solution I have found is in this StackOverflow Answer:

Basically you need to implement your own TileProvider and use that as an TileOverlay

In a couple of applications we have used this kind of layer to show tiles on the map, but we found the tiles took up a lot of space. Hence we shifted to using mbtiles and this library to display the data from mbtiles on the map.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.