Merge branch 'offlinePoiEdit'

This commit is contained in:
Victor Shcherb 2012-02-06 00:58:46 +01:00
commit ef8685b8b8
15 changed files with 1257 additions and 387 deletions

View file

@ -57,6 +57,8 @@
</activity>
<activity android:name="net.osmand.plus.activities.TestVoiceActivity"></activity>
<activity android:name="net.osmand.plus.activities.LocalIndexesActivity" android:label="@string/local_index_descr_title"></activity>
<activity android:name="net.osmand.plus.activities.LocalOpenstreetmapActivity" android:label="@string/local_openstreetmap_descr_title"></activity>
<service android:process="net.osmand.plus" android:label="@string/process_navigation_service" android:name="net.osmand.plus.NavigationService">
<intent-filter><action android:name="net.osmand.plus.NavigationService"></action></intent-filter>
</service>

View file

@ -0,0 +1,15 @@
<?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">
<LinearLayout android:id="@+id/UploadAll" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="3dp">
<Button android:id="@+id/UploadAllButton" android:layout_width="wrap_content" android:layout_gravity="right" android:layout_height="wrap_content" android:text="@string/local_openstreetmap_uploadall"
android:layout_marginLeft = "3dp" android:layout_marginTop ="3dp" android:layout_marginRight = "3dp"/>
</LinearLayout>
<ExpandableListView android:id="@android:id/list" android:layout_width="fill_parent" android:layout_weight="1" android:layout_height="wrap_content"
android:layout_marginLeft="3dp" android:layout_marginTop="3dp" android:layout_marginRight="3dp" ></ExpandableListView>
</LinearLayout>

View file

@ -0,0 +1,7 @@
<?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="wrap_content"
android:orientation="vertical">
<TextView android:id="@+id/local_openstreetmap_name" android:gravity="center_vertical" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:textSize="20sp" android:layout_marginLeft="8dp"></TextView>
</LinearLayout>

View file

@ -0,0 +1,8 @@
<?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="wrap_content">
<TextView android:id="@+id/local_openstreetmap_category_name" android:gravity="center_vertical" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:textSize="21sp" android:layout_marginLeft="40dp"></TextView>
</LinearLayout>

View file

@ -1,5 +1,17 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<resources>
<string name="update_poi_does_not_change_indexes">POI changes inside application do not affect downloaded map files, changes are saved to local file instead.</string>
<string name="local_openstreetmap_uploading_poi">Uploading POI</string>
<string name="local_openstreetmap_poi_were_uploaded">{0} POI were uploaded</string>
<string name="local_openstreetmap_uploadall">Upload All POI</string>
<string name="local_openstreetmap_items"></string>
<string name="local_openstreetmap_show_poi">Show POI on Map</string>
<string name="local_openstreetmap_upload">Upload modification to OSM</string>
<string name="local_openstreetmap_delete">Delete POI modification</string>
<string name="local_openstreetmap_descr_title">Asynchrone Openstreetmap POI Edition:</string>
<string name="local_openstreetmap_settings">Local Openstreetmap Points</string>
<string name="local_openstreetmap_settings_descr">Local Points Saved in DB</string>
<string name="live_monitoring_descr">Enable sending HTTP requests to a specified web service</string>
<string name="live_monitoring">Enable Live Tracking</string>
<string name="live_monitoring_interval_descr">Specify Live Tracking interval</string>
@ -155,7 +167,6 @@
<string name="poi_filter_by_name">Search by name</string>
<string name="old_poi_file_should_be_deleted">The POI data file \'%1$s\' is redundant and can be deleted.</string>
<string name="update_poi_file_not_found">Local file to maintain POI changes not found and could not be created.</string>
<string name="update_poi_does_not_change_indexes">POI changes inside application do not affect downloaded map files, changes are saved to local file instead.</string>
<string name="button_upgrade_osmandplus">Upgrade Osmand+</string>
<string name="map_version_changed_info">Server contains map files not compatible with your current version of the application. To download and use them, please upgrade the application to newer version.</string>

View file

@ -107,6 +107,7 @@
<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>
<Preference android:title="@string/local_openstreetmap_settings" android:key="local_openstreetmap_points" android:summary="@string/local_openstreetmap_settings_descr"></Preference>
</PreferenceCategory>
<PreferenceCategory android:title="OsmAnd debugging and development">
<CheckBoxPreference android:key="native_rendering" android:title="Native rendering" android:summary="Vector maps may display faster. May not work well on some devices."></CheckBoxPreference>

View file

@ -0,0 +1,88 @@
package net.osmand;
import java.util.Map;
import net.osmand.data.Amenity;
import net.osmand.data.AmenityType;
import net.osmand.osm.EntityInfo;
import net.osmand.osm.MapRenderingTypes;
import net.osmand.osm.MapUtils;
import net.osmand.osm.Node;
import net.osmand.osm.OSMSettings.OSMTagKey;
import net.osmand.plus.OpenstreetmapsDbHelper;
import org.apache.commons.logging.Log;
import android.content.Context;
public class OpenstreetmapLocalUtil implements OpenstreetmapUtil {
private final Context ctx;
private final OpenstreetmapsDbHelper db;
public final static Log log = LogUtil.getLog(OpenstreetmapLocalUtil.class);
public OpenstreetmapLocalUtil(Context uiContext){
this.ctx = uiContext;
this.db = new OpenstreetmapsDbHelper(ctx);
}
@Override
public EntityInfo getEntityInfo() {
return new EntityInfo();
}
@Override
public boolean commitNodeImpl(Action action, Node n, EntityInfo info, String comment){
OpenstreetmapPoint p = new OpenstreetmapPoint();
p.setEntity(n);
p.setAction(action);
p.setComment(comment);
return db.addOpenstreetmap(p);
}
@Override
public Node loadNode(Amenity n) {
if(n.getId() % 2 == 1){
// that's way id
return null;
}
long nodeId = n.getId() >> 1;
// EntityId id = new Entity.EntityId(EntityType.NODE, nodeId);
Node entity = new Node(n.getLocation().getLatitude(),
n.getLocation().getLongitude(),
nodeId);
Map<AmenityType, Map<String, String>> typeNameToTagVal = MapRenderingTypes.getDefault().getAmenityTypeNameToTagVal();
AmenityType type = n.getType();
String tag = type.getDefaultTag();
String subType = n.getSubType();
String val = subType;
if (typeNameToTagVal.containsKey(type)) {
Map<String, String> map = typeNameToTagVal.get(type);
if (map.containsKey(subType)) {
String res = map.get(subType);
if (res != null) {
int i = res.indexOf(' ');
if (i != -1) {
tag = res.substring(0, i);
val = res.substring(i + 1);
} else {
tag = res;
}
}
}
}
entity.putTag(tag, val);
entity.putTag(OSMTagKey.NAME.getValue(), n.getName());
entity.putTag(OSMTagKey.OPENING_HOURS.getValue(), n.getOpeningHours());
// check whether this is node (because id of node could be the same as relation)
if(entity != null && MapUtils.getDistance(entity.getLatLon(), n.getLocation()) < 50){
return entity;
}
return null;
}
}

View file

