add open street maps layer

git-svn-id: https://osmand.googlecode.com/svn/trunk@140 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
Victor Shcherb 2010-06-05 21:17:08 +00:00
parent c6e16ea747
commit 1df7216662
8 changed files with 317 additions and 66 deletions

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<TableLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" android:stretchColumns="1">
<TableRow >
<TextView android:id="@+id/TextView" android:layout_marginLeft="5dp"
android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Message"></TextView>
<EditText android:text="" android:id="@+id/BugMessage" android:layout_marginLeft="5dp" android:layout_marginRight="5dp"
android:layout_width="fill_parent" android:layout_height="wrap_content"></EditText>
</TableRow>
<TableRow >
<TextView android:text="Author name" android:id="@+id/TextView" android:layout_marginLeft="5dp"
android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView>
<EditText android:text="NoName" android:id="@+id/AuthorName" android:layout_marginLeft="5dp" android:layout_marginRight="5dp"
android:layout_width="fill_parent" android:layout_height="wrap_content"></EditText>
</TableRow>
</TableLayout>

View file

@ -2,7 +2,7 @@
<menu
xmlns:android="http://schemas.android.com/apk/res/android">
<group android:id="@+id/map_context_menu" android:menuCategory="container"><item android:id="@+id/map_show_settings" android:title="@string/settings_Button"></item>
<item android:id="@+id/map_add_to_favourite" android:title="@string/add_to_favourite"></item>
<item android:title="@string/mark_point" android:id="@+id/map_mark_point"></item>
<item android:title="@string/navigate_to_point" android:id="@+id/map_navigate_to_point"></item>
<item android:title="@string/map_specify_point" android:id="@+id/map_specify_point"></item>

View file

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="user_name_descr">Input user name to communicate osm</string>
<string name="user_name">User name</string>
<string name="mark_point">Mark point</string>
<string name="show_osm_bugs_descr">Show open street bugs on map</string>
<string name="show_osm_bugs">Show open street bugs</string>
<string name="favourites_activity">List of favourite points</string>

View file

@ -2,6 +2,7 @@
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="@string/app_settings"><CheckBoxPreference android:summary="@string/use_english_names_descr" android:title="@string/use_english_names" android:key="use_english_names"></CheckBoxPreference>
<EditTextPreference android:title="@string/user_name" android:summary="@string/user_name_descr" android:key="user_name"></EditTextPreference>
</PreferenceCategory>
<PreferenceCategory android:title="@string/map_preferences">

View file

@ -33,6 +33,18 @@ public class OsmandSettings {
return prefs.getBoolean(SHOW_POI_OVER_MAP, false);
}
// this value string is synchronized with settings_pref.xml preference name
public static final String USER_NAME = "user_name";
public static String getUserName(Context ctx){
SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE);
return prefs.getString(USER_NAME, "NoName");
}
public static boolean setUserName(Context ctx, String name){
SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE);
return prefs.edit().putString(USER_NAME, name).commit();
}
// this value string is synchronized with settings_pref.xml preference name
public static final String SHOW_OSM_BUGS = "show_osm_bugs";

View file

