Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

osmdroid, Maps API v2, and fragments

Ok. You'd think this would be relatively simple, but nope.

I am using Open street maps on my website, as the data is free to use, edit, and update - my project follows this mantra, and alongside googles API usage restrictions/saving data restrictions, google maps simply was not suitable for me.. at least on the web.

Given this I thought i'd follow suit with my android app, and so I setup osmdroid utilizing open street maps data.

I can have a nice map in my activity.. I also followed a tutorial, and it seemed to work at least such that I can have a map view in a fragment within a tabhost/viewpager. What i really want however (for tablets), is a list of establishments in a fragment on the left, and a map fragment on the right showing where these establishments are.

Simple enough i would have thought, but hours and hours of research suggest this is not possible unless you use some complex code and some deprecated methods..

So.. the fragment (containing a map view) loads and runs perfectly in a tabhost.. i can access methods within the fragment from my activity etc.. yet nothing to just simply have two fragments side by side.

Now.. I know google have just come out with their API v2.. I installed it and had a play.. not really knowing how osmdroid works, I thought i could update so I have MapFragment instead of SherlockFragment (I use ABS).. this then just threw up logcat errors asking for API keys etc.. and given that I dont want to use google map data, I assumed that I had gone wrong.

So.. could anyone advise on how I can get a list fragment, and a map fragment side by side using anything that is available on the market, but preferably utilizing Open source map data such that their are no usage restrictions.

I'm sure an overall overview of "what is available, and how it works" would be very much appreciated by loads of users.. so if anyone could advise it would be amazing !

like image 859
Thomas Clowes Avatar asked Dec 15 '12 21:12

Thomas Clowes


2 Answers

Before the new Google Maps API came out, I was forced into using OSMDroid for my purposes. However, after having to dig through the source several times to figure out why it was doing what it was (often incorrectly), I was dying for a new library.

Fortunately, the new Google Maps API fits the bill. You can use the Google Maps API v2 in your application and never have to use Google's basemaps, but yes, unfortunately you must get an API key first.

I am assuming you want to use OpenStreetMap as an online map source, so the code below will be tailored towards that.

GoogleMap map = <get-map-instance>;

map.setMapType(GoogleMap.MAP_TYPE_NONE);

TileOverlayOptions options = new TileOverlayOptions();

options.tileProvider(new UrlTileProvider(256, 256) {
    @Override
    public URL getTileUrl(int x, int y, int z) {
        try {
            String f = "http://tile.openstreetmap.org/%d/%d/%d.png";
            return new URL(String.format(f, z, x, y));
        }
        catch (MalformedURLException e) {
            return null;
        }
    }
});

map.addTileOverlay(options);

You can find a more formalized version of this code in my Google Maps API v2 add-ons library here.

Also, if you are targeting pre-Fragment Android versions, which I believe you are based on you using ABS, instead of using MapFragment, make sure you use SupportMapFragment.

like image 134
cocoahero Avatar answered Nov 04 '22 02:11

cocoahero


The Sample Code delivered with Google Maps Android API v2 contains the class com.example.mapdemo.TileOverlayDemoActivity. I little update to this class will show OpenStreetMap tiles within the new v2 framework. Cool! No need to use osmdroid or sherlock-fragments anymore. However... the tiles are not cached :(

Anyway, all additions/updates to the TileOverlayDemoActivity class are shown below:

private static final String OPEN_STREET_MAP_URL_FORMAT =
        "http://tile.openstreetmap.org/%d/%d/%d.png";

private void setUpMap() {
    mMap.setMapType(GoogleMap.MAP_TYPE_NONE);
    mMap.setMyLocationEnabled(true);

    TileProvider tileProvider = new UrlTileProvider(256, 256) {
        @Override
        public synchronized URL getTileUrl(int x, int y, int zoom) {
            String s = String.format(Locale.US, OPEN_STREET_MAP_URL_FORMAT, zoom, x, y);
            URL url = null;
            try {
                url = new URL(s);
            } catch (MalformedURLException e) {
                throw new AssertionError(e);
            }
            return url;
        }
    };

    mMap.addTileOverlay(new TileOverlayOptions().tileProvider(tileProvider));
}
like image 22
alexx Avatar answered Nov 04 '22 00:11

alexx