Merge pull request #648 from krabaey/feature-import-gpx

import&save gpx&kml files from file&content uri's
This commit is contained in:
vshcherb 2014-05-22 17:59:40 +02:00
commit fbb6822891
5 changed files with 276 additions and 133 deletions

View file

@ -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$

View file

@ -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" />

View file

@ -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();
}
}

View 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();
}
}
}

View file

@ -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"));