Merge branch 'offlinePoiEdit'
This commit is contained in:
commit
ef8685b8b8
15 changed files with 1257 additions and 387 deletions
|
@ -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>
|
||||
|
|
15
OsmAnd/res/layout/local_openstreetmap.xml
Normal file
15
OsmAnd/res/layout/local_openstreetmap.xml
Normal 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>
|
7
OsmAnd/res/layout/local_openstreetmap_list_item.xml
Normal file
7
OsmAnd/res/layout/local_openstreetmap_list_item.xml
Normal 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>
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
88
OsmAnd/src/net/osmand/OpenstreetmapLocalUtil.java
Normal file
88
OsmAnd/src/net/osmand/OpenstreetmapLocalUtil.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
106
OsmAnd/src/net/osmand/OpenstreetmapPoint.java
Normal file
106
OsmAnd/src/net/osmand/OpenstreetmapPoint.java
Normal 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();
|
||||
}
|
||||
}
|
436
OsmAnd/src/net/osmand/OpenstreetmapRemoteUtil.java
Normal file
436
OsmAnd/src/net/osmand/OpenstreetmapRemoteUtil.java
Normal 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();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
16
OsmAnd/src/net/osmand/OpenstreetmapUtil.java
Normal file
16
OsmAnd/src/net/osmand/OpenstreetmapUtil.java
Normal 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);
|
||||
}
|
122
OsmAnd/src/net/osmand/plus/OpenstreetmapsDbHelper.java
Normal file
122
OsmAnd/src/net/osmand/plus/OpenstreetmapsDbHelper.java
Normal 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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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 =
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue