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.

0 Response to "Example of implementing OpenStreetMap on Android using osmdroid"

Posting Komentar