diff --git a/MyTracks/AndroidManifest.xml b/MyTracks/AndroidManifest.xml
index 5ff5ac77e..7d997e93a 100755
--- a/MyTracks/AndroidManifest.xml
+++ b/MyTracks/AndroidManifest.xml
@@ -171,6 +171,7 @@ limitations under the License.
+
@@ -312,7 +313,7 @@ limitations under the License.
-
+
diff --git a/MyTracks/src/com/google/android/apps/mytracks/ExportAllActivity.java b/MyTracks/src/com/google/android/apps/mytracks/ExportAllActivity.java
new file mode 100644
index 000000000..8ff2ebb5b
--- /dev/null
+++ b/MyTracks/src/com/google/android/apps/mytracks/ExportAllActivity.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.android.apps.mytracks;
+
+import com.google.android.apps.mytracks.io.file.TrackWriterFactory.TrackFileFormat;
+import com.google.android.maps.mytracks.R;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.app.ProgressDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.Bundle;
+import android.widget.Toast;
+
+/**
+ * An activity to export all the tracks to the SD card.
+ *
+ * @author Sandor Dornbush
+ */
+public class ExportAllActivity extends Activity {
+
+ public static final String EXTRA_TRACK_FILE_FORMAT = "track_file_format";
+
+ private static final int DIALOG_PROGRESS_ID = 0;
+
+ private ExportAllAsyncTask exportAllAsyncTask;
+ private ProgressDialog progressDialog;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ Object retained = getLastNonConfigurationInstance();
+ if (retained instanceof ExportAllAsyncTask) {
+ exportAllAsyncTask = (ExportAllAsyncTask) retained;
+ exportAllAsyncTask.setActivity(this);
+ } else {
+ Intent intent = getIntent();
+ TrackFileFormat trackFileFormat = intent.getParcelableExtra(EXTRA_TRACK_FILE_FORMAT);
+
+ exportAllAsyncTask = new ExportAllAsyncTask(this, trackFileFormat);
+ exportAllAsyncTask.execute();
+ }
+ }
+
+ @Override
+ public Object onRetainNonConfigurationInstance() {
+ exportAllAsyncTask.setActivity(null);
+ return exportAllAsyncTask;
+ }
+
+ @Override
+ protected Dialog onCreateDialog(int id) {
+ switch (id) {
+ case DIALOG_PROGRESS_ID:
+ progressDialog = new ProgressDialog(this);
+ progressDialog.setCancelable(true);
+ progressDialog.setIcon(android.R.drawable.ic_dialog_info);
+ progressDialog.setIndeterminate(true);
+ progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ exportAllAsyncTask.cancel(true);
+ finish();
+ }
+ });
+ progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
+ progressDialog.setTitle(R.string.track_list_export_all);
+ return progressDialog;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Invokes when the associated AsyncTask completes.
+ *
+ * @param success true if the AsyncTask is successful
+ * @param messageId message id to display to user
+ */
+ public void onAsyncTaskCompleted(boolean success, int messageId) {
+ removeDialog(DIALOG_PROGRESS_ID);
+ Toast.makeText(this, messageId, success ? Toast.LENGTH_SHORT : Toast.LENGTH_LONG).show();
+ finish();
+ }
+
+ /**
+ * Shows the progress dialog.
+ */
+ public void showProgressDialog() {
+ showDialog(DIALOG_PROGRESS_ID);
+ }
+
+ /**
+ * Sets the progress dialog value.
+ *
+ * @param number the number of tracks exported
+ * @param max the maximum number of tracks
+ */
+ public void setProgressDialogValue(int number, int max) {
+ if (progressDialog != null) {
+ progressDialog.setIndeterminate(false);
+ progressDialog.setMax(max);
+ progressDialog.setProgress(Math.min(number, max));
+ }
+ }
+}
diff --git a/MyTracks/src/com/google/android/apps/mytracks/ExportAllAsyncTask.java b/MyTracks/src/com/google/android/apps/mytracks/ExportAllAsyncTask.java
new file mode 100644
index 000000000..06bf1e1f0
--- /dev/null
+++ b/MyTracks/src/com/google/android/apps/mytracks/ExportAllAsyncTask.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.android.apps.mytracks;
+
+import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
+import com.google.android.apps.mytracks.content.TracksColumns;
+import com.google.android.apps.mytracks.io.file.TrackWriter;
+import com.google.android.apps.mytracks.io.file.TrackWriterFactory;
+import com.google.android.apps.mytracks.io.file.TrackWriterFactory.TrackFileFormat;
+import com.google.android.apps.mytracks.util.SystemUtils;
+import com.google.android.maps.mytracks.R;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.database.Cursor;
+import android.os.AsyncTask;
+import android.os.PowerManager.WakeLock;
+
+/**
+ * AsyncTask to export all the tracks to the SD card.
+ *
+ * @author Jimmy Shih
+ */
+public class ExportAllAsyncTask extends AsyncTask {
+
+ private ExportAllActivity exportAllActivity;
+ private final TrackFileFormat trackFileFormat;
+ private final Context context;
+ private final MyTracksProviderUtils myTracksProviderUtils;
+ private WakeLock wakeLock;
+ private TrackWriter trackWriter;
+
+ // true if the AsyncTask result is success
+ private boolean success;
+
+ // true if the AsyncTask has completed
+ private boolean completed;
+
+ // message id to return to the activity
+ private int messageId;
+
+ /**
+ * Creates an AsyncTask.
+ *
+ * @param exportAllActivity the activity currently associated with this
+ * AsyncTask
+ * @param trackFileFormat the track file format
+ */
+ public ExportAllAsyncTask(ExportAllActivity exportAllActivity, TrackFileFormat trackFileFormat) {
+ this.exportAllActivity = exportAllActivity;
+ this.trackFileFormat = trackFileFormat;
+ context = exportAllActivity.getApplicationContext();
+ myTracksProviderUtils = MyTracksProviderUtils.Factory.get(exportAllActivity);
+
+ SharedPreferences sharedPreferences = exportAllActivity.getSharedPreferences(
+ Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
+ long recordingTrackId = sharedPreferences.getLong(
+ exportAllActivity.getString(R.string.recording_track_key), -1L);
+
+ // Get the wake lock if not recording
+ if (recordingTrackId == -1L) {
+ wakeLock = SystemUtils.acquireWakeLock(exportAllActivity, wakeLock);
+ }
+ success = false;
+ completed = false;
+ messageId = R.string.export_error;
+ }
+
+ /**
+ * Sets the current {@link ExportAllActivity} associated with this AyncTask.
+ *
+ * @param exportAllActivity the current {@link ExportAllActivity}, can be null
+ */
+ public void setActivity(ExportAllActivity exportAllActivity) {
+ this.exportAllActivity = exportAllActivity;
+ if (completed && exportAllActivity != null) {
+ exportAllActivity.onAsyncTaskCompleted(success, messageId);
+ }
+ }
+
+ @Override
+ protected void onPreExecute() {
+ if (exportAllActivity != null) {
+ exportAllActivity.showProgressDialog();
+ }
+ }
+
+ @Override
+ protected Boolean doInBackground(Void... params) {
+ Cursor cursor = null;
+ try {
+ cursor = myTracksProviderUtils.getTracksCursor(null, null, TracksColumns._ID);
+ if (cursor == null) {
+ messageId = R.string.export_success;
+ return true;
+ }
+ int count = cursor.getCount();
+ int idIndex = cursor.getColumnIndexOrThrow(TracksColumns._ID);
+ for (int i = 0; i < count; i++) {
+ if (isCancelled()) {
+ return false;
+ }
+ cursor.moveToPosition(i);
+ long id = cursor.getLong(idIndex);
+ trackWriter = TrackWriterFactory.newWriter(
+ context, myTracksProviderUtils, id, trackFileFormat);
+ if (trackWriter == null) {
+ return false;
+ }
+ trackWriter.writeTrack();
+
+ if (!trackWriter.wasSuccess()) {
+ messageId = trackWriter.getErrorMessage();
+ return false;
+ }
+ publishProgress(i + 1, count);
+ }
+ messageId = R.string.export_success;
+ return true;
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
+ // Release the wake lock if obtained
+ if (wakeLock != null && wakeLock.isHeld()) {
+ wakeLock.release();
+ }
+ }
+ }
+
+ @Override
+ protected void onProgressUpdate(Integer... values) {
+ if (exportAllActivity != null) {
+ exportAllActivity.setProgressDialogValue(values[0], values[1]);
+ }
+ }
+
+ @Override
+ protected void onPostExecute(Boolean result) {
+ success = result;
+ completed = true;
+ if (exportAllActivity != null) {
+ exportAllActivity.onAsyncTaskCompleted(success, messageId);
+ }
+ }
+
+ @Override
+ protected void onCancelled() {
+ if (trackWriter != null) {
+ trackWriter.stopWriteTrack();
+ }
+ }
+}
diff --git a/MyTracks/src/com/google/android/apps/mytracks/ExportAllTracks.java b/MyTracks/src/com/google/android/apps/mytracks/ExportAllTracks.java
deleted file mode 100644
index ef6169658..000000000
--- a/MyTracks/src/com/google/android/apps/mytracks/ExportAllTracks.java
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Copyright 2009 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.android.apps.mytracks;
-
-import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
-import com.google.android.apps.mytracks.content.TracksColumns;
-import com.google.android.apps.mytracks.io.file.TrackWriter;
-import com.google.android.apps.mytracks.io.file.TrackWriterFactory;
-import com.google.android.apps.mytracks.io.file.TrackWriterFactory.TrackFileFormat;
-import com.google.android.apps.mytracks.util.SystemUtils;
-import com.google.android.maps.mytracks.R;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.SharedPreferences;
-import android.database.Cursor;
-import android.os.PowerManager.WakeLock;
-import android.util.Log;
-import android.widget.Toast;
-
-/**
- * A class that will export all tracks to the sd card.
- *
- * @author Sandor Dornbush
- */
-public class ExportAllTracks {
- // These must line up with the index in the array.
- public static final int GPX_OPTION_INDEX = 0;
- public static final int KML_OPTION_INDEX = 1;
- public static final int CSV_OPTION_INDEX = 2;
- public static final int TCX_OPTION_INDEX = 3;
-
- private final Activity activity;
- private WakeLock wakeLock;
- private ProgressDialog progress;
-
- private TrackFileFormat format = TrackFileFormat.GPX;
-
- private final DialogInterface.OnClickListener itemClick =
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- switch (which) {
- case GPX_OPTION_INDEX:
- format = TrackFileFormat.GPX;
- break;
- case KML_OPTION_INDEX:
- format = TrackFileFormat.KML;
- break;
- case CSV_OPTION_INDEX:
- format = TrackFileFormat.CSV;
- break;
- case TCX_OPTION_INDEX:
- format = TrackFileFormat.TCX;
- break;
- default:
- Log.w(Constants.TAG, "Unknown export format: " + which);
- }
- }
- };
-
- public ExportAllTracks(Activity activity) {
- this.activity = activity;
- Log.i(Constants.TAG, "ExportAllTracks: Starting");
-
- String exportFileFormat = activity.getString(R.string.track_list_export_file);
- String fileTypes[] = activity.getResources().getStringArray(R.array.file_types);
-
- String[] choices = new String[fileTypes.length];
- for (int i = 0; i < fileTypes.length; i++) {
- choices[i] = String.format(exportFileFormat, fileTypes[i]);
- }
-
- AlertDialog.Builder builder = new AlertDialog.Builder(activity);
- builder.setTitle(R.string.track_list_export_all);
- builder.setSingleChoiceItems(choices, 0, itemClick);
- builder.setPositiveButton(R.string.generic_ok, positiveClick);
- builder.setNegativeButton(R.string.generic_cancel, null);
- builder.show();
- }
-
- private final DialogInterface.OnClickListener positiveClick =
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- new Thread(runner, "ExportAllTracks").start();
- }
- };
-
- private final Runnable runner = new Runnable() {
- public void run() {
- aquireLocksAndExport();
- }
- };
-
- /**
- * Makes sure that we keep the phone from sleeping.
- * See if there is a current track. Aquire a wake lock if there is no
- * current track.
- */
- private void aquireLocksAndExport() {
- SharedPreferences prefs = activity.getSharedPreferences(
- Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
- long recordingTrackId = -1;
- if (prefs != null) {
- recordingTrackId =
- prefs.getLong(activity.getString(R.string.recording_track_key), -1);
- }
- if (recordingTrackId != -1) {
- wakeLock = SystemUtils.acquireWakeLock(activity, wakeLock);
- }
-
- // Now we can safely export everything.
- exportAll();
-
- // Release the wake lock if we recorded one.
- // TODO check what happens if we started recording after getting this lock.
- if (wakeLock != null && wakeLock.isHeld()) {
- wakeLock.release();
- Log.i(Constants.TAG, "ExportAllTracks: Releasing wake lock.");
- }
- Log.i(Constants.TAG, "ExportAllTracks: Done");
- showToast(R.string.export_success, Toast.LENGTH_SHORT);
- }
-
- private void makeProgressDialog(final int trackCount) {
- String exportMsg = activity.getString(R.string.track_list_export_all);
- progress = new ProgressDialog(activity);
- progress.setIcon(android.R.drawable.ic_dialog_info);
- progress.setTitle(exportMsg);
- progress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
- progress.setMax(trackCount);
- progress.setProgress(0);
- progress.show();
- }
-
- /**
- * Actually export the tracks.
- * This should be called after the wake locks have been aquired.
- */
- private void exportAll() {
- // Get a cursor over all tracks.
- Cursor cursor = null;
- try {
- MyTracksProviderUtils providerUtils =
- MyTracksProviderUtils.Factory.get(activity);
- cursor = providerUtils.getTracksCursor(null, null, TracksColumns._ID);
- if (cursor == null) {
- return;
- }
-
- final int trackCount = cursor.getCount();
- Log.i(Constants.TAG,
- "ExportAllTracks: Exporting: " + cursor.getCount() + " tracks.");
- int idxTrackId = cursor.getColumnIndexOrThrow(TracksColumns._ID);
- activity.runOnUiThread(new Runnable() {
- public void run() {
- makeProgressDialog(trackCount);
- }
- });
-
- for (int i = 0; cursor.moveToNext(); i++) {
- final int status = i;
- activity.runOnUiThread(new Runnable() {
- public void run() {
- synchronized (this) {
- if (progress == null) {
- return;
- }
- progress.setProgress(status);
- }
- }
- });
-
- long id = cursor.getLong(idxTrackId);
- Log.i(Constants.TAG, "ExportAllTracks: exporting: " + id);
- TrackWriter writer =
- TrackWriterFactory.newWriter(activity, providerUtils, id, format);
- if (writer == null) {
- showToast(R.string.export_error, Toast.LENGTH_LONG);
- return;
- }
-
- writer.writeTrack();
-
- if (!writer.wasSuccess()) {
- // Abort the whole export on the first error.
- showToast(writer.getErrorMessage(), Toast.LENGTH_LONG);
- return;
- }
- }
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- if (progress != null) {
- synchronized (this) {
- progress.dismiss();
- progress = null;
- }
- }
- }
- }
-
- private void showToast(final int messageId, final int length) {
- activity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- Toast.makeText(activity, messageId, length).show();
- }
- });
- }
-}
diff --git a/MyTracks/src/com/google/android/apps/mytracks/TrackList.java b/MyTracks/src/com/google/android/apps/mytracks/TrackList.java
index 83bc2af0e..be0af96b1 100644
--- a/MyTracks/src/com/google/android/apps/mytracks/TrackList.java
+++ b/MyTracks/src/com/google/android/apps/mytracks/TrackList.java
@@ -28,10 +28,12 @@ import com.google.android.apps.mytracks.util.PlayTrackUtils;
import com.google.android.apps.mytracks.util.StringUtils;
import com.google.android.maps.mytracks.R;
+import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ListActivity;
import android.content.ContentUris;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
@@ -64,7 +66,8 @@ public class TrackList extends ListActivity
implements SharedPreferences.OnSharedPreferenceChangeListener,
View.OnClickListener {
- private static final int DIALOG_INSTALL_EARTH = 0;
+ private static final int DIALOG_INSTALL_EARTH_ID = 0;
+ private static final int DIALOG_EXPORT_ALL_ID = 1;
private int contextPosition = -1;
private long trackId = -1;
@@ -180,7 +183,7 @@ public class TrackList extends ListActivity
PlayTrackUtils.playTrack(this, trackId);
return true;
} else {
- showDialog(DIALOG_INSTALL_EARTH);
+ showDialog(DIALOG_INSTALL_EARTH_ID);
return true;
}
case Constants.MENU_SEND_TO_GOOGLE:
@@ -257,7 +260,7 @@ public class TrackList extends ListActivity
break;
}
case R.id.tracklist_btn_export_all: {
- new ExportAllTracks(this);
+ showDialog(DIALOG_EXPORT_ALL_ID);
break;
}
case R.id.tracklist_btn_import_all: {
@@ -327,8 +330,30 @@ public class TrackList extends ListActivity
@Override
protected Dialog onCreateDialog(int id) {
switch (id) {
- case DIALOG_INSTALL_EARTH:
+ case DIALOG_INSTALL_EARTH_ID:
return PlayTrackUtils.createInstallEarthDialog(this);
+ case DIALOG_EXPORT_ALL_ID:
+ String exportFileFormat = getString(R.string.track_list_export_file);
+ String fileTypes[] = getResources().getStringArray(R.array.file_types);
+ String[] choices = new String[fileTypes.length];
+ for (int i = 0; i < fileTypes.length; i++) {
+ choices[i] = String.format(exportFileFormat, fileTypes[i]);
+ }
+ return new AlertDialog.Builder(this)
+ .setNegativeButton(R.string.generic_cancel, null)
+ .setPositiveButton(R.string.generic_ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ int index = ((AlertDialog) dialog).getListView().getCheckedItemPosition();
+ Intent intent = new Intent(TrackList.this, ExportAllActivity.class);
+ intent.putExtra(ExportAllActivity.EXTRA_TRACK_FILE_FORMAT,
+ (Parcelable) TrackFileFormat.values()[index]);
+ TrackList.this.startActivity(intent);
+ }
+ })
+ .setSingleChoiceItems(choices, 0, null)
+ .setTitle(R.string.track_list_export_all)
+ .create();
default:
return null;
}
diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/file/SaveActivity.java b/MyTracks/src/com/google/android/apps/mytracks/io/file/SaveActivity.java
index 13aae9a44..8ecbfb596 100644
--- a/MyTracks/src/com/google/android/apps/mytracks/io/file/SaveActivity.java
+++ b/MyTracks/src/com/google/android/apps/mytracks/io/file/SaveActivity.java
@@ -51,8 +51,8 @@ public class SaveActivity extends Activity {
private static final String TAG = SaveActivity.class.getSimpleName();
- private static final int DIALOG_PROGRESS_ID = 1;
- private static final int DIALOG_RESULT_ID = 2;
+ private static final int DIALOG_PROGRESS_ID = 0;
+ private static final int DIALOG_RESULT_ID = 1;
private long trackId;
private TrackFileFormat trackFileFormat;