@ -99,7 +99,7 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
mapView.addLayer(locationLayer);
mapInfoLayer = new MapInfoLayer(this);
mapView.addLayer(mapInfoLayer);
osmBugsLayer = new OsmBugsLayer();
osmBugsLayer = new OsmBugsLayer(this);
@ -160,6 +160,7 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
startActivity(newIntent);
}
});
}
@ -225,6 +226,13 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
}
public void navigateToPoint(LatLon point){
if(point != null){
getPreferences(MODE_WORLD_READABLE).edit().
putFloat(POINT_NAVIGATE_LAT, (float) mapView.getLatitude()).
putFloat(POINT_NAVIGATE_LON, (float) mapView.getLongitude()).commit();
} else {
getPreferences(MODE_WORLD_READABLE).edit().remove(POINT_NAVIGATE_LAT).remove(POINT_NAVIGATE_LON).commit();
}
navigationLayer.setPointToNavigate(point);
}
@ -357,6 +365,23 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
}
}
@Override
public void onSensorChanged(SensorEvent event) {
// using that strange technique because sensor produces a lot of events & hangs the system
locationLayer.setHeading(event.values[0], true);
if(!sensorHandler.hasMessages(1) && locationLayer.isLocationVisible(locationLayer.getLastKnownLocation())){
Message m = Message.obtain(sensorHandler, new Runnable(){
@Override
public void run() {
mapView.refreshMap();
}
});
m.what = 1;
sensorHandler.sendMessage(m);
}
}
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.map_menu, menu);
@ -377,29 +402,42 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
final Intent settings = new Intent(MapActivity.this, SettingsActivity.class);
startActivity(settings);
return true;
} else if (item.getItemId() == R.id.map_add_to_favourite) {
addFavouritePoint();
} else if (item.getItemId() == R.id.map_mark_point) {
markPoint();
return true;
} else if (item.getItemId() == R.id.map_specify_point) {
openChangeLocationDialog();
return true;
} else if (item.getItemId() == R.id.map_navigate_to_point) {
if(navigationLayer.getPointToNavigate() != null){
getPreferences(MODE_WORLD_READABLE).edit().remove(POINT_NAVIGATE_LAT).remove(POINT_NAVIGATE_LON).commit();
item.setTitle(R.string.navigate_to_point);
navigateToPoint(null);
} else {
getPreferences(MODE_WORLD_READABLE).edit().
putFloat(POINT_NAVIGATE_LAT, (float) mapView.getLatitude()).
putFloat(POINT_NAVIGATE_LON, (float) mapView.getLongitude()).commit();
item.setTitle(R.string.stop_navigation);
navigateToPoint(new LatLon(mapView.getLatitude(), mapView.getLongitude()));
}
}
return super.onOptionsItemSelected(item);
}
private void addFavouritePoint(){
protected void markPoint(){
Builder builder = new AlertDialog.Builder(this);
builder.setItems(new String[]{"Navigate to point", "Add to favourites", "Open osm bug"}, new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
if(which == 0){
navigateToPoint(new LatLon(mapView.getLatitude(), mapView.getLongitude()));
} else if(which == 1){
addFavouritePoint();
} else if(which == 2){
osmBugsLayer.openBug(MapActivity.this, getLayoutInflater(), mapView);
}
}
});
builder.create().show();
}
protected void addFavouritePoint(){
final FavouritePoint p = new FavouritesActivity.FavouritePoint();
p.setLatitude(mapView.getLatitude());
p.setLongitude(mapView.getLongitude());
@ -435,21 +473,6 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@Override
public void onSensorChanged(SensorEvent event) {
// using that strange technique because sensor produces a lot of events & hangs the system
locationLayer.setHeading(event.values[0], true);
if(!sensorHandler.hasMessages(1) && locationLayer.isLocationVisible(locationLayer.getLastKnownLocation())){
Message m = Message.obtain(sensorHandler, new Runnable(){
@Override
public void run() {
mapView.refreshMap();
}
});
m.what = 1;
sensorHandler.sendMessage(m);
}
}
}

View file

