Merge pull request #648 from krabaey/feature-import-gpx
import&save gpx&kml files from file&content uri's
This commit is contained in:
commit
fbb6822891
5 changed files with 276 additions and 133 deletions
|
@ -36,7 +36,8 @@ public class IndexConstants {
|
|||
public static final String APP_DIR = "osmand/"; //$NON-NLS-1$
|
||||
public static final String MAPS_PATH = "";
|
||||
public static final String BACKUP_INDEX_DIR= "backup/";
|
||||
public static final String GPX_INDEX_DIR= "tracks/";
|
||||
public static final String GPX_INDEX_DIR = "tracks/";
|
||||
public static final String GPX_IMPORT_DIR = GPX_INDEX_DIR + "import/";
|
||||
public static final String TILES_INDEX_DIR= "tiles/";
|
||||
public static final String TOURS_INDEX_DIR= "tours/";
|
||||
public static final String SRTM_INDEX_DIR = "srtm/"; //$NON-NLS-1$
|
||||
|
|
|
@ -58,6 +58,14 @@
|
|||
</activity>
|
||||
<activity android:name="net.osmand.plus.activities.MapActivity" android:label="@string/app_name" android:screenOrientation="unspecified"
|
||||
android:launchMode="singleTop">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<action android:name="android.intent.action.SEND"/>
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:scheme="content" android:host="*" android:mimeType="binary/octet-stream" />
|
||||
<data android:scheme="content" android:host="*" android:mimeType="application/octet-stream" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<data android:scheme="http" android:host="download.osmand.net" android:path="go"/>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
package net.osmand.plus.activities;
|
||||
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
@ -24,9 +22,6 @@ import net.osmand.map.MapTileDownloader.DownloadRequest;
|
|||
import net.osmand.map.MapTileDownloader.IMapDownloaderCallback;
|
||||
import net.osmand.plus.ApplicationMode;
|
||||
import net.osmand.plus.BusyIndicator;
|
||||
import net.osmand.plus.GPXUtilities;
|
||||
import net.osmand.plus.GPXUtilities.GPXFile;
|
||||
import net.osmand.plus.GPXUtilities.WptPt;
|
||||
import net.osmand.plus.OsmAndConstants;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.OsmandPlugin;
|
||||
|
@ -38,7 +33,7 @@ import net.osmand.plus.Version;
|
|||
import net.osmand.plus.activities.search.SearchActivity;
|
||||
import net.osmand.plus.base.FailSafeFuntions;
|
||||
import net.osmand.plus.base.MapViewTrackingUtilities;
|
||||
import net.osmand.plus.helpers.Kml2Gpx;
|
||||
import net.osmand.plus.helpers.GpxImportHelper;
|
||||
import net.osmand.plus.render.RendererRegistry;
|
||||
import net.osmand.plus.resources.ResourceManager;
|
||||
import net.osmand.plus.routing.RoutingHelper;
|
||||
|
@ -58,7 +53,6 @@ import android.content.DialogInterface;
|
|||
import android.content.Intent;
|
||||
import android.media.AudioManager;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
|
@ -104,6 +98,7 @@ public class MapActivity extends AccessibleActivity {
|
|||
private List<DialogProvider> dialogProviders = new ArrayList<DialogProvider>(2);
|
||||
private StateChangedListener<ApplicationMode> applicationModeListener;
|
||||
private FrameLayout lockView;
|
||||
private GpxImportHelper gpxImportHelper;
|
||||
|
||||
|
||||
private Notification getNotification() {
|
||||
|
@ -193,6 +188,7 @@ public class MapActivity extends AccessibleActivity {
|
|||
if(lockView != null) {
|
||||
((FrameLayout)mapView.getParent()).addView(lockView);
|
||||
}
|
||||
gpxImportHelper = new GpxImportHelper(this, getMyApplication(), getMapView());
|
||||
}
|
||||
|
||||
public void addLockView(FrameLayout lockView) {
|
||||
|
@ -333,55 +329,39 @@ public class MapActivity extends AccessibleActivity {
|
|||
}
|
||||
|
||||
final Intent intent = getIntent();
|
||||
if (intent != null)
|
||||
{
|
||||
if (Intent.ACTION_VIEW.equals(intent.getAction()))
|
||||
{
|
||||
if (intent.getData() != null)
|
||||
{
|
||||
final Uri data = intent.getData();
|
||||
final String scheme = data.getScheme();
|
||||
if ("file".equals(scheme))
|
||||
{
|
||||
if (data.getPath().endsWith("kml"))
|
||||
{
|
||||
showImportedKml(new File(data.getPath()));
|
||||
}
|
||||
else
|
||||
{
|
||||
showImportedGpx(new File(data.getPath()));
|
||||
if (intent != null) {
|
||||
if (Intent.ACTION_VIEW.equals(intent.getAction())) {
|
||||
if (intent.getData() != null) {
|
||||
final Uri data = intent.getData();
|
||||
final String scheme = data.getScheme();
|
||||
if ("file".equals(scheme)) {
|
||||
gpxImportHelper.handleFileImport(data, new File(data.getPath()).getName());
|
||||
setIntent(null);
|
||||
} else if ("content".equals(scheme)) {
|
||||
gpxImportHelper.handleContenImport(data);
|
||||
setIntent(null);
|
||||
} else if ("google.navigation".equals(scheme) || "osmand.navigation".equals(scheme)) {
|
||||
final String schemeSpecificPart = data.getSchemeSpecificPart();
|
||||
|
||||
final Matcher matcher = Pattern.compile("q=(.+?),(.+?)").matcher(schemeSpecificPart);
|
||||
if (matcher.matches()) {
|
||||
try {
|
||||
final double lat = Double.valueOf(matcher.group(1));
|
||||
final double lon = Double.valueOf(matcher.group(2));
|
||||
|
||||
getMyApplication().getTargetPointsHelper().navigateToPoint(new LatLon(lat, lon), false, -1);
|
||||
getMapActions().enterRoutePlanningMode(null, null);
|
||||
} catch (NumberFormatException e) {
|
||||
AccessibleToast.makeText(this, getString(R.string.navigation_intent_invalid, schemeSpecificPart), Toast.LENGTH_LONG).show(); //$NON-NLS-1$
|
||||
}
|
||||
} else {
|
||||
AccessibleToast.makeText(this, getString(R.string.navigation_intent_invalid, schemeSpecificPart), Toast.LENGTH_LONG).show(); //$NON-NLS-1$
|
||||
}
|
||||
setIntent(null);
|
||||
}
|
||||
else if("google.navigation".equals(scheme) || "osmand.navigation".equals(scheme))
|
||||
{
|
||||
final String schemeSpecificPart = data.getSchemeSpecificPart();
|
||||
|
||||
final Matcher matcher = Pattern.compile("q=(.+?),(.+?)").matcher(schemeSpecificPart);
|
||||
if (matcher.matches())
|
||||
{
|
||||
try
|
||||
{
|
||||
final double lat = Double.valueOf(matcher.group(1));
|
||||
final double lon = Double.valueOf(matcher.group(2));
|
||||
|
||||
getMyApplication().getTargetPointsHelper().navigateToPoint(new LatLon(lat, lon), false, -1);
|
||||
getMapActions().enterRoutePlanningMode(null, null);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
AccessibleToast.makeText(this, getString(R.string.navigation_intent_invalid, schemeSpecificPart), Toast.LENGTH_LONG).show(); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AccessibleToast.makeText(this, getString(R.string.navigation_intent_invalid, schemeSpecificPart), Toast.LENGTH_LONG).show(); //$NON-NLS-1$
|
||||
}
|
||||
setIntent(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
View progress = mapLayers.getMapInfoLayer().getProgressBar();
|
||||
if (progress != null) {
|
||||
|
@ -731,80 +711,4 @@ public class MapActivity extends AccessibleActivity {
|
|||
public void refreshMap() {
|
||||
getMapView().refreshMap();
|
||||
}
|
||||
|
||||
private void showImportedGpx(final File gpxFile) {
|
||||
new AsyncTask<Void, Void, GPXFile>() {
|
||||
ProgressDialog progress = null;
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
progress = ProgressDialog.show(MapActivity.this, getString(R.string.loading), getString(R.string.loading_data));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GPXFile doInBackground(Void... nothing) {
|
||||
return GPXUtilities.loadGPXFile(getMyApplication(), gpxFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(GPXFile result) {
|
||||
progress.dismiss();
|
||||
if (result != null) {
|
||||
if (result.warning != null) {
|
||||
AccessibleToast.makeText(MapActivity.this, result.warning, Toast.LENGTH_LONG).show();
|
||||
} else {
|
||||
getMyApplication().setGpxFileToDisplay(result, true);
|
||||
final WptPt moveTo = result.findPointToShow();
|
||||
if (moveTo != null) {
|
||||
mapView.getAnimatedDraggingThread().startMoving(moveTo.lat, moveTo.lon, mapView.getZoom(), true);
|
||||
}
|
||||
mapView.refreshMap();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
private void showImportedKml(final File kmlFile) {
|
||||
new AsyncTask<Void, Void, GPXFile>() {
|
||||
ProgressDialog progress = null;
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
progress = ProgressDialog.show(MapActivity.this, getString(R.string.loading), getString(R.string.loading_data));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GPXFile doInBackground(Void... nothing) {
|
||||
final String result = Kml2Gpx.toGpx(kmlFile);
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return GPXUtilities.loadGPXFile(getMyApplication(), new ByteArrayInputStream(result.getBytes("UTF-8")));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(GPXFile result) {
|
||||
progress.dismiss();
|
||||
if (result != null) {
|
||||
if (result.warning != null) {
|
||||
AccessibleToast.makeText(MapActivity.this, result.warning, Toast.LENGTH_LONG).show();
|
||||
} else {
|
||||
getMyApplication().setGpxFileToDisplay(result, true);
|
||||
final WptPt moveTo = result.findPointToShow();
|
||||
if (moveTo != null) {
|
||||
mapView.getAnimatedDraggingThread().startMoving(moveTo.lat, moveTo.lon, mapView.getZoom(), true);
|
||||
}
|
||||
mapView.refreshMap();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
}
|
||||
|
|
230
OsmAnd/src/net/osmand/plus/helpers/GpxImportHelper.java
Normal file
230
OsmAnd/src/net/osmand/plus/helpers/GpxImportHelper.java
Normal file
|
@ -0,0 +1,230 @@
|
|||
package net.osmand.plus.helpers;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.provider.OpenableColumns;
|
||||
import android.widget.Toast;
|
||||
import net.osmand.IndexConstants;
|
||||
import net.osmand.access.AccessibleToast;
|
||||
import net.osmand.plus.GPXUtilities;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.views.OsmandMapTileView;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.text.MessageFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author Koen Rabaey
|
||||
*/
|
||||
public class GpxImportHelper {
|
||||
|
||||
public static final String KML_SUFFIX = ".kml";
|
||||
public static final String GPX_SUFFIX = ".gpx";
|
||||
private final MapActivity mapActivity;
|
||||
private final OsmandApplication application;
|
||||
private final OsmandMapTileView mapView;
|
||||
|
||||
public GpxImportHelper(final MapActivity mapActivity, final OsmandApplication application, final OsmandMapTileView mapView) {
|
||||
this.mapActivity = mapActivity;
|
||||
this.application = application;
|
||||
this.mapView = mapView;
|
||||
}
|
||||
|
||||
public void handleContenImport(final Uri contentUri) {
|
||||
final String name = getNameFromContentUri(contentUri);
|
||||
|
||||
handleFileImport(contentUri, name);
|
||||
}
|
||||
|
||||
public void handleFileImport(final Uri intentUri, final String fileName) {
|
||||
if (fileName != null && fileName.endsWith(KML_SUFFIX)) {
|
||||
handleKmlImport(intentUri, fileName);
|
||||
} else {
|
||||
handleGpxImport(intentUri, fileName);
|
||||
}
|
||||
}
|
||||
|
||||
private String getNameFromContentUri(Uri contentUri) {
|
||||
final String name;
|
||||
final Cursor returnCursor = application.getContentResolver().query(contentUri, null, null, null, null);
|
||||
if (returnCursor != null && returnCursor.moveToFirst()) {
|
||||
name = returnCursor.getString(returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
|
||||
returnCursor.close();
|
||||
} else {
|
||||
name = null;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
private void handleGpxImport(final Uri gpxFile, final String fileName) {
|
||||
new AsyncTask<Void, Void, GPXUtilities.GPXFile>() {
|
||||
ProgressDialog progress = null;
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
progress = ProgressDialog.show(mapActivity, application.getString(R.string.loading), application.getString(R.string.loading_data));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GPXUtilities.GPXFile doInBackground(Void... nothing) {
|
||||
InputStream is = null;
|
||||
try {
|
||||
final ParcelFileDescriptor pFD = application.getContentResolver().openFileDescriptor(gpxFile, "r");
|
||||
|
||||
if (pFD != null) {
|
||||
is = new FileInputStream(pFD.getFileDescriptor());
|
||||
return GPXUtilities.loadGPXFile(application, is);
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
//
|
||||
} finally {
|
||||
if (is != null) try {
|
||||
is.close();
|
||||
} catch (IOException ignore) {
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(GPXUtilities.GPXFile result) {
|
||||
progress.dismiss();
|
||||
handleResult(result, fileName);
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
private void handleKmlImport(final Uri kmlFile, final String name) {
|
||||
new AsyncTask<Void, Void, GPXUtilities.GPXFile>() {
|
||||
ProgressDialog progress = null;
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
progress = ProgressDialog.show(mapActivity, application.getString(R.string.loading), application.getString(R.string.loading_data));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GPXUtilities.GPXFile doInBackground(Void... nothing) {
|
||||
InputStream is = null;
|
||||
try {
|
||||
final ParcelFileDescriptor pFD = application.getContentResolver().openFileDescriptor(kmlFile, "r");
|
||||
if (pFD != null) {
|
||||
is = new FileInputStream(pFD.getFileDescriptor());
|
||||
final String result = Kml2Gpx.toGpx(is);
|
||||
if (result != null) {
|
||||
try {
|
||||
return GPXUtilities.loadGPXFile(application, new ByteArrayInputStream(result.getBytes("UTF-8")));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
//
|
||||
} finally {
|
||||
if (is != null) try {
|
||||
is.close();
|
||||
} catch (IOException ignore) {
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(GPXUtilities.GPXFile result) {
|
||||
progress.dismiss();
|
||||
handleResult(result, name);
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
private void handleResult(final GPXUtilities.GPXFile result, final String name) {
|
||||
if (result != null) {
|
||||
if (result.warning != null) {
|
||||
AccessibleToast.makeText(mapActivity, result.warning, Toast.LENGTH_LONG).show();
|
||||
} else {
|
||||
new SaveAsyncTask(result, name).execute();
|
||||
}
|
||||
} else {
|
||||
AccessibleToast.makeText(mapActivity, R.string.error_reading_gpx, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
private String saveImport(final GPXUtilities.GPXFile gpxFile, final String fileName) {
|
||||
final String warning;
|
||||
|
||||
if (gpxFile.isEmpty()) {
|
||||
warning = application.getString(R.string.error_reading_gpx);
|
||||
} else {
|
||||
final File importDir = application.getAppPath(IndexConstants.GPX_IMPORT_DIR);
|
||||
importDir.mkdirs();
|
||||
if (importDir.exists() && importDir.isDirectory() && importDir.canWrite()) {
|
||||
final GPXUtilities.WptPt pt = gpxFile.findPointToShow();
|
||||
final File toWrite = getFileToSave(fileName, importDir, pt);
|
||||
|
||||
warning = GPXUtilities.writeGpxFile(toWrite, gpxFile, application);
|
||||
if (warning == null) {
|
||||
gpxFile.path = toWrite.getAbsolutePath();
|
||||
}
|
||||
} else {
|
||||
warning = application.getString(R.string.sd_dir_not_accessible);
|
||||
}
|
||||
}
|
||||
|
||||
return warning;
|
||||
}
|
||||
|
||||
private File getFileToSave(final String fileName, final File importDir, final GPXUtilities.WptPt pt) {
|
||||
final StringBuilder builder = new StringBuilder(fileName);
|
||||
if ("".equals(fileName)) {
|
||||
builder.append("import_").append(new SimpleDateFormat("HH-mm_EEE").format(new Date(pt.time))).append(GPX_SUFFIX); //$NON-NLS-1$
|
||||
}
|
||||
if (fileName.endsWith(KML_SUFFIX)) {
|
||||
builder.replace(builder.length() - KML_SUFFIX.length(), builder.length(), GPX_SUFFIX);
|
||||
} else if (!fileName.endsWith(GPX_SUFFIX)) {
|
||||
builder.append(GPX_SUFFIX);
|
||||
}
|
||||
return new File(importDir, builder.toString());
|
||||
}
|
||||
|
||||
private class SaveAsyncTask extends AsyncTask<Void, Void, String> {
|
||||
private final GPXUtilities.GPXFile result;
|
||||
private final String name;
|
||||
|
||||
private SaveAsyncTask(GPXUtilities.GPXFile result, final String name) {
|
||||
this.result = result;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String doInBackground(Void... nothing) {
|
||||
return saveImport(result, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final String warning) {
|
||||
final String msg = warning == null ? MessageFormat.format(application.getString(R.string.gpx_saved_sucessfully), result.path) : warning;
|
||||
AccessibleToast.makeText(mapActivity, msg, Toast.LENGTH_LONG).show();
|
||||
|
||||
application.setGpxFileToDisplay(result, true);
|
||||
final GPXUtilities.WptPt moveTo = result.findPointToShow();
|
||||
if (moveTo != null) {
|
||||
mapView.getAnimatedDraggingThread().startMoving(moveTo.lat, moveTo.lon, mapView.getZoom(), true);
|
||||
}
|
||||
mapView.refreshMap();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@ import org.apache.commons.logging.Log;
|
|||
import javax.xml.transform.*;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.StringWriter;
|
||||
|
||||
/**
|
||||
|
@ -18,7 +18,7 @@ public class Kml2Gpx {
|
|||
public static final Log LOG = PlatformUtil.getLog(Kml2Gpx.class);
|
||||
|
||||
@TargetApi(8)
|
||||
public static String toGpx(final File kml) {
|
||||
public static String toGpx(final InputStream kml) {
|
||||
try {
|
||||
final Source xmlSource = new StreamSource(kml);
|
||||
final Source xsltSource = new StreamSource(Kml2Gpx.class.getResourceAsStream("kml2gpx.xslt"));
|
||||
|
|
Loading…
Reference in a new issue