diff --git a/OsmAnd-java/src/net/osmand/IndexConstants.java b/OsmAnd-java/src/net/osmand/IndexConstants.java index a8c73807a4..a79ff7e621 100644 --- a/OsmAnd-java/src/net/osmand/IndexConstants.java +++ b/OsmAnd-java/src/net/osmand/IndexConstants.java @@ -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$ diff --git a/OsmAnd/AndroidManifest.xml b/OsmAnd/AndroidManifest.xml index b54d73fce3..b426594be7 100644 --- a/OsmAnd/AndroidManifest.xml +++ b/OsmAnd/AndroidManifest.xml @@ -58,6 +58,14 @@ + + + + + + + + diff --git a/OsmAnd/src/net/osmand/plus/activities/MapActivity.java b/OsmAnd/src/net/osmand/plus/activities/MapActivity.java index ce797b3cd3..ee1da2a940 100644 --- a/OsmAnd/src/net/osmand/plus/activities/MapActivity.java +++ b/OsmAnd/src/net/osmand/plus/activities/MapActivity.java @@ -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 dialogProviders = new ArrayList(2); private StateChangedListener 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() { - 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() { - 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(); - } } diff --git a/OsmAnd/src/net/osmand/plus/helpers/GpxImportHelper.java b/OsmAnd/src/net/osmand/plus/helpers/GpxImportHelper.java new file mode 100644 index 0000000000..e3d2915529 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/helpers/GpxImportHelper.java @@ -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() { + 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() { + 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 { + 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(); + } + } +} diff --git a/OsmAnd/src/net/osmand/plus/helpers/Kml2Gpx.java b/OsmAnd/src/net/osmand/plus/helpers/Kml2Gpx.java index 8f69d14015..a593916537 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/Kml2Gpx.java +++ b/OsmAnd/src/net/osmand/plus/helpers/Kml2Gpx.java @@ -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"));