aboutsummaryrefslogtreecommitdiffstats
path: root/main/src/cgeo/geocaching/export
diff options
context:
space:
mode:
Diffstat (limited to 'main/src/cgeo/geocaching/export')
-rw-r--r--main/src/cgeo/geocaching/export/AbstractExport.java32
-rw-r--r--main/src/cgeo/geocaching/export/Export.java29
-rw-r--r--main/src/cgeo/geocaching/export/ExportFactory.java65
-rw-r--r--main/src/cgeo/geocaching/export/FieldnoteExport.java257
-rw-r--r--main/src/cgeo/geocaching/export/GpxExport.java301
5 files changed, 684 insertions, 0 deletions
diff --git a/main/src/cgeo/geocaching/export/AbstractExport.java b/main/src/cgeo/geocaching/export/AbstractExport.java
new file mode 100644
index 0000000..85b060b
--- /dev/null
+++ b/main/src/cgeo/geocaching/export/AbstractExport.java
@@ -0,0 +1,32 @@
+package cgeo.geocaching.export;
+
+import cgeo.geocaching.cgeoapplication;
+
+abstract class AbstractExport implements Export {
+ private final String name;
+
+ protected AbstractExport(final String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Generates a localized string from a resource id.
+ *
+ * @param resourceId
+ * the resource id of the string
+ * @return localized string
+ */
+ protected static String getString(int resourceId) {
+ return cgeoapplication.getInstance().getString(resourceId);
+ }
+
+ @Override
+ public String toString() {
+ // used in the array adapter of the dialog showing the exports
+ return getName();
+ }
+}
diff --git a/main/src/cgeo/geocaching/export/Export.java b/main/src/cgeo/geocaching/export/Export.java
new file mode 100644
index 0000000..7a2b075
--- /dev/null
+++ b/main/src/cgeo/geocaching/export/Export.java
@@ -0,0 +1,29 @@
+package cgeo.geocaching.export;
+
+import cgeo.geocaching.cgCache;
+
+import android.app.Activity;
+
+import java.util.List;
+
+/**
+ * Represents an exporter to export a {@link List} of {@link cgCache} to various formats.
+ */
+interface Export {
+ /**
+ * Export a {@link List} of {@link cgCache} to various formats.
+ *
+ * @param caches
+ * The {@link List} of {@link cgCache} to be exported
+ * @param activity
+ * optional: Some exporters might have an UI which requires an {@link Activity}
+ */
+ public void export(List<cgCache> caches, Activity activity);
+
+ /**
+ * Get the localized name of this exporter.
+ *
+ * @return localized name
+ */
+ public String getName();
+}
diff --git a/main/src/cgeo/geocaching/export/ExportFactory.java b/main/src/cgeo/geocaching/export/ExportFactory.java
new file mode 100644
index 0000000..8b3df58
--- /dev/null
+++ b/main/src/cgeo/geocaching/export/ExportFactory.java
@@ -0,0 +1,65 @@
+package cgeo.geocaching.export;
+
+import cgeo.geocaching.R;
+import cgeo.geocaching.cgCache;
+import cgeo.geocaching.utils.Log;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.widget.ArrayAdapter;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Factory to create a dialog with all available exporters.
+ */
+public abstract class ExportFactory {
+
+ /**
+ * Contains instances of all available exporter classes.
+ */
+ private static final List<Class<? extends Export>> exporterClasses;
+
+ static {
+ final ArrayList<Class<? extends Export>> temp = new ArrayList<Class<? extends Export>>();
+ temp.add(FieldnoteExport.class);
+ temp.add(GpxExport.class);
+ exporterClasses = Collections.unmodifiableList(temp);
+ }
+
+ /**
+ * Creates a dialog so that the user can select an exporter.
+ *
+ * @param caches
+ * The {@link List} of {@link cgCache} to be exported
+ * @param activity
+ * The {@link Activity} in whose context the dialog should be shown
+ */
+ public static void showExportMenu(final List<cgCache> caches, final Activity activity) {
+ final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+ builder.setTitle(R.string.export).setIcon(android.R.drawable.ic_menu_share);
+
+ final ArrayList<Export> export = new ArrayList<Export>();
+ for (Class<? extends Export> exporterClass : exporterClasses) {
+ try {
+ export.add(exporterClass.newInstance());
+ } catch (Exception ex) {
+ Log.e("showExportMenu", ex);
+ }
+ }
+
+ final ArrayAdapter<Export> adapter = new ArrayAdapter<Export>(activity, android.R.layout.select_dialog_item, export);
+
+ builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int item) {
+ final Export selectedExport = adapter.getItem(item);
+ selectedExport.export(caches, activity);
+ }
+ });
+
+ builder.create().show();
+ }
+} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/export/FieldnoteExport.java b/main/src/cgeo/geocaching/export/FieldnoteExport.java
new file mode 100644
index 0000000..05fb828
--- /dev/null
+++ b/main/src/cgeo/geocaching/export/FieldnoteExport.java
@@ -0,0 +1,257 @@
+package cgeo.geocaching.export;
+
+import cgeo.geocaching.LogEntry;
+import cgeo.geocaching.R;
+import cgeo.geocaching.cgCache;
+import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.activity.ActivityMixin;
+import cgeo.geocaching.activity.Progress;
+import cgeo.geocaching.enumerations.LogType;
+import cgeo.geocaching.utils.Log;
+
+import org.apache.commons.lang3.StringUtils;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.ProgressDialog;
+import android.os.AsyncTask;
+import android.os.Environment;
+import android.view.View;
+import android.widget.Button;
+import android.widget.CheckBox;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Exports offline-logs in the Groundspeak Field Note format.<br>
+ * <br>
+ *
+ * Field Notes are simple plain text files, but poorly documented. Syntax:<br>
+ * <code>GCxxxxx,yyyy-mm-ddThh:mm:ssZ,Found it,"logtext"</code>
+ */
+class FieldnoteExport extends AbstractExport {
+ private static final File exportLocation = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/field-notes");
+ private static final SimpleDateFormat fieldNoteDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
+
+ protected FieldnoteExport() {
+ super(getString(R.string.export_fieldnotes));
+ }
+
+ /**
+ * A dialog to allow the user to set options for the export.
+ *
+ * Currently available options are: upload field notes, only new logs since last export/upload
+ */
+ private class ExportOptionsDialog extends AlertDialog {
+ public ExportOptionsDialog(final List<cgCache> caches, final Activity activity) {
+ super(activity);
+
+ View layout = activity.getLayoutInflater().inflate(R.layout.fieldnote_export_dialog, null);
+ setView(layout);
+
+ ((Button) layout.findViewById(R.id.export)).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ dismiss();
+ new ExportTask(
+ caches,
+ activity,
+ ((CheckBox) findViewById(R.id.upload)).isChecked(),
+ ((CheckBox) findViewById(R.id.onlynew)).isChecked())
+ .execute((Void) null);
+ }
+ });
+ }
+ }
+
+ @Override
+ public void export(final List<cgCache> caches, final Activity activity) {
+ if (null == activity) {
+ // No activity given, so no user interaction possible.
+ // Start export with default parameters.
+ new ExportTask(caches, null, false, false).execute((Void) null);
+ } else {
+ // Show configuration dialog
+ new ExportOptionsDialog(caches, activity).show();
+ }
+ }
+
+ private class ExportTask extends AsyncTask<Void, Integer, Boolean> {
+ private final List<cgCache> caches;
+ private final Activity activity;
+ private final boolean onlyNew;
+ private final Progress progress = new Progress();
+ private File exportFile;
+
+ private static final int STATUS_UPLOAD = -1;
+
+ /**
+ * Instantiates and configurates the task for exporting field notes.
+ *
+ * @param caches
+ * The {@link List} of {@link cgCache} to be exported
+ * @param activity
+ * optional: Show a progress bar and toasts
+ * @param upload
+ * Upload the Field Note to geocaching.com
+ * @param onlyNew
+ * Upload/export only new logs since last export
+ */
+ public ExportTask(final List<cgCache> caches, final Activity activity, final boolean upload, final boolean onlyNew) {
+ this.caches = caches;
+ this.activity = activity;
+ this.onlyNew = onlyNew;
+ }
+
+ @Override
+ protected void onPreExecute() {
+ if (null != activity) {
+ progress.show(activity, null, getString(R.string.export) + ": " + getName(), ProgressDialog.STYLE_HORIZONTAL, null);
+ progress.setMaxProgressAndReset(caches.size());
+ }
+ }
+
+ @Override
+ protected Boolean doInBackground(Void... params) {
+ final StringBuilder fieldNoteBuffer = new StringBuilder();
+
+ // We need our own HashMap because LogType will give us localized and maybe
+ // different strings than gc.com expects in the field note
+ // We only need such logtypes that are possible to log via c:geo
+ Map<LogType, String> logTypes = new HashMap<LogType, String>();
+ logTypes.put(LogType.LOG_FOUND_IT, "Found it");
+ logTypes.put(LogType.LOG_DIDNT_FIND_IT, "Didn't find it");
+ logTypes.put(LogType.LOG_NOTE, "Write Note");
+ logTypes.put(LogType.LOG_NEEDS_ARCHIVE, "Needs archived");
+ logTypes.put(LogType.LOG_NEEDS_MAINTENANCE, "Needs Maintenance");
+ logTypes.put(LogType.LOG_WILL_ATTEND, "Will Attend");
+ logTypes.put(LogType.LOG_ATTENDED, "Attended");
+ logTypes.put(LogType.LOG_WEBCAM_PHOTO_TAKEN, "Webcam Photo Taken");
+
+ for (int i = 0; i < caches.size(); i++) {
+ try {
+ final cgCache cache = caches.get(i);
+ if (cache.isLogOffline()) {
+ LogEntry log = cgeoapplication.getInstance().loadLogOffline(cache.getGeocode());
+ if (null != logTypes.get(log.type)) {
+ fieldNoteBuffer.append(cache.getGeocode())
+ .append(',')
+ .append(fieldNoteDateFormat.format(new Date(log.date)))
+ .append(',')
+ .append(logTypes.get(log.type))
+ .append(",\"")
+ .append(StringUtils.replaceChars(log.log, '"', '\''))
+ .append("\"\n");
+ }
+ }
+ publishProgress(i + 1);
+ } catch (Exception e) {
+ Log.e("FieldnoteExport.ExportTask generation", e);
+ return false;
+ }
+ }
+
+ fieldNoteBuffer.append("\n");
+
+ if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+ exportLocation.mkdirs();
+
+ SimpleDateFormat fileNameDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
+ exportFile = new File(exportLocation.toString() + '/' + fileNameDateFormat.format(new Date()) + ".txt");
+
+ OutputStream os = null;
+ Writer fw = null;
+ try {
+ os = new FileOutputStream(exportFile);
+ fw = new OutputStreamWriter(os, "ISO-8859-1"); // TODO: gc.com doesn't support UTF-8
+ fw.write(fieldNoteBuffer.toString());
+ } catch (IOException e) {
+ Log.e("FieldnoteExport.ExportTask export", e);
+ return false;
+ } finally {
+ if (fw != null) {
+ try {
+ fw.close();
+ } catch (IOException e) {
+ Log.e("FieldnoteExport.ExportTask export", e);
+ return false;
+ }
+ }
+ }
+ } else {
+ return false;
+ }
+
+ /*
+ * if (upload) {
+ * TODO Use multipart POST request for uploading
+ * publishProgress(STATUS_UPLOAD);
+ *
+ * final Parameters uploadParams = new Parameters(
+ * "__EVENTTARGET", "",
+ * "__EVENTARGUMENT", "",
+ * "__VIEWSTATE", "",
+ * //TODO "ctl00$ContentBody$chkSuppressDate", "on",
+ * "ctl00$ContentBody$FieldNoteLoader", fieldNoteBuffer.toString(),
+ * "ctl00$ContentBody$btnUpload", "Upload Field Note");
+ * final String uri = "http://www.geocaching.com/my/uploadfieldnotes.aspx";
+ *
+ * String page = Network.getResponseData(Network.postRequest(uri, uploadParams));
+ * if (!Login.getLoginStatus(page)) {
+ * final StatusCode loginState = Login.login();
+ * if (loginState == StatusCode.NO_ERROR) {
+ * page = Network.getResponseData(Network.postRequest(uri, uploadParams));
+ * } else {
+ * Log.e(Settings.tag, "FieldnoteExport.ExportTask upload: No login (error: " + loginState + ")");
+ * return false;
+ * }
+ * }
+ *
+ * if (StringUtils.isBlank(page)) {
+ * Log.e(Settings.tag, "FieldnoteExport.ExportTask upload: No data from server");
+ * return false;
+ * }
+ * }
+ */
+
+ return true;
+ }
+
+ @Override
+ protected void onPostExecute(Boolean result) {
+ if (null != activity) {
+ progress.dismiss();
+
+ if (result) {
+ if (onlyNew) {
+ // update last export time in settings
+ }
+ ActivityMixin.showToast(activity, getName() + ' ' + getString(R.string.export_exportedto) + ": " + exportFile.toString());
+ } else {
+ ActivityMixin.showToast(activity, getString(R.string.export_failed));
+ }
+ }
+ }
+
+ @Override
+ protected void onProgressUpdate(Integer... status) {
+ if (null != activity) {
+ if (STATUS_UPLOAD == status[0]) {
+ progress.setMessage(getString(R.string.export_fieldnotes_uploading));
+ } else {
+ progress.setProgress(status[0]);
+ }
+ }
+ }
+ }
+}
diff --git a/main/src/cgeo/geocaching/export/GpxExport.java b/main/src/cgeo/geocaching/export/GpxExport.java
new file mode 100644
index 0000000..2c833a2
--- /dev/null
+++ b/main/src/cgeo/geocaching/export/GpxExport.java
@@ -0,0 +1,301 @@
+package cgeo.geocaching.export;
+
+import cgeo.geocaching.R;
+import cgeo.geocaching.cgCache;
+import cgeo.geocaching.LogEntry;
+import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.activity.ActivityMixin;
+import cgeo.geocaching.activity.Progress;
+import cgeo.geocaching.enumerations.CacheAttribute;
+import cgeo.geocaching.enumerations.LoadFlags;
+import cgeo.geocaching.utils.BaseUtils;
+import cgeo.geocaching.utils.Log;
+
+import org.apache.commons.lang3.StringEscapeUtils;
+
+import android.app.Activity;
+import android.app.ProgressDialog;
+import android.os.AsyncTask;
+import android.os.Environment;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+
+class GpxExport extends AbstractExport {
+ private static final File exportLocation = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/gpx-export");
+ private static final SimpleDateFormat dateFormatZ = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
+
+ protected GpxExport() {
+ super(getString(R.string.export_gpx));
+ }
+
+ @Override
+ public void export(final List<cgCache> caches, final Activity activity) {
+ new ExportTask(caches, activity).execute((Void) null);
+ }
+
+ private class ExportTask extends AsyncTask<Void, Integer, Boolean> {
+ private final List<cgCache> caches;
+ private final Activity activity;
+ private final Progress progress = new Progress();
+ private File exportFile;
+
+ /**
+ * Instantiates and configures the task for exporting field notes.
+ *
+ * @param caches
+ * The {@link List} of {@link cgCache} to be exported
+ * @param activity
+ * optional: Show a progress bar and toasts
+ */
+ public ExportTask(final List<cgCache> caches, final Activity activity) {
+ this.caches = caches;
+ this.activity = activity;
+ }
+
+ @Override
+ protected void onPreExecute() {
+ if (null != activity) {
+ progress.show(activity, null, getString(R.string.export) + ": " + getName(), ProgressDialog.STYLE_HORIZONTAL, null);
+ progress.setMaxProgressAndReset(caches.size());
+ }
+ }
+
+ @Override
+ protected Boolean doInBackground(Void... params) {
+ // quick check for being able to write the GPX file
+ if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+ return false;
+ }
+
+ // FIXME: complete export is created in memory. That should be some file stream instead.
+ final StringBuilder gpx = new StringBuilder();
+
+ gpx.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+ gpx.append("<gpx version=\"1.0\" creator=\"c:geo - http://www.cgeo.org\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.topografix.com/GPX/1/0\" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd http://www.groundspeak.com/cache/1/0/1 http://www.groundspeak.com/cache/1/0/1/cache.xsd\">");
+
+ try {
+ for (int i = 0; i < caches.size(); i++) {
+ cgCache cache = caches.get(i);
+
+ if (!cache.isDetailed()) {
+ cache = cgeoapplication.getInstance().loadCache(caches.get(i).getGeocode(), LoadFlags.LOAD_ALL_DB_ONLY);
+ }
+
+ gpx.append("<wpt ");
+ gpx.append("lat=\"" + cache.getCoords().getLatitude() + "\" ");
+ gpx.append("lon=\"" + cache.getCoords().getLongitude() + "\">");
+
+ gpx.append("<time>");
+ gpx.append(StringEscapeUtils.escapeXml(dateFormatZ.format(cache.getHiddenDate())));
+ gpx.append("</time>");
+
+ gpx.append("<name>");
+ gpx.append(StringEscapeUtils.escapeXml(cache.getGeocode()));
+ gpx.append("</name>");
+
+ gpx.append("<desc>");
+ gpx.append(StringEscapeUtils.escapeXml(cache.getName()));
+ gpx.append("</desc>");
+
+ gpx.append("<sym>");
+ gpx.append(cache.isFound() ? "Geocache Found" : "Geocache");
+ gpx.append("</sym>");
+
+ gpx.append("<type>");
+ gpx.append(StringEscapeUtils.escapeXml("Geocache|" + cache.getType().toString())); //TODO: Correct (english) string
+ gpx.append("</type>");
+
+ gpx.append("<groundspeak:cache ");
+ gpx.append("available=\"" + (!cache.isDisabled() ? "True" : "False"));
+ gpx.append("\" archived=\"" + (cache.isArchived() ? "True" : "False") + "\" ");
+ gpx.append("xmlns:groundspeak=\"http://www.groundspeak.com/cache/1/0/1\">");
+
+ gpx.append("<groundspeak:name>");
+ gpx.append(StringEscapeUtils.escapeXml(cache.getName()));
+ gpx.append("</groundspeak:name>");
+
+ gpx.append("<groundspeak:placed_by>");
+ gpx.append(StringEscapeUtils.escapeXml(cache.getOwner()));
+ gpx.append("</groundspeak:placed_by>");
+
+ gpx.append("<groundspeak:owner>");
+ gpx.append(StringEscapeUtils.escapeXml(cache.getOwnerReal()));
+ gpx.append("</groundspeak:owner>");
+
+ gpx.append("<groundspeak:type>");
+ gpx.append(StringEscapeUtils.escapeXml(cache.getType().toString())); //TODO: Correct (english) string
+ gpx.append("</groundspeak:type>");
+
+ gpx.append("<groundspeak:container>");
+ gpx.append(StringEscapeUtils.escapeXml(cache.getSize().toString())); //TODO: Correct (english) string
+ gpx.append("</groundspeak:container>");
+
+ if (cache.hasAttributes()) {
+ //TODO: Attribute conversion required: English verbose name, gpx-id
+ gpx.append("<groundspeak:attributes>");
+
+ for (String attribute : cache.getAttributes()) {
+ final CacheAttribute attr = CacheAttribute.getByGcRawName(CacheAttribute.trimAttributeName(attribute));
+ final boolean enabled = attribute.endsWith(CacheAttribute.INTERNAL_YES);
+
+ gpx.append("<groundspeak:attribute id=\"");
+ gpx.append(attr.id);
+ gpx.append("\" inc=\"");
+ if (enabled) {
+ gpx.append('1');
+ } else {
+ gpx.append('0');
+ }
+ gpx.append("\">");
+ gpx.append(StringEscapeUtils.escapeXml(attr.getL10n(enabled)));
+ gpx.append("</groundspeak:attribute>");
+ }
+
+ gpx.append("</groundspeak:attributes>");
+ }
+
+ gpx.append("<groundspeak:difficulty>");
+ gpx.append(Float.toString(cache.getDifficulty()));
+ gpx.append("</groundspeak:difficulty>");
+
+ gpx.append("<groundspeak:terrain>");
+ gpx.append(Float.toString(cache.getTerrain()));
+ gpx.append("</groundspeak:terrain>");
+
+ gpx.append("<groundspeak:country>");
+ gpx.append(StringEscapeUtils.escapeXml(cache.getLocation()));
+ gpx.append("</groundspeak:country>");
+
+ gpx.append("<groundspeak:state>");
+ gpx.append(StringEscapeUtils.escapeXml(cache.getLocation()));
+ gpx.append("</groundspeak:state>");
+
+ gpx.append("<groundspeak:short_description html=\"");
+ if (BaseUtils.containsHtml(cache.getShortDescription())) {
+ gpx.append("True");
+ } else {
+ gpx.append("False");
+ }
+ gpx.append("\">");
+ gpx.append(StringEscapeUtils.escapeXml(cache.getShortDescription()));
+ gpx.append("</groundspeak:short_description>");
+
+ gpx.append("<groundspeak:long_description html=\"");
+ if (BaseUtils.containsHtml(cache.getDescription())) {
+ gpx.append("True");
+ } else {
+ gpx.append("False");
+ }
+ gpx.append("\">");
+ gpx.append(StringEscapeUtils.escapeXml(cache.getDescription()));
+ gpx.append("</groundspeak:long_description>");
+
+ gpx.append("<groundspeak:encoded_hints>");
+ gpx.append(StringEscapeUtils.escapeXml(cache.getHint()));
+ gpx.append("</groundspeak:encoded_hints>");
+
+ gpx.append("</groundspeak:cache>");
+
+ //TODO: Waypoints
+
+ if (cache.getLogs().size() > 0) {
+ gpx.append("<groundspeak:logs>");
+
+ for (LogEntry log : cache.getLogs()) {
+ gpx.append("<groundspeak:log id=\"");
+ gpx.append(log.id);
+ gpx.append("\">");
+
+ gpx.append("<groundspeak:date>");
+ gpx.append(StringEscapeUtils.escapeXml(dateFormatZ.format(new Date(log.date))));
+ gpx.append("</groundspeak:date>");
+
+ gpx.append("<groundspeak:type>");
+ gpx.append(StringEscapeUtils.escapeXml(log.type.type));
+ gpx.append("</groundspeak:type>");
+
+ gpx.append("<groundspeak:finder id=\"\">");
+ gpx.append(StringEscapeUtils.escapeXml(log.author));
+ gpx.append("</groundspeak:finder>");
+
+ gpx.append("<groundspeak:text encoded=\"False\">");
+ gpx.append(StringEscapeUtils.escapeXml(log.log));
+ gpx.append("</groundspeak:text>");
+
+ gpx.append("</groundspeak:log>");
+ }
+
+ gpx.append("</groundspeak:logs>");
+ }
+
+ gpx.append("</wpt>");
+
+ publishProgress(i + 1);
+ }
+ } catch (Exception e) {
+ Log.e("GpxExport.ExportTask generation", e);
+ return false;
+ }
+
+ gpx.append("</gpx>");
+
+ if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+ exportLocation.mkdirs();
+
+ SimpleDateFormat fileNameDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
+ exportFile = new File(exportLocation.toString() + '/' + fileNameDateFormat.format(new Date()) + ".gpx");
+
+ OutputStream os = null;
+ Writer fw = null;
+ try {
+ os = new FileOutputStream(exportFile);
+ fw = new OutputStreamWriter(os, "UTF-8");
+ fw.write(gpx.toString());
+ } catch (IOException e) {
+ Log.e("GpxExport.ExportTask export", e);
+ return false;
+ } finally {
+ if (fw != null) {
+ try {
+ fw.close();
+ } catch (IOException e) {
+ Log.e("GpxExport.ExportTask export", e);
+ return false;
+ }
+ }
+ }
+ } else {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ protected void onPostExecute(Boolean result) {
+ if (null != activity) {
+ progress.dismiss();
+ if (result) {
+ ActivityMixin.showToast(activity, getName() + ' ' + getString(R.string.export_exportedto) + ": " + exportFile.toString());
+ } else {
+ ActivityMixin.showToast(activity, getString(R.string.export_failed));
+ }
+ }
+ }
+
+ @Override
+ protected void onProgressUpdate(Integer... status) {
+ if (null != activity) {
+ progress.setProgress(status[0]);
+ }
+ }
+ }
+}