@ -0,0 +1,106 @@
package net.osmand;
import java.io.Serializable;
import net.osmand.OpenstreetmapRemoteUtil;
import net.osmand.data.AmenityType;
import net.osmand.osm.Node;
import net.osmand.osm.OSMSettings.OSMTagKey;
public class OpenstreetmapPoint implements Serializable {
private static final long serialVersionUID = 729654300829771467L;
private Node entity;
private OpenstreetmapUtil.Action action;
private String comment;
private boolean stored = false;
public OpenstreetmapPoint(){
}
public long getId() {
return entity.getId();
}
public String getName() {
String ret = entity.getTag(OSMTagKey.NAME.getValue());
if (ret == null)
return "";
return ret;
}
public String getType() {
String type = AmenityType.valueToString(AmenityType.OTHER);
for(String k : entity.getTagKeySet()){
if (!OSMTagKey.NAME.getValue().equals(k) &&
!OSMTagKey.OPENING_HOURS.getValue().equals(k)) {
type = k;
break;
}
}
return type;
}
public String getSubtype() {
return entity.getTag(this.getType());
}
public double getLatitude() {
return entity.getLatitude();
}
public double getLongitude() {
return entity.getLongitude();
}
public String getOpeninghours() {
String ret = entity.getTag(OSMTagKey.OPENING_HOURS.getValue());
if (ret == null)
return "";
return entity.getTag(ret);
}
public Node getEntity() {
return entity;
}
public OpenstreetmapUtil.Action getAction() {
return action;
}
public String getComment() {
return comment;
}
public boolean isStored() {
return stored;
}
public void setEntity(Node entity) {
this.entity = entity;
}
public void setAction(String action) {
this.action = OpenstreetmapRemoteUtil.actionString.get(action);
}
public void setAction(OpenstreetmapUtil.Action action) {
this.action = action;
}
public void setComment(String comment) {
this.comment = comment;
}
public void setStored(boolean stored) {
this.stored = stored;
}
@Override
public String toString() {
return new StringBuffer("Openstreetmap Point ").append(this.getAction()).append(" ").append(this.getName())
.append(" (").append(this.getId()).append("): [")
.append(this.getType()).append("/").append(this.getSubtype())
.append(" (").append(this.getLatitude()).append(", ").append(this.getLongitude())
.append(")]").toString();
}
}

View file