@ -7,6 +7,7 @@ import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
@ -28,6 +29,7 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
private ListPreference positionOnMap;
private CheckBoxPreference useEnglishNames;
private CheckBoxPreference showOsmBugs;
private EditTextPreference userName;
@Override
public void onCreate(Bundle savedInstanceState) {
@ -46,6 +48,8 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
showOsmBugs.setOnPreferenceChangeListener(this);
useEnglishNames =(CheckBoxPreference) screen.findPreference(OsmandSettings.USE_ENGLISH_NAMES);
useEnglishNames.setOnPreferenceChangeListener(this);
userName = (EditTextPreference) screen.findPreference(OsmandSettings.USER_NAME);
userName.setOnPreferenceChangeListener(this);
positionOnMap =(ListPreference) screen.findPreference(OsmandSettings.POSITION_ON_MAP);
positionOnMap.setOnPreferenceChangeListener(this);
@ -68,6 +72,7 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
positionOnMap.setEntryValues(e);
positionOnMap.setEntries(e);
positionOnMap.setValueIndex(OsmandSettings.getPositionOnMap(this));
userName.setText(OsmandSettings.getUserName(this));
List<TileSourceTemplate> list = TileSourceManager.getKnownSourceTemplates();
@ -100,6 +105,9 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
} else if(preference == useEnglishNames){
edit.putBoolean(OsmandSettings.USE_ENGLISH_NAMES, (Boolean) newValue);
edit.commit();
} else if(preference == userName){
edit.putString(OsmandSettings.USER_NAME, (String) newValue);
edit.commit();
} else if(preference == showViewAngle){
edit.putBoolean(OsmandSettings.SHOW_VIEW_ANGLE, (Boolean) newValue);
edit.commit();

View file

@ -5,13 +5,21 @@ import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.logging.Log;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
@ -21,9 +29,14 @@ import android.graphics.RectF;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
import com.osmand.LogUtil;
import com.osmand.OsmandSettings;
import com.osmand.R;
import com.osmand.osm.MapUtils;
public class OsmBugsLayer implements OsmandMapLayer {
@ -41,14 +54,19 @@ public class OsmBugsLayer implements OsmandMapLayer {
private Paint pointClosedUI;
private Paint pointOpenedUI;
private Pattern patternToParse = Pattern.compile("putAJAXMarker\\((\\d*), ((\\d|\\.)*), ((\\d|\\.)*), '([^']*)', (\\d)\\);");
private SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy hh:mm aaa", Locale.US);
private double cTopLatitude;
private double cBottomLatitude;
private double cLeftLongitude;
private double cRightLongitude;
private int czoom;
private final Activity activity;
public OsmBugsLayer(Activity activity){
this.activity = activity;
}
@Override
public void initLayer(OsmandMapTileView view) {
@ -168,46 +186,36 @@ public class OsmBugsLayer implements OsmandMapLayer {
}
}
protected List<OpenStreetBug> loadingBugs(double topLatitude, double leftLongitude, double bottomLatitude,double rightLongitude){
List<OpenStreetBug> bugs = new ArrayList<OpenStreetBug>();
StringBuilder b = new StringBuilder();
b.append("http://openstreetbugs.schokokeks.org/api/0.1/getBugs?");
b.append("b=").append(bottomLatitude);
b.append("&t=").append(topLatitude);
b.append("&l=").append(leftLongitude);
b.append("&r=").append(rightLongitude);
try {
URL url = new URL(b.toString());
URLConnection connection = url.openConnection();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String st = null;
while((st = reader.readLine()) != null){
Matcher matcher = patternToParse.matcher(st);
if(matcher.find()){
OpenStreetBug bug = new OpenStreetBug();
bug.setId(Long.parseLong(matcher.group(1)));
bug.setLongitude(Double.parseDouble(matcher.group(2)));
bug.setLatitude(Double.parseDouble(matcher.group(4)));
bug.setName(matcher.group(6));
bug.setOpened(matcher.group(7).equals("0"));
bugs.add(bug);
}
}
} catch (IOException e) {
log.warn("Error loading bugs", e);
} catch (NumberFormatException e) {
log.warn("Error loading bugs", e);
} catch (RuntimeException e) {
log.warn("Error loading bugs", e);
}
return bugs;
}
@Override
public boolean onLongPressEvent(PointF point) {
if (objects != null && !objects.isEmpty()) {
int ex = (int) point.x;
int ey = (int) point.y;
int radius = getRadiusBug(view.getZoom()) * 3 / 2;
try {
for (final OpenStreetBug n : objects) {
int x = view.getRotatedMapXForPoint(n.getLatitude(), n.getLongitude());
int y = view.getRotatedMapYForPoint(n.getLatitude(), n.getLongitude());
if (Math.abs(x - ex) <= radius && Math.abs(y - ey) <= radius) {
Builder builder = new AlertDialog.Builder(view.getContext());
builder.setItems(new String[]{"Add comment", "Close bug"}, new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
if(which == 0){
commentBug(view.getContext(), activity.getLayoutInflater(), n);
} else if(which == 1){
closeBug(view.getContext(), activity.getLayoutInflater(), n);
}
}
});
builder.create().show();
return true;
}
}
} catch (IndexOutOfBoundsException e) {
// that's really rare case, but is much efficient than introduce synchronized block
}
}
return false;
}
@ -235,6 +243,182 @@ public class OsmBugsLayer implements OsmandMapLayer {
}
public void clearCache() {
objects.clear();
cTopLatitude = 0;
cBottomLatitude = 0;
cLeftLongitude = 0;
cRightLongitude = 0;
}
public boolean createNewBug(double latitude, double longitude, String text, String authorName){
StringBuilder b = new StringBuilder();
b.append("http://openstreetbugs.schokokeks.org/api/0.1/addPOIexec?");
b.append("lat=").append(latitude);
b.append("&lon=").append(longitude);
text = text + " [" + authorName +" "+ dateFormat.format(new Date())+ "]";
b.append("&text=").append(text);
b.append("&name=").append(authorName);
return editingPOI(b.toString(), "creating bug");
}
public boolean addingComment(long id, String text, String authorName){
StringBuilder b = new StringBuilder();
b.append("http://openstreetbugs.schokokeks.org/api/0.1/editPOIexec?");
b.append("id=").append(id);
text = text + " [" + authorName +" "+ dateFormat.format(new Date())+ "]";
b.append("&text=").append(text);
b.append("&name=").append(authorName);
return editingPOI(b.toString(), "adding comment");
}
public boolean closingBug(long id){
StringBuilder b = new StringBuilder();
b.append("http://openstreetbugs.schokokeks.org/api/0.1/closePOIexec?");
b.append("id=").append(id);
return editingPOI(b.toString(),"closing bug");
}
private boolean editingPOI(String urlStr, String debugAction){
urlStr = urlStr.replace(" ", "%20");
try {
URL url = new URL(urlStr);
URLConnection connection = url.openConnection();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
while(reader.readLine() != null){
}
log.debug("Action " + debugAction + " successfull");
return true;
} catch (IOException e) {
log.error("Error " +debugAction, e);
} catch (RuntimeException e) {
log.error("Error "+debugAction, e);
}
return false;
}
protected List<OpenStreetBug> loadingBugs(double topLatitude, double leftLongitude, double bottomLatitude,double rightLongitude){
List<OpenStreetBug> bugs = new ArrayList<OpenStreetBug>();
StringBuilder b = new StringBuilder();
b.append("http://openstreetbugs.schokokeks.org/api/0.1/getBugs?");
b.append("b=").append(bottomLatitude);
b.append("&t=").append(topLatitude);
b.append("&l=").append(leftLongitude);
b.append("&r=").append(rightLongitude);
try {
URL url = new URL(b.toString());
URLConnection connection = url.openConnection();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String st = null;
while((st = reader.readLine()) != null){
Matcher matcher = patternToParse.matcher(st);
if(matcher.find()){
OpenStreetBug bug = new OpenStreetBug();
bug.setId(Long.parseLong(matcher.group(1)));
bug.setLongitude(Double.parseDouble(matcher.group(2)));
bug.setLatitude(Double.parseDouble(matcher.group(4)));
bug.setName(matcher.group(6).replace("<hr />", "\n"));
bug.setOpened(matcher.group(7).equals("0"));
bugs.add(bug);
}
}
} catch (IOException e) {
log.warn("Error loading bugs", e);
} catch (NumberFormatException e) {
log.warn("Error loading bugs", e);
} catch (RuntimeException e) {
log.warn("Error loading bugs", e);
}
return bugs;
}
public void openBug(final Context ctx, LayoutInflater layoutInflater, final OsmandMapTileView mapView){
Builder builder = new AlertDialog.Builder(ctx);
builder.setTitle("Input text of bug");
final View view = layoutInflater.inflate(R.layout.open_bug, null);
builder.setView(view);
((EditText)view.findViewById(R.id.AuthorName)).setText(OsmandSettings.getUserName(ctx));
builder.setNegativeButton("Cancel", null);
builder.setPositiveButton("Add", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String text = ((EditText)view.findViewById(R.id.BugMessage)).getText().toString();
String author = ((EditText)view.findViewById(R.id.AuthorName)).getText().toString();
OsmandSettings.setUserName(ctx, author);
boolean bug = createNewBug(mapView.getLatitude(), mapView.getLongitude(),
text, author);
if (bug) {
Toast.makeText(ctx, "Bug was successfully created", Toast.LENGTH_LONG).show();
clearCache();
if (mapView.getLayers().contains(OsmBugsLayer.this)) {
mapView.refreshMap();
}
} else {
Toast.makeText(ctx, "Exception occured : bug was not created", Toast.LENGTH_LONG).show();
}
}
});
builder.show();
}
public void commentBug(final Context ctx, LayoutInflater layoutInflater, final OpenStreetBug bug){
Builder builder = new AlertDialog.Builder(ctx);
builder.setTitle("Adding comment to bug");
final View view = layoutInflater.inflate(R.layout.open_bug, null);
builder.setView(view);
((EditText)view.findViewById(R.id.AuthorName)).setText(OsmandSettings.getUserName(ctx));
builder.setNegativeButton("Cancel", null);
builder.setPositiveButton("Add comment", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String text = ((EditText)view.findViewById(R.id.BugMessage)).getText().toString();
String author = ((EditText)view.findViewById(R.id.AuthorName)).getText().toString();
OsmandSettings.setUserName(ctx, author);
boolean added = addingComment(bug.getId(), text, author);
if (added) {
Toast.makeText(ctx, "Comment was successfully added", Toast.LENGTH_LONG).show();
clearCache();
if (OsmBugsLayer.this.view.getLayers().contains(OsmBugsLayer.this)) {
OsmBugsLayer.this.view.refreshMap();
}
} else {
Toast.makeText(ctx, "Exception occured : comment was not added", Toast.LENGTH_LONG).show();
}
}
});
builder.show();
}
public void closeBug(final Context ctx, LayoutInflater layoutInflater, final OpenStreetBug bug){
Builder builder = new AlertDialog.Builder(ctx);
builder.setTitle("Closing bug");
builder.setNegativeButton("Cancel", null);
builder.setPositiveButton("Close bug", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
boolean closed = closingBug(bug.getId());
if (closed) {
Toast.makeText(ctx, "Bug was successfully added", Toast.LENGTH_LONG).show();
clearCache();
if (OsmBugsLayer.this.view.getLayers().contains(OsmBugsLayer.this)) {
OsmBugsLayer.this.view.refreshMap();
}
} else {
Toast.makeText(ctx, "Exception occured : bug was not closed", Toast.LENGTH_LONG).show();
}
}
});
builder.show();
}
public static class OpenStreetBug {
private double latitude;
private double longitude;