Jun 28, 2012

Example of implementing OpenStreetMap on Android using osmdroid

Last article describe the preparation to using osmdroid on Android. It's time to implement a simple app to display OpenStreetMap on Android using osmdroid.

OpenStreetMap on Android

OpenStreetMap on Android

OpenStreetMap on Android


Make sure copy the requested JARs to libs folder, and edit manifest to add the permissions ~ refer last article.

Modify the main layout to add <org.osmdroid.views.MapView>.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:padding="@dimen/padding_medium"
        android:text="@string/hello_world"
        tools:context=".MainActivity" />
    
    <org.osmdroid.views.MapView
        android:id="@+id/mapview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:clickable="true"/>

</RelativeLayout>


Modify the main activity:
package com.android_osmdroid;

import org.osmdroid.DefaultResourceProxyImpl;
import org.osmdroid.ResourceProxy;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.MapView;
import android.os.Bundle;
import android.app.Activity;
import android.graphics.drawable.Drawable;

public class MainActivity extends Activity {
 
 MyItemizedOverlay myItemizedOverlay = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        MapView mapView = (MapView) findViewById(R.id.mapview);
        mapView.setBuiltInZoomControls(true);
        
        Drawable marker=getResources().getDrawable(android.R.drawable.star_big_on);
        int markerWidth = marker.getIntrinsicWidth();
        int markerHeight = marker.getIntrinsicHeight();
        marker.setBounds(0, markerHeight, markerWidth, 0);
        
        ResourceProxy resourceProxy = new DefaultResourceProxyImpl(getApplicationContext());
        
        myItemizedOverlay = new MyItemizedOverlay(marker, resourceProxy);
        mapView.getOverlays().add(myItemizedOverlay);
        
        GeoPoint myPoint1 = new GeoPoint(0*1000000, 0*1000000);
        myItemizedOverlay.addItem(myPoint1, "myPoint1", "myPoint1");
        GeoPoint myPoint2 = new GeoPoint(50*1000000, 50*1000000);
        myItemizedOverlay.addItem(myPoint2, "myPoint2", "myPoint2");
        
    } 
    
}


Create a new class MyItemizedOverlay.java.
package com.android_osmdroid;

import java.util.ArrayList;

import org.osmdroid.ResourceProxy;
import org.osmdroid.api.IMapView;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.overlay.ItemizedOverlay;
import org.osmdroid.views.overlay.OverlayItem;

import android.graphics.Point;
import android.graphics.drawable.Drawable;

public class MyItemizedOverlay extends ItemizedOverlay<OverlayItem> {
 
 private ArrayList<OverlayItem> overlayItemList = new ArrayList<OverlayItem>();

 public MyItemizedOverlay(Drawable pDefaultMarker,
   ResourceProxy pResourceProxy) {
  super(pDefaultMarker, pResourceProxy);
  // TODO Auto-generated constructor stub
 }
 
 public void addItem(GeoPoint p, String title, String snippet){
  OverlayItem newItem = new OverlayItem(title, snippet, p);
  overlayItemList.add(newItem);
  populate(); 
 }

 @Override
 public boolean onSnapToItem(int arg0, int arg1, Point arg2, IMapView arg3) {
  // TODO Auto-generated method stub
  return false;
 }

 @Override
 protected OverlayItem createItem(int arg0) {
  // TODO Auto-generated method stub
  return overlayItemList.get(arg0);
 }

 @Override
 public int size() {
  // TODO Auto-generated method stub
  return overlayItemList.size();
 }

}


Compare with Google Map version with the same function.

Next: Display user location by adding MyLocationOverlay on org.osmdroid.views.MapView



Updated@2014-04-16: no map but saw this in my logcat: "Problem downloading MapTile: /0/0/0 HTTP response: HTTP/1.1 403 Forbidden"

The default Apache HttpClient user-agent was recently banned from accessing tile.openstreetmap.org (server returns 403). As a result, the Mapnik provider is no longer serving any tiles for osmdroid.

OpenStreetMap's tile usage policy ( http://wiki.openstreetmap.org/wiki/Tile_usage_policy ) says that a "Valid User-Agent identifying application" must be sent. The current user-agent osmdroid sends when it downloads a tile is "Apache-HttpClient/UNAVAILABLE (java 1.4)" which is pretty generic.

I've created a patch that will send a user-agent that is more compliant with OSM's tile usage policy. The new user-agent is "osmdroid ([package name])" where [package name] is the package name of the application using osmdroid.

The patch can be found here: http://pastebin.com/kxBh1gQ5

The patch is not very pretty, but it does its job.

reference: osmdroid Issue 515 : Send a better user-agent when downloading tiles

Thanks Lora Anneken comment.

16 comments:

  1. You write code in posts and a wider layout for the blog body shall be very pleasant to use. Scroll works but that hassle can be reduced to minimum.

    ReplyDelete
  2. Hello!
    Nice tutorial. But I have a problem. Everything works fine, except that I cannot drag map in any direction and also zoom buttons didn't appear. I did however use this lines:
    mapView.setBuiltInZoomControls(true);
    mapView.setMultiTouchControls(true);
    what could be a problem?

    ReplyDelete
  3. I get the same problem as Matic d.b "I cannot drag map in any direction and also zoom buttons didn't appear".
    I observe this with version 3.0.9 but not with the previous 3.0.8. Do you have any solution?

    ReplyDelete
  4. To work zoom button and drag map, make our mapview programmatically based in this code:

    https://code.google.com/p/osmdroid/source/browse/branches/rotation/OpenStreetMapViewer/src/org/osmdroid/MapActivity.java?r=914

    ReplyDelete
  5. Hi, Could you please tell me how to get a pop up, when the screen is touched, with the location..Please!

    ReplyDelete
  6. hi i am new at android please let me know how we can use Open Street Maps as offline maps , please make tutorial about it , how to use offline maps in android thanks

    ReplyDelete
  7. my map does not appear?.. can you tell me whats wrong? or does the loading of the map take a lot of time... do i need fast internet for it to work??

    ReplyDelete
  8. Hi, i followed your tutorial but i cant see the map. I can zoom (in/out) but there is no map.

    Am i missing something? Thanks

    ReplyDelete
  9. no map but saw this in my logcat:

    "Problem downloading MapTile: /0/0/0 HTTP response: HTTP/1.1 403 Forbidden"

    Solution here:
    https://code.google.com/p/osmdroid/issues/detail?id=515
    http://stackoverflow.com/questions/21205935/downloading-maptile-0-0-0-http-response-http-1-1-403-forbidden

    basically update to 4.1 jar

    ReplyDelete
  10. This comment has been removed by the author.

    ReplyDelete
  11. Hi, I entered everything just like you said here in the files that you stated, and did the jars thing just like you said, but still when I run the app I get nothing but a grey screen filled with grey squares (like coordinates squares) and the two big stars. How could I fix this problem?
    Thank you

    ReplyDelete
  12. my area is not covered very well in open street map...
    But it's covered very well in google map and also bing map.

    So how could i use the map from either google map / bing map
    to be used in OSMDroid for offline navigation purposes?

    ReplyDelete
  13. the app crashes after launching .But i followed your code :it gives me the folowing error :

    FATAL EXCEPTION: main
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.project.project1/com.example.project.project1.MainActivity}: android.view.InflateException: Binary XML file line #6: Error inflating class uses-permission
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)

    ReplyDelete

Infolinks In Text Ads