implementing editing osm data

git-svn-id: https://osmand.googlecode.com/svn/trunk@167 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
Victor Shcherb 2010-06-16 15:05:06 +00:00
parent 881d88ef40
commit 9b6212b5ed
20 changed files with 901 additions and 120 deletions

View file

@ -31,17 +31,11 @@ public class ToDoConstants {
// DONE : back end (POI filter object, save, delete, read)
// TODO : activity to create/edit new index, activity to read both user defined/osm standard, add actions to remove/create
// 8. Enable change POI directly on map (requires OSM login)
// GOT : Victor
// DONE : Victor investigation
// TODO:
// 33. Build transport locations. Create transport index (transport-stops) (investigate)
// GOT : Victor
// DONE: Load transport routes in swing.
// TODO: Create transport index, create transport activity
// 36. Postcode search
// 37. Get rid of exit button (!). Think about when notification should go & how clear resources if it is necessary
// DONE :
@ -51,7 +45,6 @@ public class ToDoConstants {
// IDEA : Victor have ideas
// FUTURE RELEASES
// 43. Enable poi filter by name (?)
// 40. Support simple vector road rendering (require new index file) (?)
@ -70,6 +63,8 @@ public class ToDoConstants {
// BUGS Swing
// DONE ANDROID :
// 36. Postcode search
// 8. Enable change POI directly on map (requires OSM login)
// 45. Autozoom feature (for car navigation)
// 44. Introduce settings presets (car/bicycle/pedestrian/default) - show different icons for car (bigger), possibly change fonts, position
// 20. Implement save track/route to gpx

View file

@ -20,6 +20,23 @@ public class Amenity extends MapObject {
public Amenity(){
}
public String convertToAmenityTag(){
switch (getType()) {
case SHOP:
return OSMTagKey.SHOP.getValue();
case LEISURE:
return OSMTagKey.LEISURE.getValue();
case HISTORIC:
return OSMTagKey.HISTORIC.getValue();
case TOURISM:
return OSMTagKey.TOURISM.getValue();
case SPORT:
return OSMTagKey.SPORT.getValue();
default:
return OSMTagKey.AMENITY.getValue();
}
}
protected String getSubType(Entity node) {
if (node.getTag(OSMTagKey.SHOP) != null) {
return node.getTag(OSMTagKey.SHOP);
@ -44,8 +61,10 @@ public class Amenity extends MapObject {
return AmenityType.SHOP;
} else if(node.getTag(OSMTagKey.TOURISM) != null){
return AmenityType.TOURISM;
} else if(node.getTag(OSMTagKey.LEISURE) != null || node.getTag(OSMTagKey.SPORT) != null){
return AmenityType.LEISURE_AND_SPORT;
} else if(node.getTag(OSMTagKey.LEISURE) != null){
return AmenityType.LEISURE;
} else if(node.getTag(OSMTagKey.SPORT) != null){
return AmenityType.SPORT;
} else if(node.getTag(OSMTagKey.HISTORIC) != null){
return AmenityType.HISTORIC;
} else if(AmenityType.amenityMap.containsKey(node.getTag(OSMTagKey.AMENITY))){
@ -77,6 +96,8 @@ public class Amenity extends MapObject {
return true;
} else if(n.getTag(OSMTagKey.LEISURE) != null){
return true;
} else if(n.getTag(OSMTagKey.SPORT) != null){
return true;
} else if(n.getTag(OSMTagKey.TOURISM) != null){
return true;
} else if(n.getTag(OSMTagKey.HISTORIC) != null){

View file

@ -20,7 +20,8 @@ public enum AmenityType {
TOURISM, // [TAG] hotel, sights, museum ..
HISTORIC, // [TAG] historic places, monuments (should we unify tourism/historic)
SHOP, // [TAG] convenience (product), clothes...
LEISURE_AND_SPORT, // [TAG] sport
LEISURE, // [TAG] leisure
SPORT, // [TAG] sport
OTHER, // grave-yard, police, post-office [+Internet_access]
;
@ -151,76 +152,76 @@ public enum AmenityType {
amenityMap.put("video", AmenityType.SHOP);
amenityMap.put("dog_park", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("sports_centre", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("golf_course", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("stadium", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("track", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("pitch", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("water_park", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("marina", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("slipway", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("fishing", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("nature_reserve", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("park", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("playground", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("garden", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("common", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("ice_rink", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("miniature_golf", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("dance", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("dog_park", AmenityType.LEISURE);
amenityMap.put("sports_centre", AmenityType.LEISURE);
amenityMap.put("golf_course", AmenityType.LEISURE);
amenityMap.put("stadium", AmenityType.LEISURE);
amenityMap.put("track", AmenityType.LEISURE);
amenityMap.put("pitch", AmenityType.LEISURE);
amenityMap.put("water_park", AmenityType.LEISURE);
amenityMap.put("marina", AmenityType.LEISURE);
amenityMap.put("slipway", AmenityType.LEISURE);
amenityMap.put("fishing", AmenityType.LEISURE);
amenityMap.put("nature_reserve", AmenityType.LEISURE);
amenityMap.put("park", AmenityType.LEISURE);
amenityMap.put("playground", AmenityType.LEISURE);
amenityMap.put("garden", AmenityType.LEISURE);
amenityMap.put("common", AmenityType.LEISURE);
amenityMap.put("ice_rink", AmenityType.LEISURE);
amenityMap.put("miniature_golf", AmenityType.LEISURE);
amenityMap.put("dance", AmenityType.LEISURE);
amenityMap.put("9pin", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("10pin", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("archery", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("athletics", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("australian_football", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("baseball", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("basketball", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("beachvolleyball", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("boules", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("bowls", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("canoe", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("chess", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("climbing", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("cricket", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("cricket_nets", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("croquet", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("cycling", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("diving", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("dog_racing", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("equestrian", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("football", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("golf", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("gymnastics", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("hockey", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("horse_racing", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("ice_stock", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("korfball", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("motor", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("multi", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("orienteering", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("paddle_tennis", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("paragliding", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("pelota", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("racquet", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("rowing", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("rugby", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("shooting", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("skating", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("skateboard", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("skiing", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("soccer", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("swimming", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("table_tennis", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("team_handball", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("tennis", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("toboggan", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("volleyball", AmenityType.LEISURE_AND_SPORT);
amenityMap.put("9pin", AmenityType.SPORT);
amenityMap.put("10pin", AmenityType.SPORT);
amenityMap.put("archery", AmenityType.SPORT);
amenityMap.put("athletics", AmenityType.SPORT);
amenityMap.put("australian_football", AmenityType.SPORT);
amenityMap.put("baseball", AmenityType.SPORT);
amenityMap.put("basketball", AmenityType.SPORT);
amenityMap.put("beachvolleyball", AmenityType.SPORT);
amenityMap.put("boules", AmenityType.SPORT);
amenityMap.put("bowls", AmenityType.SPORT);
amenityMap.put("canoe", AmenityType.SPORT);
amenityMap.put("chess", AmenityType.SPORT);
amenityMap.put("climbing", AmenityType.SPORT);
amenityMap.put("cricket", AmenityType.SPORT);
amenityMap.put("cricket_nets", AmenityType.SPORT);
amenityMap.put("croquet", AmenityType.SPORT);
amenityMap.put("cycling", AmenityType.SPORT);
amenityMap.put("diving", AmenityType.SPORT);
amenityMap.put("dog_racing", AmenityType.SPORT);
amenityMap.put("equestrian", AmenityType.SPORT);
amenityMap.put("football", AmenityType.SPORT);
amenityMap.put("golf", AmenityType.SPORT);
amenityMap.put("gymnastics", AmenityType.SPORT);
amenityMap.put("hockey", AmenityType.SPORT);
amenityMap.put("horse_racing", AmenityType.SPORT);
amenityMap.put("ice_stock", AmenityType.SPORT);
amenityMap.put("korfball", AmenityType.SPORT);
amenityMap.put("motor", AmenityType.SPORT);
amenityMap.put("multi", AmenityType.SPORT);
amenityMap.put("orienteering", AmenityType.SPORT);
amenityMap.put("paddle_tennis", AmenityType.SPORT);
amenityMap.put("paragliding", AmenityType.SPORT);
amenityMap.put("pelota", AmenityType.SPORT);
amenityMap.put("racquet", AmenityType.SPORT);
amenityMap.put("rowing", AmenityType.SPORT);
amenityMap.put("rugby", AmenityType.SPORT);
amenityMap.put("shooting", AmenityType.SPORT);
amenityMap.put("skating", AmenityType.SPORT);
amenityMap.put("skateboard", AmenityType.SPORT);
amenityMap.put("skiing", AmenityType.SPORT);
amenityMap.put("soccer", AmenityType.SPORT);
amenityMap.put("swimming", AmenityType.SPORT);
amenityMap.put("table_tennis", AmenityType.SPORT);
amenityMap.put("team_handball", AmenityType.SPORT);
amenityMap.put("tennis", AmenityType.SPORT);
amenityMap.put("toboggan", AmenityType.SPORT);
amenityMap.put("volleyball", AmenityType.SPORT);
// amenity sub type
amenityMap.put("place_of_worship", AmenityType.HISTORIC);
amenityMap.put("place_of_worship", AmenityType.OTHER);
amenityMap.put("restaurant", AmenityType.SUSTENANCE);
amenityMap.put("food_court", AmenityType.SUSTENANCE);

View file

@ -2,8 +2,10 @@ package com.osmand.data.index;
public class IndexConstants {
// Important : Every time you change schema of db upgrade version!!!
// If you want that new application support old index : put upgrade code in android app ResourceManager
public final static int POI_TABLE_VERSION = 0;
public final static int ADDRESS_TABLE_VERSION = 0;
public final static int ADDRESS_TABLE_VERSION = 1;
public static final String POI_INDEX_DIR = "POI/";
public static final String ADDRESS_INDEX_DIR = "Address/";

View file

@ -20,6 +20,10 @@ public abstract class Entity {
return id;
}
public String removeTag(String key){
return tags.remove(key);
}
public String putTag(String key, String value){
if(tags == null){
tags = new LinkedHashMap<String, String>();

View file

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" android:orientation="vertical">
<TableLayout android:layout_width="fill_parent" android:layout_height="wrap_content">
<TableRow>
<TextView android:text="Name" android:id="@+id/TextView" android:layout_marginLeft="5dp" android:layout_width="fill_parent" android:layout_height="wrap_content"/>
<EditText android:text="" android:id="@+id/Name" android:layout_marginLeft="5dp" android:layout_marginRight="5dp" android:layout_height="wrap_content" android:layout_weight="1"></EditText>
</TableRow>
<TableRow>
<Button android:text="&lt;Type&gt;" android:id="@+id/TypeButton" android:layout_width="fill_parent" android:layout_height="wrap_content"/>
<AutoCompleteTextView android:text="" android:id="@+id/Type" android:layout_marginLeft="5dp" android:layout_marginRight="5dp" android:layout_height="wrap_content" android:layout_weight="1"/>
<!-- <EditText android:text="" android:id="@+id/Type" android:layout_marginLeft="5dp" android:layout_marginRight="5dp" android:layout_height="wrap_content" android:layout_weight="1"/> -->
</TableRow>
<TableRow>
<TextView android:text="Opening hours" android:id="@+id/TextView" android:layout_marginLeft="5dp" android:layout_width="fill_parent" android:layout_height="wrap_content"/>
<EditText android:text="" android:hint="Mo-Su 08:00-18:00" android:id="@+id/OpeningHours" android:layout_marginLeft="5dp" android:layout_marginRight="5dp" android:layout_height="wrap_content" android:layout_weight="1"></EditText>
</TableRow>
<TableRow>
<TextView android:text="Comment" android:id="@+id/TextView" android:layout_marginLeft="5dp" android:layout_width="fill_parent" android:layout_height="wrap_content"/>
<EditText android:text="POI changing" android:id="@+id/Comment" android:layout_marginLeft="5dp" android:layout_marginRight="5dp" android:layout_height="wrap_content" android:layout_weight="1"></EditText>
</TableRow>
</TableLayout>
<TextView android:text="All other tags are preserved" android:id="@+id/TextView" android:layout_marginLeft="5dp" android:layout_width="fill_parent" android:layout_height="wrap_content"/>
<LinearLayout android:id="@+id/LinearLayout" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal"
android:gravity="bottom|center">
<Button android:layout_width="125dp" android:layout_height="wrap_content" android:text="Commit" android:id="@+id/Commit"></Button>
<Button android:layout_width="125dp" android:layout_height="wrap_content" android:text="Cancel" android:id="@+id/Cancel"></Button>
</LinearLayout>
</LinearLayout>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:textSize="19dp" android:textStyle="bold">
</TextView>

View file

@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="user_password_descr">Input osm password</string>
<string name="user_password">User password</string>
<string name="osm_settings_descr">Specify osm settings: show bugs, osm login</string>
<string name="monitor_preferences_descr">Specify monitor settings : save track</string>
<string name="search_settings_descr">Specify search settings</string>

View file

@ -28,6 +28,7 @@
<PreferenceScreen android:title="@string/osm_settings" android:summary="@string/osm_settings_descr">
<CheckBoxPreference android:key="show_osm_bugs" android:title="@string/show_osm_bugs" android:summary="@string/show_osm_bugs_descr"></CheckBoxPreference>
<EditTextPreference android:title="@string/user_name" android:summary="@string/user_name_descr" android:key="user_name"></EditTextPreference>
<EditTextPreference android:title="@string/user_password" android:password="true" android:summary="@string/user_password_descr" android:key="user_password"></EditTextPreference>
</PreferenceScreen>
</PreferenceScreen>

View file

@ -79,6 +79,35 @@ public class AmenityIndexRepository {
return amenities;
}
public boolean addAmenity(long id, double latitude, double longitude, String name, String nameEn, AmenityType t, String subType, String openingHours){
assert IndexPoiTable.values().length == 8;
db.execSQL("INSERT INTO " + IndexPoiTable.getTable() + " VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
new Object[]{id, latitude, longitude, openingHours, name, nameEn,AmenityType.valueToString(t), subType});
return true;
}
public boolean updateAmenity(long id, double latitude, double longitude, String name, String nameEn, AmenityType t, String subType, String openingHours){
StringBuilder b = new StringBuilder();
b.append("UPDATE " + IndexPoiTable.getTable() + " SET ");
b.append(IndexPoiTable.LATITUDE.name()).append(" = ?").append(", ").
append(IndexPoiTable.LONGITUDE.name()).append(" = ?").append(", ").
append(IndexPoiTable.OPENING_HOURS.name()).append(" = ?").append(", ").
append(IndexPoiTable.NAME.name()).append(" = ?").append(", ").
append(IndexPoiTable.NAME_EN.name()).append(" = ?").append(", ").
append(IndexPoiTable.TYPE.name()).append(" = ?").append(", ").
append(IndexPoiTable.SUBTYPE.name()).append(" = ?").append(" ").
append(" WHERE ").append(IndexPoiTable.ID.name()).append(" = ?");
db.execSQL(b.toString(),
new Object[]{latitude, longitude, openingHours, name, nameEn,AmenityType.valueToString(t), subType, id});
return true;
}
public boolean deleteAmenity(long id){
db.execSQL("DELETE FROM " + IndexPoiTable.getTable()+ " WHERE id="+id);
return true;
}
public synchronized void clearCache(){
cachedAmenities.clear();
@ -168,6 +197,12 @@ public class AmenityIndexRepository {
return name;
}
public boolean checkContains(double latitude, double longitude){
if(latitude < dataTopLatitude && latitude > dataBottomLatitude && longitude > dataLeftLongitude && longitude < dataRightLongitude){
return true;
}
return false;
}
public boolean checkContains(double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude){
if(rightLongitude < dataLeftLongitude || leftLongitude > dataRightLongitude){

View file

@ -69,6 +69,17 @@ public class OsmandSettings {
return prefs.edit().putString(USER_NAME, name).commit();
}
public static final String USER_PASSWORD = "user_password";
public static String getUserPassword(Context ctx){
SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE);
return prefs.getString(USER_PASSWORD, "");
}
public static boolean setUserPassword(Context ctx, String name){
SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE);
return prefs.edit().putString(USER_PASSWORD, name).commit();
}
// this value string is synchronized with settings_pref.xml preference name
public static final String APPLICATION_MODE = "application_mode";
@ -299,7 +310,7 @@ public class OsmandSettings {
SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE);
Editor edit = prefs.edit().putLong(LAST_SEARCHED_CITY, cityId).putString(LAST_SEARCHED_STREET, "").putString(
LAST_SEARCHED_BUILDING, "");
if (prefs.contains(LAST_SEARCHED_INTERSECTED_STREET)) {
if(prefs.contains(LAST_SEARCHED_INTERSECTED_STREET)){
edit.putString(LAST_SEARCHED_INTERSECTED_STREET, "");
}
return edit.commit();

View file

@ -56,6 +56,7 @@ public class PoiFiltersHelper {
types.put(AmenityType.HISTORIC, null);
types.put(AmenityType.TOURISM, null);
list = new ArrayList<String>();
list.add("place_of_worship");
list.add("internet_access");
list.add("bench");
list.add("embassy");

View file

@ -1,7 +1,6 @@
package com.osmand;
import java.io.File;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@ -311,24 +310,21 @@ public class RegionAddressRepository {
public void preloadPostcodes(City city) {
if (city.getPostcodes().isEmpty()) {
// check if it possible to load postcodes
try {
Cursor query = db.query(true, IndexBuildingTable.getTable(), new String[]{IndexBuildingTable.POSTCODE.toString()},null,null,null,null,null,null);
log.debug("Start loading postcodes for " + city.getName());
if (query.moveToFirst()) {
do {
String postcode = query.getString(0);
if (postcode != null) {
city.getPostcodes().add(postcode);
}
} while (query.moveToNext());
}
query.close();
log.debug("Loaded " + city.getPostcodes().size() + " buildings");
} catch (Throwable t) {
log.warn("Can't load postcodes information. It might be that you are using old version of index.", t);
}
}
// check if it possible to load postcodes
Cursor query = db.query(true, IndexBuildingTable.getTable(), new String[] { IndexBuildingTable.POSTCODE.toString() }, null,
null, null, null, null, null);
log.debug("Start loading postcodes for " + city.getName());
if (query.moveToFirst()) {
do {
String postcode = query.getString(0);
if (postcode != null) {
city.getPostcodes().add(postcode);
}
} while (query.moveToNext());
}
query.close();
log.debug("Loaded " + city.getPostcodes().size() + " postcodes ");
}
}
public void preloadBuildings(Street street){

View file

@ -218,6 +218,15 @@ public class ResourceManager {
}
// //////////////////////////////////////////// Working with amenities ////////////////////////////////////////////////
public List<AmenityIndexRepository> searchRepositories(double latitude, double longitude) {
List<AmenityIndexRepository> repos = new ArrayList<AmenityIndexRepository>();
for (AmenityIndexRepository index : amenityRepositories) {
if (index.checkContains(latitude,longitude)) {
repos.add(index);
}
}
return repos;
}
public List<Amenity> searchAmenities(PoiFilter filter, double latitude, double longitude, int zoom, int limit) {
double tileNumberX = MapUtils.getTileNumberX(zoom, longitude);
double tileNumberY = MapUtils.getTileNumberY(zoom, latitude);

View file

@ -0,0 +1,534 @@
package com.osmand.activities;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.xml.sax.SAXException;
import org.xmlpull.v1.XmlSerializer;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.util.Xml;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.osmand.AmenityIndexRepository;
import com.osmand.LogUtil;
import com.osmand.OsmandSettings;
import com.osmand.R;
import com.osmand.ResourceManager;
import com.osmand.Version;
import com.osmand.data.Amenity;
import com.osmand.data.AmenityType;
import com.osmand.osm.Entity;
import com.osmand.osm.EntityInfo;
import com.osmand.osm.Node;
import com.osmand.osm.OSMSettings.OSMTagKey;
import com.osmand.osm.io.OsmBaseStorage;
import com.osmand.util.Base64;
import com.osmand.views.OsmandMapTileView;
public class EditingPOIActivity {
// private final static String SITE_API = "http://api06.dev.openstreetmap.org/";
private final static String SITE_API = "http://api.openstreetmap.org/";
private static final String DELETE_ACTION = "delete"; // NON-NLS
private static final String MODIFY_ACTION = "modify"; // NON-NLS
private static final String CREATE_ACTION = "create"; // NON-NLS
private Dialog dlg;
private final Context ctx;
private final OsmandMapTileView view;
private AutoCompleteTextView typeText;
private EditText nameText;
private Button typeButton;
private EditText openingHours;
private EntityInfo entityInfo;
private EditText commentText;
private final static Log log = LogUtil.getLog(EditingPOIActivity.class);
public EditingPOIActivity(final Context ctx){
this.ctx = ctx;
this.view = null;
}
public EditingPOIActivity(final Context ctx, OsmandMapTileView view){
this.ctx = ctx;
this.view = view;
}
public void showEditDialog(long id){
Node n = loadNode(id);
if(n != null){
dlg = new Dialog(ctx);
dlg.setTitle("Edit POI");
showDialog(n);
}
}
public void showCreateDialog(double latitude, double longitude){
dlg = new Dialog(ctx);
Node n = new Node(latitude, longitude, -1);
n.putTag(OSMTagKey.AMENITY.getValue(), "");
n.putTag(OSMTagKey.OPENING_HOURS.getValue(), "Mo-Su 08:00-20:00");
dlg.setTitle("Create POI");
showDialog(n);
}
public void showDeleteDialog(long id){
final Node n = loadNode(id);
if(n == null){
Toast.makeText(ctx, "POI doesn't found", Toast.LENGTH_LONG).show();
return;
}
Builder builder = new AlertDialog.Builder(ctx);
builder.setTitle("Are you sure to delete " + n.getTag(OSMTagKey.NAME)+" (enter comment) ?");
final EditText comment = new EditText(ctx);
comment.setText("Delete POI");
builder.setView(comment);
builder.setNegativeButton("Cancel", null);
builder.setPositiveButton("Delete", new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
String c = comment.getText().toString();
if(commitNode(DELETE_ACTION, n, entityInfo, c)){ // NON-NLS
Toast.makeText(ctx, "POI was successfully deleted", Toast.LENGTH_LONG).show();
if(view != null){
view.refreshMap();
}
}
}
});
builder.show();
}
private void showDialog(final Node n){
final Amenity a = new Amenity(n);
dlg.setContentView(R.layout.editing_poi);
nameText =((EditText)dlg.findViewById(R.id.Name));
nameText.setText(a.getName());
typeText = ((AutoCompleteTextView)dlg.findViewById(R.id.Type));
typeButton = ((Button)dlg.findViewById(R.id.TypeButton));
openingHours = ((EditText)dlg.findViewById(R.id.OpeningHours));
openingHours.setText(a.getOpeningHours());
typeText = ((AutoCompleteTextView)dlg.findViewById(R.id.Type));
typeText.setThreshold(1);
commentText = ((EditText)dlg.findViewById(R.id.Comment));
updateType(a);
typeButton.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
Builder builder = new AlertDialog.Builder(ctx);
String[] vals = new String[AmenityType.values().length];
for(int i=0; i<vals.length; i++){
vals[i] = AmenityType.toPublicString(AmenityType.values()[i]);
}
builder.setItems(vals, new Dialog.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
AmenityType aType = AmenityType.values()[which];
if(aType != a.getType()){
a.setType(aType);
a.setSubType("");
updateType(a);
}
}
});
builder.show();
}
});
((Button)dlg.findViewById(R.id.Cancel)).setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
dlg.dismiss();
}
});
((Button)dlg.findViewById(R.id.Commit)).setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
String msg = n.getId() == -1 ? "added" : "changed";
String action = n.getId() == -1 ? CREATE_ACTION: MODIFY_ACTION;
n.putTag(a.convertToAmenityTag(), typeText.getText().toString());
n.putTag(OSMTagKey.NAME.getValue(), nameText.getText().toString());
if(openingHours.getText().toString().length() == 0){
n.removeTag(OSMTagKey.OPENING_HOURS.getValue());
} else {
n.putTag(OSMTagKey.OPENING_HOURS.getValue(), openingHours.getText().toString());
}
if (commitNode(action, n, entityInfo, commentText.getText().toString())) {
Toast.makeText(ctx, "POI was successfully " + msg, Toast.LENGTH_LONG).show();
if(view != null){
view.refreshMap();
}
}
dlg.dismiss();
}
});
dlg.show();
}
private void updateType(Amenity a){
typeText.setText(a.getSubType());
typeButton.setText(AmenityType.toPublicString(a.getType()));
List<String> subCategories = AmenityType.getSubCategories(a.getType());
ArrayAdapter<Object> adapter = new ArrayAdapter<Object>(ctx, R.layout.list_textview, subCategories.toArray());
typeText.setAdapter(adapter);
}
protected String sendRequsetThroughHttpClient(String url, String requestMethod, String requestBody, String userOperation, boolean doAuthenticate) {
StringBuilder responseBody = new StringBuilder();
try {
HttpParams params = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(params, 15000);
DefaultHttpClient httpclient = new DefaultHttpClient(params);
if (doAuthenticate) {
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(OsmandSettings.getUserName(ctx) + ":"
+ OsmandSettings.getUserPassword(ctx));
httpclient.getCredentialsProvider().setCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT), credentials);
}
HttpRequestBase method = null;
if (requestMethod.equals("GET")) {
method = new HttpGet(url);
} else if (requestMethod.equals("POST")) {
method = new HttpPost(url);
} else if (requestMethod.equals("PUT")) {
method = new HttpPut(url);
} else if (requestMethod.equals("DELETE")) {
method = new HttpDelete(url);
} else {
throw new IllegalArgumentException(requestMethod + " is invalid method");
}
if (requestMethod.equals("PUT") || requestMethod.equals("POST") || requestMethod.equals("DELETE")) {
// TODO
// connection.setDoOutput(true);
// connection.setRequestProperty("Content-type", "text/xml");
// OutputStream out = connection.getOutputStream();
// if (requestBody != null) {
// BufferedWriter bwr = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"));
// bwr.write(requestBody);
// bwr.flush();
// }
// out.close();
}
HttpResponse response = httpclient.execute(method);
if(response.getStatusLine() == null ||
response.getStatusLine().getStatusCode() != 200){
String msg;
if(response.getStatusLine() != null){
msg = userOperation + " failed" ;
} else {
msg = userOperation + " failed " + response.getStatusLine().getStatusCode() +" : "+
response.getStatusLine().getReasonPhrase();
}
log.error(msg);
Toast.makeText(ctx, msg, Toast.LENGTH_LONG).show();
} else {
InputStream is = response.getEntity().getContent();
if (is != null) {
BufferedReader in = new BufferedReader(new InputStreamReader(is, "UTF-8"));
String s;
while ((s = in.readLine()) != null) {
responseBody.append(s);
responseBody.append("\n");
}
is.close();
}
httpclient.getConnectionManager().shutdown();
return responseBody.toString();
}
} catch (MalformedURLException e) {
log.error(userOperation + " failed", e);
Toast.makeText(ctx, "Unexpected exception while " + userOperation + " ocurred", Toast.LENGTH_LONG).show();
} catch (IOException e) {
log.error(userOperation + " failed", e);
Toast.makeText(ctx, "Input/output exception while " + userOperation + " ocurred", Toast.LENGTH_LONG).show();
}
return null;
}
private String sendRequest(String url, String requestMethod, String requestBody, String userOperation, boolean doAuthenticate) {
log.info("Sending request " + url);
// if(true){
// return sendRequsetThroughHttpClient(url, requestMethod, requestBody, userOperation, doAuthenticate);
// }
try {
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setConnectTimeout(15000);
connection.setRequestMethod(requestMethod);
StringBuilder responseBody = new StringBuilder();
if (doAuthenticate) {
String token = OsmandSettings.getUserName(ctx) + ":" + OsmandSettings.getUserPassword(ctx);
connection.addRequestProperty("Authorization", "Basic " + Base64.encode(token.getBytes("UTF-8")));
}
connection.setDoInput(true);
if (requestMethod.equals("PUT") || requestMethod.equals("POST") || requestMethod.equals("DELETE")) {
connection.setDoOutput(true);
connection.setRequestProperty("Content-type", "text/xml");
OutputStream out = connection.getOutputStream();
if (requestBody != null) {
BufferedWriter bwr = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"), 1024);
bwr.write(requestBody);
bwr.flush();
}
out.close();
}
connection.connect();
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
String msg = userOperation + " failed : " + connection.getResponseMessage();
log.error(msg);
Toast.makeText(ctx, msg, Toast.LENGTH_LONG).show();
} else {
log.info("Response : " + connection.getResponseMessage());
// populate return fields.
responseBody.setLength(0);
InputStream i = connection.getInputStream();
if (i != null) {
BufferedReader in = new BufferedReader(new InputStreamReader(i, "UTF-8"), 256);
String s;
boolean f = true;
while ((s = in.readLine()) != null) {
if(!f){
responseBody.append("\n");
} else {
f = false;
}
responseBody.append(s);
}
}
return responseBody.toString();
}
} catch (NullPointerException e) {
// that's tricky case why NPE is thrown to fix that problem httpClient could be used
String msg = "Authorization failed";
log.error(msg , e);
Toast.makeText(ctx, msg, Toast.LENGTH_LONG).show();
} catch (MalformedURLException e) {
log.error(userOperation + " failed" , e);
Toast.makeText(ctx, "Unexpected exception while "+ userOperation+" ocurred", Toast.LENGTH_LONG).show();
} catch (IOException e) {
log.error(userOperation + " failed" , e);
Toast.makeText(ctx, "Input/output exception while "+ userOperation+" ocurred", Toast.LENGTH_LONG).show();
}
return null;
}
public long openChangeSet(String comment,double lat, double lon) {
long id = -1;
StringWriter writer = new StringWriter(256);
XmlSerializer ser = Xml.newSerializer();
try {
ser.setOutput(writer);
ser.startDocument("UTF-8", true);
ser.startTag(null, "osm");
ser.startTag(null, "changeset");
ser.startTag(null, "tag");
ser.attribute(null, "k", "comment");
ser.attribute(null, "v", comment);
ser.endTag(null, "tag");
ser.startTag(null, "tag");
ser.attribute(null, "k", "created_by");
ser.attribute(null, "v", Version.APP_NAME_VERSION);
ser.endTag(null, "tag");
ser.endTag(null, "changeset");
ser.endTag(null, "osm");
ser.endDocument();
writer.close();
} catch (IOException e) {
log.error("Unhandled exception", e);
}
String response = sendRequest(SITE_API + "api/0.6/changeset/create/", "PUT", writer.getBuffer().toString(), "Opening changeset", true);
if (response != null && response.length() > 0) {
id = Long.parseLong(response);
}
return id;
}
public void closeChangeSet(long id){
String response = sendRequest(SITE_API+"api/0.6/changeset/"+id+"/close", "PUT", "", "Closing changeset", true);
log.info("Response : " + response);
}
private void writeNode(Node n, EntityInfo i, XmlSerializer ser, long changeSetId, String user) throws IllegalArgumentException, IllegalStateException, IOException{
ser.startTag(null, "node");
ser.attribute(null, "id", n.getId()+"");
ser.attribute(null, "lat", n.getLatitude()+"");
ser.attribute(null, "lon", n.getLongitude()+"");
if (i != null) {
// ser.attribute(null, "timestamp", i.getETimestamp());
// ser.attribute(null, "uid", i.getUid());
// ser.attribute(null, "user", i.getUser());
ser.attribute(null, "visible", i.getVisible());
ser.attribute(null, "version", i.getVersion());
}
ser.attribute(null, "changeset", changeSetId+"");
for(String k : n.getTagKeySet()){
String val = n.getTag(k);
ser.startTag(null, "tag");
ser.attribute(null, "k", k);
ser.attribute(null, "v", val);
ser.endTag(null, "tag");
}
ser.endTag(null, "node");
}
private void updateNodeInIndexes(String action, Node n){
List<AmenityIndexRepository> repos = ResourceManager.getResourceManager().searchRepositories(n.getLatitude(), n.getLongitude());
if(DELETE_ACTION.equals(action)){
for(AmenityIndexRepository r: repos){
r.deleteAmenity(n.getId());
r.clearCache();
}
} else {
boolean changed = MODIFY_ACTION.equals(action);
Amenity a = new Amenity(n);
for(AmenityIndexRepository r: repos){
if(changed){
r.updateAmenity(a.getId(), n.getLatitude(), n.getLongitude(), a.getName(), a.getEnName(), a.getType(), a.getSubType(), a.getOpeningHours());
} else {
r.addAmenity(a.getId(), n.getLatitude(), n.getLongitude(), a.getName(), a.getEnName(), a.getType(), a.getSubType(), a.getOpeningHours());
}
r.clearCache();
}
}
}
public boolean commitNode(String action, Node n, EntityInfo info, String comment){
if(info == null && !CREATE_ACTION.equals(action)){
Toast.makeText(ctx, "Info about node was not loaded", Toast.LENGTH_LONG).show();
return false;
}
long changeSetId = openChangeSet(comment, n.getLatitude(), n.getLongitude());
if(changeSetId < 0){
return false;
}
try {
StringWriter writer = new StringWriter(256);
XmlSerializer ser = Xml.newSerializer();
try {
ser.setOutput(writer);
ser.startDocument("UTF-8", true);
ser.startTag(null, "osmChange");
ser.attribute(null, "version", "0.6");
ser.attribute(null, "generator", Version.APP_NAME);
ser.startTag(null, action);
ser.attribute(null, "version", "0.6");
ser.attribute(null, "generator", Version.APP_NAME);
writeNode(n, info, ser, changeSetId, OsmandSettings.getUserName(ctx));
ser.endTag(null, action);
ser.endTag(null, "osmChange");
ser.endDocument();
} catch (IOException e) {
log.error("Unhandled exception", e);
}
String res = sendRequest(SITE_API+"api/0.6/changeset/"+changeSetId + "/upload", "POST",
writer.getBuffer().toString(), "Commiting node", true);
log.debug(res+"");
if (res != null) {
if (CREATE_ACTION.equals(action)) {
long newId = n.getId();
int i = res.indexOf("new_id=\"");
if (i > 0) {
i = i + "new_id=\"".length();
int end = res.indexOf("\"", i);
if (end > 0) {
newId = Long.parseLong(res.substring(i, end));
Node newN = new Node(n.getLatitude(), n.getLongitude(), newId);
for (String t : n.getTagKeySet()) {
newN.putTag(t, n.getTag(t));
}
n = newN;
}
}
}
updateNodeInIndexes(action, n);
return true;
}
return false;
} finally {
closeChangeSet(changeSetId);
}
}
public Node loadNode(long id) {
try {
String res = sendRequest(SITE_API+"api/0.6/node/"+id, "GET", null, "Loading poi " + id, false);
if(res != null){
OsmBaseStorage st = new OsmBaseStorage();
st.parseOSM(new ByteArrayInputStream(res.getBytes("UTF-8")), null, null, true);
Entity entity = st.getRegisteredEntities().get(id);
entityInfo = st.getRegisteredEntityInfo().get(id);
if(entity instanceof Node){
return (Node) entity;
}
}
} catch (IOException e) {
log.error("Loading node failed" + id, e);
Toast.makeText(ctx, "Input/output exception ocurred", Toast.LENGTH_LONG).show();
} catch (SAXException e) {
log.error("Loading node failed" + id, e);
Toast.makeText(ctx, "Input/output exception ocurred", Toast.LENGTH_LONG).show();
}
return null;
}
}

View file

@ -355,6 +355,7 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
if(!OsmandSettings.isShowingViewAngle(this)){
locationLayer.setHeading(null);
}
poiMapLayer.setFilter(OsmandSettings.getPoiFilterForMap(this));
mapView.setMapPosition(OsmandSettings.getPositionOnMap(this));
SharedPreferences prefs = getSharedPreferences(OsmandSettings.SHARED_PREFERENCES_NAME, MODE_WORLD_READABLE);
if(prefs != null && prefs.contains(OsmandSettings.LAST_KNOWN_MAP_LAT)){
@ -363,7 +364,7 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
mapView.setZoom(OsmandSettings.getLastKnownMapZoom(this));
}
backToLocation.setVisibility(View.INVISIBLE);
poiMapLayer.setFilter(OsmandSettings.getPoiFilterForMap(this));
if(mapView.getLayers().contains(poiMapLayer) != OsmandSettings.isShowingPoiOverMap(this)){
@ -491,7 +492,7 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
protected void contextMenuPoint(final double latitude, final double longitude){
Builder builder = new AlertDialog.Builder(this);
builder.setItems(new String[]{"Navigate to point", "Add to favourites", "Update map", "Open osm bug"}, new DialogInterface.OnClickListener(){
builder.setItems(new String[]{"Navigate to point", "Add to favourites", "Update map", "Open osm bug", "Create POI"}, new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
@ -503,6 +504,9 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat
reloadTile(mapView.getZoom(), latitude, longitude);
} else if(which == 3){
osmBugsLayer.openBug(MapActivity.this, getLayoutInflater(), mapView, latitude, longitude);
} else if(which == 4){
EditingPOIActivity activity = new EditingPOIActivity(MapActivity.this, mapView);
activity.showCreateDialog(latitude, longitude);
}
}
});

View file

@ -37,6 +37,7 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
private Preference saveCurrentTrack;
private ListPreference applicationMode;
private CheckBoxPreference autoZoom;
private EditTextPreference userPassword;
@Override
public void onCreate(Bundle savedInstanceState) {
@ -64,6 +65,8 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
useEnglishNames.setOnPreferenceChangeListener(this);
userName = (EditTextPreference) screen.findPreference(OsmandSettings.USER_NAME);
userName.setOnPreferenceChangeListener(this);
userPassword = (EditTextPreference) screen.findPreference(OsmandSettings.USER_PASSWORD);
userPassword.setOnPreferenceChangeListener(this);
saveTrackToGpx =(CheckBoxPreference) screen.findPreference(OsmandSettings.SAVE_TRACK_TO_GPX);
saveTrackToGpx.setOnPreferenceChangeListener(this);
@ -101,6 +104,7 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
positionOnMap.setEntries(e);
positionOnMap.setValueIndex(OsmandSettings.getPositionOnMap(this));
userName.setText(OsmandSettings.getUserName(this));
userPassword.setText(OsmandSettings.getUserPassword(this));
saveTrackInterval.setEntries(new String[]{"1 second", "2 seconds", "5 seconds", "15 seconds", "30 seconds", "1 minute", "5 minute"});
saveTrackInterval.setEntryValues(new String[]{"1", "2", "5", "15", "30", "60", "300"});
@ -170,6 +174,9 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
} else if(preference == saveTrackInterval){
edit.putInt(OsmandSettings.SAVE_TRACK_INTERVAL, Integer.parseInt(newValue.toString()));
edit.commit();
} else if(preference == userPassword){
edit.putString(OsmandSettings.USER_PASSWORD, (String) newValue);
edit.commit();
} else if(preference == userName){
edit.putString(OsmandSettings.USER_NAME, (String) newValue);
edit.commit();

View file

@ -8,7 +8,6 @@ import java.util.List;
import android.app.ListActivity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
@ -102,16 +101,11 @@ public class SearchPOIActivity extends ListActivity {
}
}
public void onListItemClick(ListView parent, View v, int position, long id) {
SharedPreferences prefs = getSharedPreferences(OsmandSettings.SHARED_PREFERENCES_NAME, MODE_WORLD_READABLE);
if (prefs != null) {
Amenity amenity = ((AmenityAdapter)getListAdapter()).getItem(position);
OsmandSettings.setMapLocationToShow(this, amenity.getLocation().getLatitude(), amenity.getLocation().getLongitude());
Intent newIntent = new Intent(SearchPOIActivity.this, MapActivity.class);
startActivity(newIntent);
}
Amenity amenity = ((AmenityAdapter) getListAdapter()).getItem(position);
OsmandSettings.setMapLocationToShow(this, amenity.getLocation().getLatitude(), amenity.getLocation().getLongitude());
Intent newIntent = new Intent(SearchPOIActivity.this, MapActivity.class);
startActivity(newIntent);
}
class AmenityAdapter extends ArrayAdapter<Amenity> {

View file

@ -0,0 +1,93 @@
package com.osmand.util;
/**
* @source http://www.javaworld.com/javaworld/javatips/jw-javatip47.html -- 24.11.2008, (mb)
*/
public class Base64 {
/*******************************************************************************************************************
* BASE 64 encoding of a String or an array of bytes. See also RFC 1421.
*
* @author Unknown
* @author David W. Croft
* @version 1998-06-08
******************************************************************************************************************/
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
public static final char[] alphabet = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 0 to 7
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 8 to 15
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 16 to 23
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', // 24 to 31
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', // 32 to 39
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', // 40 to 47
'w', 'x', 'y', 'z', '0', '1', '2', '3', // 48 to 55
'4', '5', '6', '7', '8', '9', '+', '/' }; // 56 to 63
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
public static String encode(final String s)
//////////////////////////////////////////////////////////////////////
{
return encode(s.getBytes());
}
public static String encode(final byte[] octetString)
//////////////////////////////////////////////////////////////////////
{
int bits24;
int bits6;
final char[] out = new char[((octetString.length - 1) / 3 + 1) * 4];
int outIndex = 0;
int i = 0;
while ((i + 3) <= octetString.length) {
// store the octets
bits24 = (octetString[i++] & 0xFF) << 16;
bits24 |= (octetString[i++] & 0xFF) << 8;
bits24 |= (octetString[i++] & 0xFF) << 0;
bits6 = (bits24 & 0x00FC0000) >> 18;
out[outIndex++] = alphabet[bits6];
bits6 = (bits24 & 0x0003F000) >> 12;
out[outIndex++] = alphabet[bits6];
bits6 = (bits24 & 0x00000FC0) >> 6;
out[outIndex++] = alphabet[bits6];
bits6 = (bits24 & 0x0000003F);
out[outIndex++] = alphabet[bits6];
}
if (octetString.length - i == 2) {
// store the octets
bits24 = (octetString[i] & 0xFF) << 16;
bits24 |= (octetString[i + 1] & 0xFF) << 8;
bits6 = (bits24 & 0x00FC0000) >> 18;
out[outIndex++] = alphabet[bits6];
bits6 = (bits24 & 0x0003F000) >> 12;
out[outIndex++] = alphabet[bits6];
bits6 = (bits24 & 0x00000FC0) >> 6;
out[outIndex++] = alphabet[bits6];
// padding
out[outIndex++] = '=';
} else if (octetString.length - i == 1) {
// store the octets
bits24 = (octetString[i] & 0xFF) << 16;
bits6 = (bits24 & 0x00FC0000) >> 18;
out[outIndex++] = alphabet[bits6];
bits6 = (bits24 & 0x0003F000) >> 12;
out[outIndex++] = alphabet[bits6];
// padding
out[outIndex++] = '=';
out[outIndex++] = '=';
}
return new String(out);
}
}

View file

@ -3,6 +3,10 @@ package com.osmand.views;
import java.util.ArrayList;
import java.util.List;
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;
@ -14,6 +18,7 @@ import android.widget.Toast;
import com.osmand.OsmandSettings;
import com.osmand.PoiFilter;
import com.osmand.ResourceManager;
import com.osmand.activities.EditingPOIActivity;
import com.osmand.data.Amenity;
import com.osmand.osm.MapUtils;
@ -32,6 +37,27 @@ public class POIMapLayer implements OsmandMapLayer {
@Override
public boolean onLongPressEvent(PointF point) {
final Amenity n = getAmenityFromPoint(point);
if(n != null){
Context ctx = view.getContext();
Builder builder = new AlertDialog.Builder(ctx);
final EditingPOIActivity edit = new EditingPOIActivity(ctx, view);
builder.setItems(new String[]{"Modify", "Delete"}, new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
if(which == 0){
edit.showEditDialog(n.getId());
} else {
edit.showDeleteDialog(n.getId());
}
}
});
builder.show();
return true;
}
return false;
}
@ -43,9 +69,7 @@ public class POIMapLayer implements OsmandMapLayer {
this.filter = filter;
}
@Override
public boolean onTouchEvent(PointF point) {
public Amenity getAmenityFromPoint(PointF point){
if (objects != null) {
int ex = (int) point.x;
int ey = (int) point.y;
@ -56,18 +80,28 @@ public class POIMapLayer implements OsmandMapLayer {
int x = view.getRotatedMapXForPoint(n.getLocation().getLatitude(), n.getLocation().getLongitude());
int y = view.getRotatedMapYForPoint(n.getLocation().getLatitude(), n.getLocation().getLongitude());
if (Math.abs(x - ex) <= radius && Math.abs(y - ey) <= radius) {
String format = n.getSimpleFormat(OsmandSettings.usingEnglishNames(view.getContext()));
if(n.getOpeningHours() != null){
format += "\n Opening hours : " + n.getOpeningHours();
}
Toast.makeText(view.getContext(), format, Toast.LENGTH_SHORT).show();
return true;
return n;
}
}
} catch (IndexOutOfBoundsException e) {
// that's really rare case, but is much efficient than introduce synchronized block
}
}
return null;
}
@Override
public boolean onTouchEvent(PointF point) {
Amenity n = getAmenityFromPoint(point);
if(n != null){
String format = n.getSimpleFormat(OsmandSettings.usingEnglishNames(view.getContext()));
if(n.getOpeningHours() != null){
format += "\nOpening hours : " + n.getOpeningHours();
}
Toast.makeText(view.getContext(), format, Toast.LENGTH_SHORT).show();
return true;
}
return false;
}