@ -0,0 +1,436 @@
package net.osmand;
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.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import net.osmand.data.Amenity;
import net.osmand.osm.Entity;
import net.osmand.osm.Entity.EntityId;
import net.osmand.osm.Entity.EntityType;
import net.osmand.osm.EntityInfo;
import net.osmand.osm.MapUtils;
import net.osmand.osm.Node;
import net.osmand.osm.io.OsmBaseStorage;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R;
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.content.Context;
import android.util.Xml;
import android.view.View;
import android.widget.Toast;
public class OpenstreetmapRemoteUtil implements OpenstreetmapUtil {
// private final static String SITE_API = "http://api06.dev.openstreetmap.org/";
private final static String SITE_API = "http://api.openstreetmap.org/"; //$NON-NLS-1$
public static final Map<Action, String> stringAction = new HashMap<Action, String>();
public static final Map<String, Action> actionString = new HashMap<String, Action>();
static {
stringAction.put(Action.CREATE, "create");
stringAction.put(Action.MODIFY, "modify");
stringAction.put(Action.DELETE, "delete");
actionString.put("create", Action.CREATE);
actionString.put("modify", Action.MODIFY);
actionString.put("delete", Action.DELETE);
};
private static final long NO_CHANGESET_ID = -1;
private final Context ctx;
private final View view;
private EntityInfo entityInfo;
// reuse changeset
private long changeSetId = NO_CHANGESET_ID;
private long changeSetTimeStamp = NO_CHANGESET_ID;
public final static Log log = LogUtil.getLog(OpenstreetmapRemoteUtil.class);
public OpenstreetmapRemoteUtil(Context uiContext, View view){
this.ctx = uiContext;
this.view = view;
}
@Override
public EntityInfo getEntityInfo() {
return entityInfo;
}
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.getOsmandSettings(ctx).USER_NAME.get() + ":" //$NON-NLS-1$
+ OsmandSettings.getOsmandSettings(ctx).USER_PASSWORD.get());
httpclient.getCredentialsProvider().setCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT), credentials);
}
HttpRequestBase method = null;
if (requestMethod.equals("GET")) { //$NON-NLS-1$
method = new HttpGet(url);
} else if (requestMethod.equals("POST")) { //$NON-NLS-1$
method = new HttpPost(url);
} else if (requestMethod.equals("PUT")) { //$NON-NLS-1$
method = new HttpPut(url);
} else if (requestMethod.equals("DELETE")) { //$NON-NLS-1$
method = new HttpDelete(url);
} else {
throw new IllegalArgumentException(requestMethod + " is invalid method"); //$NON-NLS-1$
}
if (requestMethod.equals("PUT") || requestMethod.equals("POST") || requestMethod.equals("DELETE")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
// TODO add when needed
// 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 + " " +ctx.getString(R.string.failed_op); //$NON-NLS-1$
} else {
msg = userOperation + " " + ctx.getString(R.string.failed_op) + response.getStatusLine().getStatusCode() + " : " + //$NON-NLS-1$//$NON-NLS-2$
response.getStatusLine().getReasonPhrase();
}
log.error(msg);
showWarning(msg);
} else {
InputStream is = response.getEntity().getContent();
if (is != null) {
BufferedReader in = new BufferedReader(new InputStreamReader(is, "UTF-8")); //$NON-NLS-1$
String s;
while ((s = in.readLine()) != null) {
responseBody.append(s);
responseBody.append("\n"); //$NON-NLS-1$
}
is.close();
}
httpclient.getConnectionManager().shutdown();
return responseBody.toString();
}
} catch (MalformedURLException e) {
log.error(userOperation + " failed", e); //$NON-NLS-1$
showWarning(MessageFormat.format(ctx.getResources().getString(R.string.poi_error_unexpected_template), userOperation));
} catch (IOException e) {
log.error(userOperation + " failed", e); //$NON-NLS-1$
showWarning(MessageFormat.format(ctx.getResources().getString(R.string.poi_error_unexpected_template), userOperation));
}
return null;
}
private String sendRequest(String url, String requestMethod, String requestBody, String userOperation, boolean doAuthenticate) {
log.info("Sending request " + url); //$NON-NLS-1$
// 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.getOsmandSettings(ctx).USER_NAME.get() + ":" + OsmandSettings.getOsmandSettings(ctx).USER_PASSWORD.get(); //$NON-NLS-1$
connection.addRequestProperty("Authorization", "Basic " + Base64.encode(token.getBytes("UTF-8"))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
connection.setDoInput(true);
if (requestMethod.equals("PUT") || requestMethod.equals("POST") || requestMethod.equals("DELETE")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
connection.setDoOutput(true);
connection.setRequestProperty("Content-type", "text/xml"); //$NON-NLS-1$ //$NON-NLS-2$
OutputStream out = connection.getOutputStream();
if (requestBody != null) {
BufferedWriter bwr = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"), 1024); //$NON-NLS-1$
bwr.write(requestBody);
bwr.flush();
}
out.close();
}
connection.connect();
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
String msg = userOperation + " " + ctx.getString(R.string.failed_op) + " : " + connection.getResponseMessage(); //$NON-NLS-1$//$NON-NLS-2$
log.error(msg);
showWarning(msg);
} else {
log.info("Response : " + connection.getResponseMessage()); //$NON-NLS-1$
// populate return fields.
responseBody.setLength(0);
InputStream i = connection.getInputStream();
if (i != null) {
BufferedReader in = new BufferedReader(new InputStreamReader(i, "UTF-8"), 256); //$NON-NLS-1$
String s;
boolean f = true;
while ((s = in.readLine()) != null) {
if(!f){
responseBody.append("\n"); //$NON-NLS-1$
} 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 = ctx.getString(R.string.auth_failed);
log.error(msg , e);
showWarning(msg);
} catch (MalformedURLException e) {
log.error(userOperation + " " + ctx.getString(R.string.failed_op) , e); //$NON-NLS-1$
showWarning(MessageFormat.format(ctx.getResources().getString(R.string.poi_error_unexpected_template), userOperation));
} catch (IOException e) {
log.error(userOperation + " " + ctx.getString(R.string.failed_op) , e); //$NON-NLS-1$
showWarning(MessageFormat.format(ctx.getResources().getString(R.string.poi_error_io_error_template), userOperation));
}
return null;
}
public long openChangeSet(String comment) {
long id = -1;
StringWriter writer = new StringWriter(256);
XmlSerializer ser = Xml.newSerializer();
try {
ser.setOutput(writer);
ser.startDocument("UTF-8", true); //$NON-NLS-1$
ser.startTag(null, "osm"); //$NON-NLS-1$
ser.startTag(null, "changeset"); //$NON-NLS-1$
ser.startTag(null, "tag"); //$NON-NLS-1$
ser.attribute(null, "k", "comment"); //$NON-NLS-1$ //$NON-NLS-2$
ser.attribute(null, "v", comment); //$NON-NLS-1$
ser.endTag(null, "tag"); //$NON-NLS-1$
ser.startTag(null, "tag"); //$NON-NLS-1$
ser.attribute(null, "k", "created_by"); //$NON-NLS-1$ //$NON-NLS-2$
ser.attribute(null, "v", Version.getFullVersion(ctx)); //$NON-NLS-1$
ser.endTag(null, "tag"); //$NON-NLS-1$
ser.endTag(null, "changeset"); //$NON-NLS-1$
ser.endTag(null, "osm"); //$NON-NLS-1$
ser.endDocument();
writer.close();
} catch (IOException e) {
log.error("Unhandled exception", e); //$NON-NLS-1$
}
String response = sendRequest(SITE_API + "api/0.6/changeset/create/", "PUT", writer.getBuffer().toString(), ctx.getString(R.string.opening_changeset), true); //$NON-NLS-1$ //$NON-NLS-2$
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", "", ctx.getString(R.string.closing_changeset), true); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
log.info("Response : " + response); //$NON-NLS-1$
}
private void writeNode(Node n, EntityInfo i, XmlSerializer ser, long changeSetId, String user) throws IllegalArgumentException, IllegalStateException, IOException{
ser.startTag(null, "node"); //$NON-NLS-1$
ser.attribute(null, "id", n.getId()+""); //$NON-NLS-1$ //$NON-NLS-2$
ser.attribute(null, "lat", n.getLatitude()+""); //$NON-NLS-1$ //$NON-NLS-2$
ser.attribute(null, "lon", n.getLongitude()+""); //$NON-NLS-1$ //$NON-NLS-2$
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()); //$NON-NLS-1$
ser.attribute(null, "version", i.getVersion()); //$NON-NLS-1$
}
ser.attribute(null, "changeset", changeSetId+""); //$NON-NLS-1$ //$NON-NLS-2$
for(String k : n.getTagKeySet()){
String val = n.getTag(k);
ser.startTag(null, "tag"); //$NON-NLS-1$
ser.attribute(null, "k", k); //$NON-NLS-1$
ser.attribute(null, "v", val); //$NON-NLS-1$
ser.endTag(null, "tag"); //$NON-NLS-1$
}
ser.endTag(null, "node"); //$NON-NLS-1$
}
private boolean isNewChangesetRequired() {
// first commit
if (changeSetId == NO_CHANGESET_ID){
return true;
}
long now = System.currentTimeMillis();
// changeset is idle for more than 30 minutes (1 hour according specification)
if (now - changeSetTimeStamp > 30 * 60 * 1000) {
return true;
}
return false;
}
@Override
public boolean commitNodeImpl(Action action, Node n, EntityInfo info, String comment){
if (isNewChangesetRequired()){
changeSetId = openChangeSet(comment);
changeSetTimeStamp = System.currentTimeMillis();
}
if(changeSetId < 0){
return false;
}
try {
StringWriter writer = new StringWriter(256);
XmlSerializer ser = Xml.newSerializer();
try {
ser.setOutput(writer);
ser.startDocument("UTF-8", true); //$NON-NLS-1$
ser.startTag(null, "osmChange"); //$NON-NLS-1$
ser.attribute(null, "version", "0.6"); //$NON-NLS-1$ //$NON-NLS-2$
ser.attribute(null, "generator", Version.getAppName(ctx)); //$NON-NLS-1$
ser.startTag(null, stringAction.get(action));
ser.attribute(null, "version", "0.6"); //$NON-NLS-1$ //$NON-NLS-2$
ser.attribute(null, "generator", Version.getAppName(ctx)); //$NON-NLS-1$
writeNode(n, info, ser, changeSetId, OsmandSettings.getOsmandSettings(ctx).USER_NAME.get());
ser.endTag(null, stringAction.get(action));
ser.endTag(null, "osmChange"); //$NON-NLS-1$
ser.endDocument();
} catch (IOException e) {
log.error("Unhandled exception", e); //$NON-NLS-1$
}
String res = sendRequest(SITE_API+"api/0.6/changeset/"+changeSetId + "/upload", "POST", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
writer.getBuffer().toString(), ctx.getString(R.string.commiting_node), true);
log.debug(res+""); //$NON-NLS-1$
if (res != null) {
if (Action.CREATE == action) {
long newId = n.getId();
int i = res.indexOf("new_id=\""); //$NON-NLS-1$
if (i > 0) {
i = i + "new_id=\"".length(); //$NON-NLS-1$
int end = res.indexOf("\"", i); //$NON-NLS-1$
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;
}
}
}
changeSetTimeStamp = System.currentTimeMillis();
return true;
}
return false;
} finally {
// reuse changeset, do not close
//closeChangeSet(changeSetId);
}
}
public EntityInfo loadNode(Node n) {
long nodeId = n.getId() >> 1;
try {
String res = sendRequest(SITE_API + "api/0.6/node/"+nodeId, "GET", null, ctx.getString(R.string.loading_poi_obj) + nodeId, false); //$NON-NLS-1$ //$NON-NLS-2$
if(res != null){
OsmBaseStorage st = new OsmBaseStorage();
st.parseOSM(new ByteArrayInputStream(res.getBytes("UTF-8")), null, null, true); //$NON-NLS-1$
EntityId id = new Entity.EntityId(EntityType.NODE, nodeId);
// Node entity = (Node) st.getRegisteredEntities().get(id);
entityInfo = st.getRegisteredEntityInfo().get(id);
return entityInfo;
}
} catch (IOException e) {
log.error("Loading node failed " + nodeId, e); //$NON-NLS-1$
Toast.makeText(ctx, ctx.getResources().getString(R.string.error_io_error), Toast.LENGTH_LONG).show();
} catch (SAXException e) {
log.error("Loading node failed " + nodeId, e); //$NON-NLS-1$
Toast.makeText(ctx, ctx.getResources().getString(R.string.error_io_error), Toast.LENGTH_LONG).show();
}
return null;
}
@Override
public Node loadNode(Amenity n) {
if(n.getId() % 2 == 1){
// that's way id
return null;
}
long nodeId = n.getId() >> 1;
try {
String res = sendRequest(SITE_API+"api/0.6/node/"+nodeId, "GET", null, ctx.getString(R.string.loading_poi_obj) + nodeId, false); //$NON-NLS-1$ //$NON-NLS-2$
if(res != null){
OsmBaseStorage st = new OsmBaseStorage();
st.parseOSM(new ByteArrayInputStream(res.getBytes("UTF-8")), null, null, true); //$NON-NLS-1$
EntityId id = new Entity.EntityId(EntityType.NODE, nodeId);
Node entity = (Node) st.getRegisteredEntities().get(id);
entityInfo = st.getRegisteredEntityInfo().get(id);
// check whether this is node (because id of node could be the same as relation)
if(entity != null && MapUtils.getDistance(entity.getLatLon(), n.getLocation()) < 50){
return entity;
}
return null;
}
} catch (IOException e) {
log.error("Loading node failed " + nodeId, e); //$NON-NLS-1$
Toast.makeText(ctx, ctx.getResources().getString(R.string.error_io_error), Toast.LENGTH_LONG).show();
} catch (SAXException e) {
log.error("Loading node failed " + nodeId, e); //$NON-NLS-1$
Toast.makeText(ctx, ctx.getResources().getString(R.string.error_io_error), Toast.LENGTH_LONG).show();
}
return null;
}
private void showWarning(final String msg){
view.post(new Runnable(){
@Override
public void run() {
Toast.makeText(ctx, msg, Toast.LENGTH_LONG).show();
}
});
}
}

View file

@ -0,0 +1,16 @@
package net.osmand;
import net.osmand.data.Amenity;
import net.osmand.osm.EntityInfo;
import net.osmand.osm.Node;
public interface OpenstreetmapUtil {
public static enum Action {CREATE, MODIFY, DELETE};
public EntityInfo getEntityInfo();
public boolean commitNodeImpl(Action action, Node n, EntityInfo info, String comment);
public Node loadNode(Amenity n);
}

View file

@ -0,0 +1,122 @@
package net.osmand.plus;
import java.util.ArrayList;
import java.util.List;
import net.osmand.OpenstreetmapPoint;
import net.osmand.OpenstreetmapRemoteUtil;
import net.osmand.osm.Node;
import net.osmand.osm.OSMSettings.OSMTagKey;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class OpenstreetmapsDbHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 1;
public static final String OPENSTREETMAP_DB_NAME = "openstreetmap"; //$NON-NLS-1$
private static final String OPENSTREETMAP_TABLE_NAME = "openstreetmap"; //$NON-NLS-1$
private static final String OPENSTREETMAP_COL_ID = "id"; //$NON-NLS-1$
private static final String OPENSTREETMAP_COL_NAME = "name"; //$NON-NLS-1$
private static final String OPENSTREETMAP_COL_TYPE = "type"; //$NON-NLS-1$
private static final String OPENSTREETMAP_COL_SUBTYPE = "subtype"; //$NON-NLS-1$
private static final String OPENSTREETMAP_COL_LAT = "latitude"; //$NON-NLS-1$
private static final String OPENSTREETMAP_COL_LON = "longitude"; //$NON-NLS-1$
private static final String OPENSTREETMAP_COL_ACTION = "action"; //$NON-NLS-1$
private static final String OPENSTREETMAP_COL_COMMENT = "comment"; //$NON-NLS-1$
private static final String OPENSTREETMAP_COL_OPENINGHOURS = "openinghours"; //$NON-NLS-1$
private static final String OPENSTREETMAP_TABLE_CREATE = "CREATE TABLE " + OPENSTREETMAP_TABLE_NAME + " (" + //$NON-NLS-1$ //$NON-NLS-2$
OPENSTREETMAP_COL_ID + " INTEGER, " + OPENSTREETMAP_COL_NAME + " TEXT, " + OPENSTREETMAP_COL_TYPE + " TEXT, " + OPENSTREETMAP_COL_SUBTYPE + " TEXT, " + //$NON-NLS-1$ //$NON-NLS-2$
OPENSTREETMAP_COL_LAT + " double, " + OPENSTREETMAP_COL_LON + " double, " + //$NON-NLS-1$ //$NON-NLS-2$
OPENSTREETMAP_COL_ACTION + " TEXT, " + OPENSTREETMAP_COL_COMMENT + " TEXT, " + OPENSTREETMAP_COL_OPENINGHOURS + " TEXT);"; //$NON-NLS-1$ //$NON-NLS-2$
private List<OpenstreetmapPoint> cachedOpenstreetmapPoints = new ArrayList<OpenstreetmapPoint>();
// private final Context context;
public OpenstreetmapsDbHelper(Context context) {
super(context, OPENSTREETMAP_DB_NAME, null, DATABASE_VERSION);
// this.context = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(OPENSTREETMAP_TABLE_CREATE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public List<OpenstreetmapPoint> getOpenstreetmapPoints() {
checkOpenstreetmapPoints();
return cachedOpenstreetmapPoints;
}
public boolean addOpenstreetmap(OpenstreetmapPoint p) {
checkOpenstreetmapPoints();
SQLiteDatabase db = getWritableDatabase();
if (db != null) {
db.execSQL("INSERT INTO " + OPENSTREETMAP_TABLE_NAME +
" (" + OPENSTREETMAP_COL_ID + ", " + OPENSTREETMAP_COL_NAME + ", " + OPENSTREETMAP_COL_TYPE + ", " + OPENSTREETMAP_COL_SUBTYPE + ", " + OPENSTREETMAP_COL_LAT + "," + OPENSTREETMAP_COL_LON + "," + OPENSTREETMAP_COL_ACTION + "," + OPENSTREETMAP_COL_COMMENT + "," + OPENSTREETMAP_COL_OPENINGHOURS + ")" +
" VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", new Object[] { p.getId(), p.getName(), p.getType(), p.getSubtype(), p.getLatitude(), p.getLongitude(), OpenstreetmapRemoteUtil.stringAction.get(p.getAction()), p.getComment(), p.getOpeninghours() }); //$NON-NLS-1$ //$NON-NLS-2$
cachedOpenstreetmapPoints.add(p);
p.setStored(true);
return true;
}
return false;
}
public boolean deleteOpenstreetmap(OpenstreetmapPoint p) {
checkOpenstreetmapPoints();
SQLiteDatabase db = getWritableDatabase();
if (db != null) {
db.execSQL("DELETE FROM " + OPENSTREETMAP_TABLE_NAME +
" WHERE " + OPENSTREETMAP_COL_ID + " = ? AND " +
OPENSTREETMAP_COL_NAME + " = ? AND " +
OPENSTREETMAP_COL_TYPE + " = ? AND " +
OPENSTREETMAP_COL_SUBTYPE + " = ? AND " +
OPENSTREETMAP_COL_LAT + " = ? AND " +
OPENSTREETMAP_COL_LON + " = ? AND " +
OPENSTREETMAP_COL_ACTION + " = ? AND " +
OPENSTREETMAP_COL_COMMENT + " = ? AND " +
OPENSTREETMAP_COL_OPENINGHOURS + " = ?",
new Object[] { p.getId(), p.getName(), p.getType(), p.getSubtype(), p.getLatitude(), p.getLongitude(), OpenstreetmapRemoteUtil.stringAction.get(p.getAction()), p.getComment(), p.getOpeninghours() }); //$NON-NLS-1$ //$NON-NLS-2$
cachedOpenstreetmapPoints.remove(p);
p.setStored(false);
return true;
}
return false;
}
private void checkOpenstreetmapPoints(){
SQLiteDatabase db = getWritableDatabase();
if (db != null) {
Cursor query = db.rawQuery("SELECT " + OPENSTREETMAP_COL_ID + ", " + OPENSTREETMAP_COL_NAME + ", " + OPENSTREETMAP_COL_TYPE + ", " + OPENSTREETMAP_COL_SUBTYPE + ", " + OPENSTREETMAP_COL_LAT + "," + OPENSTREETMAP_COL_LON + "," + OPENSTREETMAP_COL_ACTION + "," + OPENSTREETMAP_COL_COMMENT + "," + OPENSTREETMAP_COL_OPENINGHOURS + " FROM " + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
OPENSTREETMAP_TABLE_NAME, null);
cachedOpenstreetmapPoints.clear();
if (query.moveToFirst()) {
do {
String name = query.getString(1);
OpenstreetmapPoint p = new OpenstreetmapPoint();
Node entity = new Node(query.getDouble(4),
query.getDouble(5),
query.getLong(0));
entity.putTag(query.getString(2), query.getString(3));
entity.putTag(OSMTagKey.NAME.getValue(), name);
String openingHours = query.getString(8);
if (openingHours != null && openingHours.length() > 0)
entity.putTag(OSMTagKey.OPENING_HOURS.getValue(), openingHours);
p.setEntity(entity);
p.setStored(true);
p.setAction(query.getString(6));
p.setComment(query.getString(7));
cachedOpenstreetmapPoints.add(p);
} while (query.moveToNext());
}
query.close();
}
}
}

View file

@ -439,6 +439,8 @@ public class OsmandSettings {
public final OsmandPreference<String> USER_PASSWORD =
new StringPreference("user_password", "", true);
public static final String LOCAL_OPENSTREETMAP_POINTS = "local_openstreetmap_points";
// this value string is synchronized with settings_pref.xml preference name
public final OsmandPreference<DayNightMode> DAYNIGHT_MODE =

View file

@ -1,17 +1,5 @@
package net.osmand.plus.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.text.MessageFormat;
import java.util.ArrayList;
import java.util.LinkedHashSet;
@ -19,48 +7,26 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import net.osmand.Base64;
import net.osmand.LogUtil;
import net.osmand.OpenstreetmapLocalUtil;
import net.osmand.OpenstreetmapRemoteUtil;
import net.osmand.OpenstreetmapUtil;
import net.osmand.OsmAndFormatter;
import net.osmand.Version;
import net.osmand.data.Amenity;
import net.osmand.data.AmenityType;
import net.osmand.osm.Entity;
import net.osmand.osm.EntityInfo;
import net.osmand.osm.MapRenderingTypes;
import net.osmand.osm.MapUtils;
import net.osmand.osm.Node;
import net.osmand.osm.OpeningHoursParser;
import net.osmand.osm.Entity.EntityId;
import net.osmand.osm.Entity.EntityType;
import net.osmand.osm.OSMSettings.OSMTagKey;
import net.osmand.osm.OpeningHoursParser;
import net.osmand.osm.OpeningHoursParser.BasicDayOpeningHourRule;
import net.osmand.osm.OpeningHoursParser.OpeningHoursRule;
import net.osmand.osm.io.OsmBaseStorage;
import net.osmand.plus.AmenityIndexRepositoryOdb;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R;
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.AlertDialog.Builder;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
@ -69,7 +35,6 @@ import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.text.method.LinkMovementMethod;
import android.util.Xml;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
@ -80,29 +45,16 @@ import android.widget.Toast;
public class EditingPOIActivity implements DialogProvider {
// private final static String SITE_API = "http://api06.dev.openstreetmap.org/";
private final static String SITE_API = "http://api.openstreetmap.org/"; //$NON-NLS-1$
private static final String DELETE_ACTION = "delete"; //$NON-NLS-1$
private static final String MODIFY_ACTION = "modify"; //$NON-NLS-1$
private static final String CREATE_ACTION = "create"; //$NON-NLS-1$
private static final long NO_CHANGESET_ID = -1;
private final MapActivity ctx;
private final OpenstreetmapUtil openstreetmapUtil;
private AutoCompleteTextView typeText;
private EditText nameText;
private Button typeButton;
private Button openHoursButton;
private EditText openingHours;
private EntityInfo entityInfo;
private EditText commentText;
// reuse changeset
private long changeSetId = NO_CHANGESET_ID;
private long changeSetTimeStamp = NO_CHANGESET_ID;
private final static Log log = LogUtil.getLog(EditingPOIActivity.class);
// private final static Log log = LogUtil.getLog(EditingPOIActivity.class);
/* dialog stuff */
private static final int DIALOG_CREATE_POI = 200;
@ -119,10 +71,17 @@ public class EditingPOIActivity implements DialogProvider {
public EditingPOIActivity(MapActivity uiContext){
this.ctx = uiContext;
OsmandSettings settings = OsmandSettings.getOsmandSettings(ctx);
if(!settings.isInternetConnectionAvailable(true)){
this.openstreetmapUtil = new OpenstreetmapLocalUtil(ctx);
} else {
this.openstreetmapUtil = new OpenstreetmapRemoteUtil(ctx, ctx.getMapView());
}
}
public void showEditDialog(Amenity editA){
Node n = loadNode(editA);
Node n = openstreetmapUtil.loadNode(editA);
if(n != null){
showPOIDialog(DIALOG_EDIT_POI, n, editA.getType(), editA.getSubType());
} else {
@ -144,7 +103,7 @@ public class EditingPOIActivity implements DialogProvider {
}
public void showDeleteDialog(Amenity a){
final Node n = loadNode(a);
final Node n = openstreetmapUtil.loadNode(a);
if(n == null){
Toast.makeText(ctx, ctx.getResources().getString(R.string.poi_error_poi_not_found), Toast.LENGTH_LONG).show();
return;
@ -172,7 +131,7 @@ public class EditingPOIActivity implements DialogProvider {
public void onClick(DialogInterface dialog, int which) {
Node n = (Node) args.getSerializable(KEY_AMENITY_NODE);
String c = comment.getText().toString();
commitNode(DELETE_ACTION, n, entityInfo, c, new Runnable(){
commitNode(OpenstreetmapUtil.Action.DELETE, n, openstreetmapUtil.getEntityInfo(), c, new Runnable(){
@Override
public void run() {
Toast.makeText(ctx, ctx.getResources().getString(R.string.poi_remove_success), Toast.LENGTH_LONG).show();
@ -285,7 +244,7 @@ public class EditingPOIActivity implements DialogProvider {
Resources resources = v.getResources();
final String msg = n.getId() == -1 ? resources.getString(R.string.poi_action_add) : resources
.getString(R.string.poi_action_change);
String action = n.getId() == -1 ? CREATE_ACTION : MODIFY_ACTION;
OpenstreetmapUtil.Action action = n.getId() == -1 ? OpenstreetmapUtil.Action.CREATE : OpenstreetmapUtil.Action.MODIFY;
Map<AmenityType, Map<String, String>> typeNameToTagVal = MapRenderingTypes.getDefault().getAmenityTypeNameToTagVal();
AmenityType type = a.getType();
String tag = type.getDefaultTag();
@ -313,7 +272,7 @@ public class EditingPOIActivity implements DialogProvider {
} else {
n.putTag(OSMTagKey.OPENING_HOURS.getValue(), openingHours.getText().toString());
}
commitNode(action, n, entityInfo, commentText.getText().toString(), new Runnable() {
commitNode(action, n, openstreetmapUtil.getEntityInfo(), commentText.getText().toString(), new Runnable() {
@Override
public void run() {
Toast.makeText(ctx, MessageFormat.format(ctx.getResources().getString(R.string.poi_action_succeded_template), msg),
@ -355,15 +314,6 @@ public class EditingPOIActivity implements DialogProvider {
updateSubTypesAdapter(a.getType());
}
private void showWarning(final String msg){
ctx.getMapView().post(new Runnable(){
@Override
public void run() {
Toast.makeText(ctx, msg, Toast.LENGTH_LONG).show();
}
});
}
private Dialog createOpenHoursDlg(){
List<OpeningHoursRule> time = OpeningHoursParser.parseOpenedHours(openingHours.getText().toString());
@ -405,215 +355,7 @@ public class EditingPOIActivity implements DialogProvider {
}
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.getOsmandSettings(ctx).USER_NAME.get() + ":" //$NON-NLS-1$
+ OsmandSettings.getOsmandSettings(ctx).USER_PASSWORD.get());
httpclient.getCredentialsProvider().setCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT), credentials);
}
HttpRequestBase method = null;
if (requestMethod.equals("GET")) { //$NON-NLS-1$
method = new HttpGet(url);
} else if (requestMethod.equals("POST")) { //$NON-NLS-1$
method = new HttpPost(url);
} else if (requestMethod.equals("PUT")) { //$NON-NLS-1$
method = new HttpPut(url);
} else if (requestMethod.equals("DELETE")) { //$NON-NLS-1$
method = new HttpDelete(url);
} else {
throw new IllegalArgumentException(requestMethod + " is invalid method"); //$NON-NLS-1$
}
if (requestMethod.equals("PUT") || requestMethod.equals("POST") || requestMethod.equals("DELETE")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
// TODO add when needed
// 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 + " " +ctx.getString(R.string.failed_op); //$NON-NLS-1$
} else {
msg = userOperation + " " + ctx.getString(R.string.failed_op) + response.getStatusLine().getStatusCode() + " : " + //$NON-NLS-1$//$NON-NLS-2$
response.getStatusLine().getReasonPhrase();
}
log.error(msg);
showWarning(msg);
} else {
InputStream is = response.getEntity().getContent();
if (is != null) {
BufferedReader in = new BufferedReader(new InputStreamReader(is, "UTF-8")); //$NON-NLS-1$
String s;
while ((s = in.readLine()) != null) {
responseBody.append(s);
responseBody.append("\n"); //$NON-NLS-1$
}
is.close();
}
httpclient.getConnectionManager().shutdown();
return responseBody.toString();
}
} catch (MalformedURLException e) {
log.error(userOperation + " failed", e); //$NON-NLS-1$
showWarning(MessageFormat.format(ctx.getResources().getString(R.string.poi_error_unexpected_template), userOperation));
} catch (IOException e) {
log.error(userOperation + " failed", e); //$NON-NLS-1$
showWarning(MessageFormat.format(ctx.getResources().getString(R.string.poi_error_unexpected_template), userOperation));
}
return null;
}
private String sendRequest(String url, String requestMethod, String requestBody, String userOperation, boolean doAuthenticate) {
log.info("Sending request " + url); //$NON-NLS-1$
// 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.getOsmandSettings(ctx).USER_NAME.get() + ":" + OsmandSettings.getOsmandSettings(ctx).USER_PASSWORD.get(); //$NON-NLS-1$
connection.addRequestProperty("Authorization", "Basic " + Base64.encode(token.getBytes("UTF-8"))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
connection.setDoInput(true);
if (requestMethod.equals("PUT") || requestMethod.equals("POST") || requestMethod.equals("DELETE")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
connection.setDoOutput(true);
connection.setRequestProperty("Content-type", "text/xml"); //$NON-NLS-1$ //$NON-NLS-2$
OutputStream out = connection.getOutputStream();
if (requestBody != null) {
BufferedWriter bwr = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"), 1024); //$NON-NLS-1$
bwr.write(requestBody);
bwr.flush();
}
out.close();
}
connection.connect();
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
String msg = userOperation + " " + ctx.getString(R.string.failed_op) + " : " + connection.getResponseMessage(); //$NON-NLS-1$//$NON-NLS-2$
log.error(msg);
showWarning(msg);
} else {
log.info("Response : " + connection.getResponseMessage()); //$NON-NLS-1$
// populate return fields.
responseBody.setLength(0);
InputStream i = connection.getInputStream();
if (i != null) {
BufferedReader in = new BufferedReader(new InputStreamReader(i, "UTF-8"), 256); //$NON-NLS-1$
String s;
boolean f = true;
while ((s = in.readLine()) != null) {
if(!f){
responseBody.append("\n"); //$NON-NLS-1$
} 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 = ctx.getString(R.string.auth_failed);
log.error(msg , e);
showWarning(msg);
} catch (MalformedURLException e) {
log.error(userOperation + " " + ctx.getString(R.string.failed_op) , e); //$NON-NLS-1$
showWarning(MessageFormat.format(ctx.getResources().getString(R.string.poi_error_unexpected_template), userOperation));
} catch (IOException e) {
log.error(userOperation + " " + ctx.getString(R.string.failed_op) , e); //$NON-NLS-1$
showWarning(MessageFormat.format(ctx.getResources().getString(R.string.poi_error_io_error_template), userOperation));
}
return null;
}
public long openChangeSet(String comment) {
long id = -1;
StringWriter writer = new StringWriter(256);
XmlSerializer ser = Xml.newSerializer();
try {
ser.setOutput(writer);
ser.startDocument("UTF-8", true); //$NON-NLS-1$
ser.startTag(null, "osm"); //$NON-NLS-1$
ser.startTag(null, "changeset"); //$NON-NLS-1$
ser.startTag(null, "tag"); //$NON-NLS-1$
ser.attribute(null, "k", "comment"); //$NON-NLS-1$ //$NON-NLS-2$
ser.attribute(null, "v", comment); //$NON-NLS-1$
ser.endTag(null, "tag"); //$NON-NLS-1$
ser.startTag(null, "tag"); //$NON-NLS-1$
ser.attribute(null, "k", "created_by"); //$NON-NLS-1$ //$NON-NLS-2$
ser.attribute(null, "v", Version.getFullVersion(ctx)); //$NON-NLS-1$
ser.endTag(null, "tag"); //$NON-NLS-1$
ser.endTag(null, "changeset"); //$NON-NLS-1$
ser.endTag(null, "osm"); //$NON-NLS-1$
ser.endDocument();
writer.close();
} catch (IOException e) {
log.error("Unhandled exception", e); //$NON-NLS-1$
}
String response = sendRequest(SITE_API + "api/0.6/changeset/create/", "PUT", writer.getBuffer().toString(), ctx.getString(R.string.opening_changeset), true); //$NON-NLS-1$ //$NON-NLS-2$
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", "", ctx.getString(R.string.closing_changeset), true); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
log.info("Response : " + response); //$NON-NLS-1$
}
private void writeNode(Node n, EntityInfo i, XmlSerializer ser, long changeSetId, String user) throws IllegalArgumentException, IllegalStateException, IOException{
ser.startTag(null, "node"); //$NON-NLS-1$
ser.attribute(null, "id", n.getId()+""); //$NON-NLS-1$ //$NON-NLS-2$
ser.attribute(null, "lat", n.getLatitude()+""); //$NON-NLS-1$ //$NON-NLS-2$
ser.attribute(null, "lon", n.getLongitude()+""); //$NON-NLS-1$ //$NON-NLS-2$
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()); //$NON-NLS-1$
ser.attribute(null, "version", i.getVersion()); //$NON-NLS-1$
}
ser.attribute(null, "changeset", changeSetId+""); //$NON-NLS-1$ //$NON-NLS-2$
for(String k : n.getTagKeySet()){
String val = n.getTag(k);
ser.startTag(null, "tag"); //$NON-NLS-1$
ser.attribute(null, "k", k); //$NON-NLS-1$
ser.attribute(null, "v", val); //$NON-NLS-1$
ser.endTag(null, "tag"); //$NON-NLS-1$
}
ser.endTag(null, "node"); //$NON-NLS-1$
}
private void updateNodeInIndexes(String action, Node n) {
private void updateNodeInIndexes(OpenstreetmapUtil.Action action, Node n) {
final OsmandApplication app = ctx.getMyApplication();
final AmenityIndexRepositoryOdb repo = app.getResourceManager().getUpdatablePoiDb();
ctx.getMapView().post(new Runnable() {
@ -630,12 +372,12 @@ public class EditingPOIActivity implements DialogProvider {
});
// delete all amenities with same id
if (DELETE_ACTION.equals(action) || MODIFY_ACTION.equals(action)) {
if (OpenstreetmapUtil.Action.DELETE == action || OpenstreetmapUtil.Action.MODIFY == action) {
repo.deleteAmenities(n.getId() << 1);
repo.clearCache();
}
// add amenities
if (!DELETE_ACTION.equals(action)) {
if (OpenstreetmapUtil.Action.DELETE != action) {
List<Amenity> ams = Amenity.parseAmenities(n, new ArrayList<Amenity>());
for (Amenity a : ams) {
repo.addAmenity(a);
@ -646,8 +388,8 @@ public class EditingPOIActivity implements DialogProvider {
}
public void commitNode(final String action, final Node n, final EntityInfo info, final String comment, final Runnable successAction) {
if (info == null && !CREATE_ACTION.equals(action)) {
public void commitNode(final OpenstreetmapUtil.Action action, final Node n, final EntityInfo info, final String comment, final Runnable successAction) {
if (info == null && OpenstreetmapUtil.Action.CREATE != action) {
Toast.makeText(ctx, ctx.getResources().getString(R.string.poi_error_info_not_loaded), Toast.LENGTH_LONG).show();
return;
}
@ -657,7 +399,8 @@ public class EditingPOIActivity implements DialogProvider {
@Override
public void run() {
try {
if (commitNodeImpl(action, n, info, comment)) {
if (openstreetmapUtil.commitNodeImpl(action, n, info, comment)) {
updateNodeInIndexes(action, n);
ctx.getMapView().post(successAction);
}
} finally {
@ -668,110 +411,7 @@ public class EditingPOIActivity implements DialogProvider {
}, "EditingPoi").start(); //$NON-NLS-1$
}
private boolean isNewChangesetRequired() {
// first commit
if (changeSetId == NO_CHANGESET_ID){
return true;
}
long now = System.currentTimeMillis();
// changeset is idle for more than 30 minutes (1 hour according specification)
if (now - changeSetTimeStamp > 30 * 60 * 1000) {
return true;
}
return false;
}
public boolean commitNodeImpl(String action, Node n, EntityInfo info, String comment){
if (isNewChangesetRequired()){
changeSetId = openChangeSet(comment);
changeSetTimeStamp = System.currentTimeMillis();
}
if(changeSetId < 0){
return false;
}
try {
StringWriter writer = new StringWriter(256);
XmlSerializer ser = Xml.newSerializer();
try {
ser.setOutput(writer);
ser.startDocument("UTF-8", true); //$NON-NLS-1$
ser.startTag(null, "osmChange"); //$NON-NLS-1$
ser.attribute(null, "version", "0.6"); //$NON-NLS-1$ //$NON-NLS-2$
ser.attribute(null, "generator", Version.getFullVersion(ctx)); //$NON-NLS-1$
ser.startTag(null, action);
ser.attribute(null, "version", "0.6"); //$NON-NLS-1$ //$NON-NLS-2$
ser.attribute(null, "generator", Version.getFullVersion(ctx)); //$NON-NLS-1$
writeNode(n, info, ser, changeSetId, OsmandSettings.getOsmandSettings(ctx).USER_NAME.get());
ser.endTag(null, action);
ser.endTag(null, "osmChange"); //$NON-NLS-1$
ser.endDocument();
} catch (IOException e) {
log.error("Unhandled exception", e); //$NON-NLS-1$
}
String res = sendRequest(SITE_API+"api/0.6/changeset/"+changeSetId + "/upload", "POST", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
writer.getBuffer().toString(), ctx.getString(R.string.commiting_node), true);
log.debug(res+""); //$NON-NLS-1$
if (res != null) {
if (CREATE_ACTION.equals(action)) {
long newId = n.getId();
int i = res.indexOf("new_id=\""); //$NON-NLS-1$
if (i > 0) {
i = i + "new_id=\"".length(); //$NON-NLS-1$
int end = res.indexOf("\"", i); //$NON-NLS-1$
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);
changeSetTimeStamp = System.currentTimeMillis();
return true;
}
return false;
} finally {
// reuse changeset, do not close
//closeChangeSet(changeSetId);
}
}
public Node loadNode(Amenity n) {
if(n.getId() % 2 == 1){
// that's way id
return null;
}
long nodeId = n.getId() >> 1;
try {
String res = sendRequest(SITE_API+"api/0.6/node/"+nodeId, "GET", null, ctx.getString(R.string.loading_poi_obj) + nodeId, false); //$NON-NLS-1$ //$NON-NLS-2$
if(res != null){
OsmBaseStorage st = new OsmBaseStorage();
st.parseOSM(new ByteArrayInputStream(res.getBytes("UTF-8")), null, null, true); //$NON-NLS-1$
EntityId id = new Entity.EntityId(EntityType.NODE, nodeId);
Node entity = (Node) st.getRegisteredEntities().get(id);
entityInfo = st.getRegisteredEntityInfo().get(id);
// check whether this is node (because id of node could be the same as relation)
if(entity != null && MapUtils.getDistance(entity.getLatLon(), n.getLocation()) < 50){
return entity;
}
return null;
}
} catch (IOException e) {
log.error("Loading node failed " + nodeId, e); //$NON-NLS-1$
Toast.makeText(ctx, ctx.getResources().getString(R.string.error_io_error), Toast.LENGTH_LONG).show();
} catch (SAXException e) {
log.error("Loading node failed " + nodeId, e); //$NON-NLS-1$
Toast.makeText(ctx, ctx.getResources().getString(R.string.error_io_error), Toast.LENGTH_LONG).show();
}
return null;
}
@Override
public Dialog onCreateDialog(int id) {
Bundle args = dialogBundle;

View file

@ -0,0 +1,410 @@
package net.osmand.plus.activities;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.app.ExpandableListActivity;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.BaseExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
import android.widget.ExpandableListView.OnChildClickListener;
import android.widget.TextView;
import android.widget.Toast;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import net.osmand.OpenstreetmapPoint;
import net.osmand.OpenstreetmapUtil;
import net.osmand.OpenstreetmapRemoteUtil;
import net.osmand.LogUtil;
import net.osmand.osm.EntityInfo;
import net.osmand.plus.AmenityIndexRepositoryOdb;
import net.osmand.plus.OpenstreetmapsDbHelper;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.ProgressDialogImplementation;
import net.osmand.plus.R;
public class LocalOpenstreetmapActivity extends ExpandableListActivity {
/** dialogs **/
protected static final int DIALOG_PROGRESS_UPLOAD = 0;
private LocalOpenstreetmapAdapter listAdapter;
private OpenstreetmapsDbHelper db;
private OpenstreetmapRemoteUtil remote;
private ProgressDialog progressPointDlg = null;
protected OpenstreetmapPoint[] toUpload;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.local_openstreetmap);
listAdapter = new LocalOpenstreetmapAdapter();
getExpandableListView().setOnChildClickListener(new OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
final OpenstreetmapPoint point = (OpenstreetmapPoint) listAdapter.getChild(groupPosition, childPosition);
showContextMenu(point);
return true;
}
});
getExpandableListView().setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() {
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
long packedPos = ((ExpandableListContextMenuInfo)menuInfo).packedPosition;
int group = ExpandableListView.getPackedPositionGroup(packedPos);
int child = ExpandableListView.getPackedPositionChild(packedPos);
if (child >= 0 && group >= 0) {
final OpenstreetmapPoint point = (OpenstreetmapPoint) listAdapter.getChild(group, child);
showContextMenu(point);
}
}
});
setListAdapter(listAdapter);
db = new OpenstreetmapsDbHelper(this);
List<OpenstreetmapPoint> l = db.getOpenstreetmapPoints();
android.util.Log.d(LogUtil.TAG, "List of POI " + l.size() + " length");
for (OpenstreetmapPoint p : l) {
listAdapter.addOpenstreetmapPoint(p);
}
listAdapter.notifyDataSetChanged();
remote = new OpenstreetmapRemoteUtil(this, this.getWindow().getDecorView());
findViewById(R.id.UploadAllButton).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toUpload = listAdapter.values().toArray(new OpenstreetmapPoint[0]);
showDialog(DIALOG_PROGRESS_UPLOAD);
}
});
}
@Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case DIALOG_PROGRESS_UPLOAD:
progressPointDlg = ProgressDialogImplementation.createProgressDialog(
LocalOpenstreetmapActivity.this,
getString(R.string.uploading),
getString(R.string.local_openstreetmap_uploading_poi),
ProgressDialog.STYLE_HORIZONTAL).getDialog();
return progressPointDlg;
}
return null;
}
@Override
protected void onPrepareDialog(int id, Dialog dialog, Bundle args) {
switch (id) {
case DIALOG_PROGRESS_UPLOAD:
UploadOpenstreetmapPointAsyncTask uploadTask = new UploadOpenstreetmapPointAsyncTask(progressPointDlg, remote, db,
toUpload.length);
uploadTask.execute(toUpload);
break;
}
}
public class UploadOpenstreetmapPointAsyncTask extends AsyncTask<OpenstreetmapPoint, OpenstreetmapPoint, Integer> {
private ProgressDialog progress;
private OpenstreetmapRemoteUtil remote;
private OpenstreetmapsDbHelper db;
private int listSize = 0;
private boolean interruptUploading = false;
private int uploaded = 0;
public UploadOpenstreetmapPointAsyncTask(ProgressDialog progress,
OpenstreetmapRemoteUtil remote,
OpenstreetmapsDbHelper db,
int listSize) {
this.progress = progress;
this.remote = remote;
this.db = db;
this.listSize = listSize;
}
@Override
protected Integer doInBackground(OpenstreetmapPoint... points) {
for (OpenstreetmapPoint p : points) {
if (interruptUploading) break;
EntityInfo entityInfo = null;
if (OpenstreetmapUtil.Action.CREATE != p.getAction()) {
entityInfo = remote.loadNode(p.getEntity());
}
if (remote.commitNodeImpl(p.getAction(), p.getEntity(), entityInfo, p.getComment())) {
db.deleteOpenstreetmap(p);
uploaded++;
publishProgress(p);
}
}
return new Integer(uploaded);
}
@Override
protected void onPreExecute() {
interruptUploading = false;
uploaded = 0;
progress.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
UploadOpenstreetmapPointAsyncTask.this.setInterruptUploading(true);
}
});
progress.setMax(listSize);
}
@Override
protected void onPostExecute(Integer result) {
listAdapter.notifyDataSetChanged();
if(result != null){
Toast.makeText(LocalOpenstreetmapActivity.this, MessageFormat.format(getString(R.string.local_openstreetmap_poi_were_uploaded), result.intValue()), Toast.LENGTH_LONG).show();
}
removeDialog(DIALOG_PROGRESS_UPLOAD);
}
public void setInterruptUploading(boolean b) {
interruptUploading = b;
}
@Override
protected void onProgressUpdate(OpenstreetmapPoint... points) {
listAdapter.delete(points[0]);
progress.setProgress(uploaded);
}
}
private void showContextMenu(final OpenstreetmapPoint info) {
Builder builder = new AlertDialog.Builder(this);
final List<Integer> menu = new ArrayList<Integer>();
menu.add(R.string.local_openstreetmap_show_poi);
menu.add(R.string.local_openstreetmap_upload);
menu.add(R.string.local_openstreetmap_delete);
String[] values = new String[menu.size()];
for (int i = 0; i < values.length; i++) {
values[i] = getString(menu.get(i));
}
builder.setItems(values, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
int resId = menu.get(which);
if (info != null) {
if (resId == R.string.local_openstreetmap_show_poi) {
OsmandSettings settings = OsmandSettings.getOsmandSettings(LocalOpenstreetmapActivity.this);
settings.setMapLocationToShow(info.getLatitude(), info.getLongitude(), settings.getLastKnownMapZoom());
MapActivity.launchMapActivityMoveToTop(LocalOpenstreetmapActivity.this);
} else if (resId == R.string.local_openstreetmap_delete) {
listAdapter.delete(info);
} else if (resId == R.string.local_openstreetmap_upload) {
toUpload = new OpenstreetmapPoint[]{info};
showDialog(DIALOG_PROGRESS_UPLOAD);
}
}
}
});
builder.show();
}
protected class LocalOpenstreetmapAdapter extends BaseExpandableListAdapter {
Map<String, List<OpenstreetmapPoint>> data = new LinkedHashMap<String, List<OpenstreetmapPoint>>();
List<String> category = new ArrayList<String>();
List<String> filterCategory = null;
public LocalOpenstreetmapAdapter() {
}
public void clear() {
data.clear();
category.clear();
filterCategory = null;
notifyDataSetChanged();
}
public List<OpenstreetmapPoint> values() {
List<OpenstreetmapPoint> values = new ArrayList<OpenstreetmapPoint>();
for (List<OpenstreetmapPoint> v : data.values()) {
values.addAll(v);
}
return values;
}
public void delete(OpenstreetmapPoint i) {
final AmenityIndexRepositoryOdb repo = ((OsmandApplication) getApplication()).getResourceManager().getUpdatablePoiDb();
android.util.Log.d(LogUtil.TAG, "Delete " + i);
db.deleteOpenstreetmap(i);
String c = i.getType();
if(c != null){
data.get(c).remove(i);
// We need to re-insert the POI if it is a delete or modify
repo.deleteAmenities(i.getId() << 1);
repo.clearCache();
}
listAdapter.notifyDataSetChanged();
}
public void cancelFilter(){
filterCategory = null;
notifyDataSetChanged();
}
public void filterCategories(String... types) {
List<String> filter = new ArrayList<String>();
List<String> source = filterCategory == null ? category : filterCategory;
for (String info : source) {
for (String ts : types) {
if (info.compareTo(ts) == 0) {
filter.add(info);
}
}
}
filterCategory = filter;
notifyDataSetChanged();
}
public void addOpenstreetmapPoint(OpenstreetmapPoint info) {
int found = -1;
// search from end
for (int i = category.size() - 1; i >= 0; i--) {
String cat = category.get(i);
if (cat.compareTo(info.getType()) == 0) {
found = i;
break;
}
}
if (found == -1) {
found = category.size();
category.add(info.getType());
}
if (!data.containsKey(category.get(found))) {
data.put(category.get(found), new ArrayList<OpenstreetmapPoint>());
}
data.get(category.get(found)).add(info);
}
@Override
public OpenstreetmapPoint getChild(int groupPosition, int childPosition) {
String cat = filterCategory != null ? filterCategory.get(groupPosition) : category.get(groupPosition);
return data.get(cat).get(childPosition);
}
@Override
public long getChildId(int groupPosition, int childPosition) {
// it would be unusable to have 10000 local categories
return groupPosition * 10000 + childPosition;
}
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
View v = convertView;
final OpenstreetmapPoint child = (OpenstreetmapPoint) getChild(groupPosition, childPosition);
if (v == null ) {
LayoutInflater inflater = getLayoutInflater();
v = inflater.inflate(net.osmand.plus.R.layout.local_openstreetmap_list_item, parent, false);
}
TextView viewName = ((TextView) v.findViewById(R.id.local_openstreetmap_name));
viewName.setText("(" + child.getSubtype() + ") " + child.getName());
if (child.getAction() == OpenstreetmapUtil.Action.CREATE) {
viewName.setTextColor(Color.GREEN);
} else if (child.getAction() == OpenstreetmapUtil.Action.MODIFY) {
viewName.setTextColor(Color.MAGENTA);
} else if (child.getAction() == OpenstreetmapUtil.Action.DELETE) {
viewName.setTextColor(Color.RED);
}
return v;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
View v = convertView;
String group = getGroup(groupPosition);
if (v == null) {
LayoutInflater inflater = getLayoutInflater();
v = inflater.inflate(net.osmand.plus.R.layout.local_openstreetmap_list_item_category, parent, false);
}
StringBuilder t = new StringBuilder(group);
TextView nameView = ((TextView) v.findViewById(R.id.local_openstreetmap_category_name));
t.append(" [").append(getChildrenCount(groupPosition));
if(getString(R.string.local_openstreetmap_items).length() > 0){
t.append(" ").append(getString(R.string.local_openstreetmap_items));
}
if(getString(R.string.local_openstreetmap_items).length() > 0){
t.append(" ").append(getString(R.string.local_openstreetmap_items));
}
t.append("]");
nameView.setText(t.toString());
return v;
}
@Override
public int getChildrenCount(int groupPosition) {
String cat = filterCategory != null ? filterCategory.get(groupPosition) : category.get(groupPosition);
return data.get(cat).size();
}
@Override
public String getGroup(int groupPosition) {
return filterCategory == null ? category.get(groupPosition) : filterCategory.get(groupPosition);
}
@Override
public int getGroupCount() {
return filterCategory == null ? category.size() : filterCategory.size();
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
}
}

View file

@ -67,6 +67,7 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
private Preference saveCurrentTrack;
private Preference testVoiceCommands;
private Preference localOpenstreetmapPoints;
private EditTextPreference applicationDir;
private ListPreference applicationModePreference;
@ -331,6 +332,8 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
routeServiceEnabled.setOnPreferenceChangeListener(this);
applicationDir = (EditTextPreference) screen.findPreference(OsmandSettings.EXTERNAL_STORAGE_DIR);
applicationDir.setOnPreferenceChangeListener(this);
localOpenstreetmapPoints = (Preference) screen.findPreference(OsmandSettings.LOCAL_OPENSTREETMAP_POINTS);
localOpenstreetmapPoints.setOnPreferenceClickListener(this);
@ -778,6 +781,9 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
helper.close();
}
return true;
} else if(preference == localOpenstreetmapPoints){
startActivity(new Intent(this, LocalOpenstreetmapActivity.class));
return true;
}
return false;
}