forked from upstream-mirrors/OpenTracks
sync from main
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* 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.io.backup;
|
||||
|
||||
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.os.Bundle;
|
||||
import android.widget.Toast;
|
||||
|
||||
/**
|
||||
* Activity to backup data to the SD card.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class BackupActivity extends Activity {
|
||||
|
||||
private static final int DIALOG_PROGRESS_ID = 0;
|
||||
|
||||
private BackupAsyncTask backupAsyncTask;
|
||||
private ProgressDialog progressDialog;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
Object retained = getLastNonConfigurationInstance();
|
||||
if (retained instanceof BackupAsyncTask) {
|
||||
backupAsyncTask = (BackupAsyncTask) retained;
|
||||
backupAsyncTask.setActivity(this);
|
||||
} else {
|
||||
backupAsyncTask = new BackupAsyncTask(this);
|
||||
backupAsyncTask.execute();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object onRetainNonConfigurationInstance() {
|
||||
backupAsyncTask.setActivity(null);
|
||||
return backupAsyncTask;
|
||||
}
|
||||
|
||||
@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.setMessage(getString(R.string.settings_backup_now_progress_message));
|
||||
progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
|
||||
progressDialog.setTitle(R.string.generic_progress_title);
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1,240 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010 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.io.backup;
|
||||
|
||||
import com.google.android.apps.mytracks.Constants;
|
||||
import com.google.android.apps.mytracks.MyTracks;
|
||||
import com.google.android.apps.mytracks.util.FileUtils;
|
||||
import com.google.android.apps.mytracks.util.StringUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.AlertDialog.Builder;
|
||||
import android.app.Dialog;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.content.Intent;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Helper which shows a UI for writing or restoring a backup,
|
||||
* and calls the appropriate handler for actually executing those
|
||||
* operations.
|
||||
*
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
public class BackupActivityHelper {
|
||||
|
||||
private static final Comparator<Date> REVERSE_DATE_ORDER =
|
||||
new Comparator<Date>() {
|
||||
@Override
|
||||
public int compare(Date s1, Date s2) {
|
||||
return s2.compareTo(s1);
|
||||
}
|
||||
};
|
||||
|
||||
private final FileUtils fileUtils;
|
||||
private final ExternalFileBackup backup;
|
||||
private final Activity activity;
|
||||
|
||||
public BackupActivityHelper(Activity activity) {
|
||||
this.activity = activity;
|
||||
this.fileUtils = new FileUtils();
|
||||
this.backup = new ExternalFileBackup(activity, fileUtils);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a full backup to the default file.
|
||||
* This shows the results to the user.
|
||||
*/
|
||||
public void writeBackup() {
|
||||
if (!fileUtils.isSdCardAvailable()) {
|
||||
showToast(R.string.sd_card_error_no_storage);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!backup.isBackupsDirectoryAvailable(true)) {
|
||||
showToast(R.string.sd_card_error_create_dir);
|
||||
return;
|
||||
}
|
||||
|
||||
final ProgressDialog progressDialog = ProgressDialog.show(
|
||||
activity,
|
||||
activity.getString(R.string.generic_progress_title),
|
||||
activity.getString(R.string.settings_backup_now_progress_message),
|
||||
true);
|
||||
|
||||
// Do the writing in another thread
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
backup.writeToDefaultFile();
|
||||
showToast(R.string.sd_card_success_write_file);
|
||||
} catch (IOException e) {
|
||||
Log.e(Constants.TAG, "Failed to write backup", e);
|
||||
showToast(R.string.sd_card_error_write_file);
|
||||
} finally {
|
||||
dismissDialog(progressDialog);
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores a full backup from the SD card.
|
||||
* The user will be given a choice of which backup to restore as well as a
|
||||
* confirmation dialog.
|
||||
*/
|
||||
public void restoreBackup() {
|
||||
// Get the list of existing backups
|
||||
if (!fileUtils.isSdCardAvailable()) {
|
||||
showToast(R.string.sd_card_error_no_storage);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!backup.isBackupsDirectoryAvailable(false)) {
|
||||
showToast(R.string.settings_backup_restore_no_backup);
|
||||
return;
|
||||
}
|
||||
|
||||
final Date[] backupDates = backup.getAvailableBackups();
|
||||
if (backupDates == null || backupDates.length == 0) {
|
||||
showToast(R.string.settings_backup_restore_no_backup);
|
||||
return;
|
||||
}
|
||||
Arrays.sort(backupDates, REVERSE_DATE_ORDER);
|
||||
|
||||
// Show a confirmation dialog
|
||||
Builder confirmationDialogBuilder = new AlertDialog.Builder(activity);
|
||||
confirmationDialogBuilder.setMessage(R.string.settings_backup_restore_confirm_message);
|
||||
confirmationDialogBuilder.setCancelable(true);
|
||||
confirmationDialogBuilder.setPositiveButton(android.R.string.yes,
|
||||
new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
pickBackupForRestore(backupDates);
|
||||
}
|
||||
});
|
||||
confirmationDialogBuilder.setNegativeButton(android.R.string.no, null);
|
||||
confirmationDialogBuilder.create().show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a backup list for the user to pick, then restores it.
|
||||
*
|
||||
* @param backupDates the list of available backup files
|
||||
*/
|
||||
private void pickBackupForRestore(final Date[] backupDates) {
|
||||
if (backupDates.length == 1) {
|
||||
// Only one choice, don't bother showing the list
|
||||
restoreFromDateAsync(backupDates[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
// Make a user-visible version of the backup filenames
|
||||
final String backupDateStrs[] = new String[backupDates.length];
|
||||
for (int i = 0; i < backupDates.length; i++) {
|
||||
backupDateStrs[i] = StringUtils.formatDateTime(activity, backupDates[i].getTime());
|
||||
}
|
||||
|
||||
// Show a dialog for the user to pick which backup to restore
|
||||
Builder dialogBuilder = new AlertDialog.Builder(activity);
|
||||
dialogBuilder.setCancelable(true);
|
||||
dialogBuilder.setTitle(R.string.settings_backup_restore_select_title);
|
||||
dialogBuilder.setItems(backupDateStrs, new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
// User picked to restore this one
|
||||
restoreFromDateAsync(backupDates[which]);
|
||||
}
|
||||
});
|
||||
dialogBuilder.create().show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a progress dialog, then starts restoring the backup asynchronously.
|
||||
*
|
||||
* @param date the date
|
||||
*/
|
||||
private void restoreFromDateAsync(final Date date) {
|
||||
// Show a progress dialog
|
||||
ProgressDialog.show(
|
||||
activity,
|
||||
activity.getString(R.string.generic_progress_title),
|
||||
activity.getString(R.string.settings_backup_restore_progress_message),
|
||||
true);
|
||||
|
||||
// Do the actual importing in another thread (don't block the UI)
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
backup.restoreFromDate(date);
|
||||
showToast(R.string.sd_card_success_read_file);
|
||||
} catch (IOException e) {
|
||||
Log.e(Constants.TAG, "Failed to restore backup", e);
|
||||
showToast(R.string.sd_card_error_read_file);
|
||||
} finally {
|
||||
// Data may have been restored, "reboot" the app to catch it
|
||||
restartApplication();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Restarts My Tracks completely.
|
||||
* This forces any modified data to be re-read.
|
||||
*/
|
||||
private void restartApplication() {
|
||||
Intent intent = new Intent(activity, MyTracks.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
activity.startActivity(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a toast with the given contents.
|
||||
*/
|
||||
private void showToast(final int resId) {
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(activity, resId, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely dismisses the given dialog.
|
||||
*/
|
||||
private void dismissDialog(final Dialog dialog) {
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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.io.backup;
|
||||
|
||||
import com.google.android.apps.mytracks.util.FileUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* AsyncTask to backup data to the SD card.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class BackupAsyncTask extends AsyncTask<Void, Integer, Boolean> {
|
||||
|
||||
private static final String TAG = BackupAsyncTask.class.getSimpleName();
|
||||
|
||||
private BackupActivity backupActivity;
|
||||
private final ExternalFileBackup externalFileBackup;
|
||||
|
||||
// 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 backupActivity the activity currently associated with this
|
||||
* AsyncTask
|
||||
*/
|
||||
public BackupAsyncTask(BackupActivity backupActivity) {
|
||||
this.backupActivity = backupActivity;
|
||||
this.externalFileBackup = new ExternalFileBackup(backupActivity, new FileUtils());
|
||||
success = false;
|
||||
completed = false;
|
||||
messageId = R.string.sd_card_error_write_file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current {@link BackupActivity} associated with this AyncTask.
|
||||
*
|
||||
* @param activity the current {@link BackupActivity}, can be null
|
||||
*/
|
||||
public void setActivity(BackupActivity activity) {
|
||||
this.backupActivity = activity;
|
||||
if (completed && backupActivity != null) {
|
||||
backupActivity.onAsyncTaskCompleted(success, messageId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
if (backupActivity != null) {
|
||||
backupActivity.showProgressDialog();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... params) {
|
||||
FileUtils fileUtils = new FileUtils();
|
||||
|
||||
if (!fileUtils.isSdCardAvailable()) {
|
||||
messageId = R.string.sd_card_error_no_storage;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!externalFileBackup.isBackupsDirectoryAvailable(true)) {
|
||||
messageId = R.string.sd_card_error_create_dir;
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
externalFileBackup.writeToDefaultFile();
|
||||
messageId = R.string.sd_card_success_write_file;
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
Log.d(TAG, "IO exception", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean result) {
|
||||
success = result;
|
||||
completed = true;
|
||||
if (backupActivity != null) {
|
||||
backupActivity.onAsyncTaskCompleted(success, messageId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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.io.backup;
|
||||
|
||||
import com.google.android.apps.mytracks.MyTracks;
|
||||
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.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* An activity to restore data from the SD card.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class RestoreActivity extends Activity {
|
||||
|
||||
public static final String EXTRA_DATE = "date";
|
||||
|
||||
private static final String TAG = RestoreActivity.class.getSimpleName();
|
||||
private static final int DIALOG_PROGRESS_ID = 0;
|
||||
|
||||
private RestoreAsyncTask restoreAsyncTask;
|
||||
private ProgressDialog progressDialog;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
Object retained = getLastNonConfigurationInstance();
|
||||
if (retained instanceof RestoreAsyncTask) {
|
||||
restoreAsyncTask = (RestoreAsyncTask) retained;
|
||||
restoreAsyncTask.setActivity(this);
|
||||
} else {
|
||||
long date = getIntent().getLongExtra(EXTRA_DATE, -1L);
|
||||
if (date == -1L) {
|
||||
Log.d(TAG, "Invalid date");
|
||||
finish();
|
||||
}
|
||||
restoreAsyncTask = new RestoreAsyncTask(this, new Date(date));
|
||||
restoreAsyncTask.execute();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object onRetainNonConfigurationInstance() {
|
||||
restoreAsyncTask.setActivity(null);
|
||||
return restoreAsyncTask;
|
||||
}
|
||||
|
||||
@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.setMessage(getString(R.string.settings_backup_restore_progress_message));
|
||||
progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
|
||||
progressDialog.setTitle(R.string.generic_progress_title);
|
||||
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();
|
||||
startActivity(new Intent(this, MyTracks.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
|
||||
finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the progress dialog.
|
||||
*/
|
||||
public void showProgressDialog() {
|
||||
showDialog(DIALOG_PROGRESS_ID);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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.io.backup;
|
||||
|
||||
import com.google.android.apps.mytracks.util.FileUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* AsyncTask to restore data from the SD card.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class RestoreAsyncTask extends AsyncTask<Void, Integer, Boolean> {
|
||||
|
||||
private static final String TAG = RestoreAsyncTask.class.getSimpleName();
|
||||
|
||||
private RestoreActivity restoreActivity;
|
||||
private final Date date;
|
||||
private final ExternalFileBackup externalFileBackup;
|
||||
|
||||
// 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 restoreActivity the activity currently associated with this
|
||||
* AsyncTask
|
||||
* @param date the date to retore from
|
||||
*/
|
||||
public RestoreAsyncTask(RestoreActivity restoreActivity, Date date) {
|
||||
this.restoreActivity = restoreActivity;
|
||||
this.date = date;
|
||||
this.externalFileBackup = new ExternalFileBackup(restoreActivity, new FileUtils());
|
||||
success = false;
|
||||
completed = false;
|
||||
messageId = R.string.sd_card_error_read_file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current {@link RestoreActivity} associated with this AyncTask.
|
||||
*
|
||||
* @param activity the current {@link RestoreActivity}, can be null
|
||||
*/
|
||||
public void setActivity(RestoreActivity activity) {
|
||||
this.restoreActivity = activity;
|
||||
if (completed && restoreActivity != null) {
|
||||
restoreActivity.onAsyncTaskCompleted(success, messageId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
if (restoreActivity != null) {
|
||||
restoreActivity.showProgressDialog();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... params) {
|
||||
try {
|
||||
externalFileBackup.restoreFromDate(date);
|
||||
messageId = R.string.sd_card_success_read_file;
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
Log.d(TAG, "IO exception", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean result) {
|
||||
success = result;
|
||||
completed = true;
|
||||
if (restoreActivity != null) {
|
||||
restoreActivity.onAsyncTaskCompleted(success, messageId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* 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.io.backup;
|
||||
|
||||
import com.google.android.apps.mytracks.util.FileUtils;
|
||||
import com.google.android.apps.mytracks.util.StringUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnCancelListener;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* An activity to choose a date to restore from.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class RestoreChooserActivity extends Activity {
|
||||
|
||||
private static final Comparator<Date> REVERSE_DATE_ORDER = new Comparator<Date>() {
|
||||
@Override
|
||||
public int compare(Date s1, Date s2) {
|
||||
return s2.compareTo(s1);
|
||||
}
|
||||
};
|
||||
private static final int DIALOG_CHOOSER_ID = 0;
|
||||
|
||||
private Date[] backupDates;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
FileUtils fileUtils = new FileUtils();
|
||||
ExternalFileBackup externalFileBackup = new ExternalFileBackup(this, fileUtils);
|
||||
|
||||
// Get the list of existing backups
|
||||
if (!fileUtils.isSdCardAvailable()) {
|
||||
Toast.makeText(this, R.string.sd_card_error_no_storage, Toast.LENGTH_LONG).show();
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!externalFileBackup.isBackupsDirectoryAvailable(false)) {
|
||||
Toast.makeText(this, R.string.settings_backup_restore_no_backup, Toast.LENGTH_LONG).show();
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
backupDates = externalFileBackup.getAvailableBackups();
|
||||
if (backupDates == null || backupDates.length == 0) {
|
||||
Toast.makeText(this, R.string.settings_backup_restore_no_backup, Toast.LENGTH_LONG).show();
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
if (backupDates.length == 1) {
|
||||
startActivity(new Intent(this, RestoreActivity.class)
|
||||
.putExtra(RestoreActivity.EXTRA_DATE, backupDates[0].getTime()));
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
Arrays.sort(backupDates, REVERSE_DATE_ORDER);
|
||||
showDialog(DIALOG_CHOOSER_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Dialog onCreateDialog(int id) {
|
||||
switch (id) {
|
||||
case DIALOG_CHOOSER_ID:
|
||||
String items[] = new String[backupDates.length];
|
||||
for (int i = 0; i < backupDates.length; i++) {
|
||||
items[i] = StringUtils.formatDateTime(this, backupDates[i].getTime());
|
||||
}
|
||||
return new AlertDialog.Builder(this)
|
||||
.setCancelable(true)
|
||||
.setItems(items, new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
startActivity(new Intent(RestoreChooserActivity.this, RestoreActivity.class)
|
||||
.putExtra(RestoreActivity.EXTRA_DATE, backupDates[which].getTime()));
|
||||
finish();
|
||||
}
|
||||
})
|
||||
.setOnCancelListener(new OnCancelListener() {
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
finish();
|
||||
}
|
||||
})
|
||||
.setTitle(R.string.settings_backup_restore_select_title)
|
||||
.create();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 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.io.file;
|
||||
|
||||
import static com.google.android.apps.mytracks.Constants.TAG;
|
||||
|
||||
import com.google.android.apps.mytracks.ImportAllTracks;
|
||||
import com.google.android.apps.mytracks.util.UriUtils;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* An activity that imports a track from a file and displays the track in My Tracks.
|
||||
*
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
public class ImportActivity extends Activity {
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
|
||||
Intent intent = getIntent();
|
||||
String action = intent.getAction();
|
||||
Uri data = intent.getData();
|
||||
if (!(Intent.ACTION_VIEW.equals(action) || Intent.ACTION_ATTACH_DATA.equals(action))) {
|
||||
Log.e(TAG, "Received an intent with unsupported action: " + intent);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!UriUtils.isFileUri(data)) {
|
||||
Log.e(TAG, "Received an intent with unsupported data: " + intent);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
String path = data.getPath();
|
||||
Log.i(TAG, "Importing GPX file at " + path);
|
||||
new ImportAllTracks(this, path);
|
||||
}
|
||||
}
|
||||
@@ -13,24 +13,19 @@
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.android.apps.mytracks.io.file;
|
||||
|
||||
import static com.google.android.apps.mytracks.Constants.TAG;
|
||||
|
||||
import com.google.android.apps.mytracks.Constants;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.TracksColumns;
|
||||
import com.google.android.apps.mytracks.io.file.TrackWriterFactory.TrackFileFormat;
|
||||
import com.google.android.apps.mytracks.util.FileUtils;
|
||||
import com.google.android.apps.mytracks.util.PlayTrackUtils;
|
||||
import com.google.android.apps.mytracks.util.UriUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.ContentUris;
|
||||
import android.content.Context;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnCancelListener;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
@@ -42,208 +37,190 @@ import android.util.Log;
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Activity for saving a track to a file (and optionally sending that file).
|
||||
* Activity for saving a track to the SD card, and optionally share or play the
|
||||
* track.
|
||||
*
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
public class SaveActivity extends Activity {
|
||||
public static final String EXTRA_FILE_FORMAT = "file_format";
|
||||
public static final String EXTRA_SHARE_FILE = "share_file";
|
||||
public static final String EXTRA_PLAY_FILE = "play_file";
|
||||
|
||||
private static final int RESULT_DIALOG = 1;
|
||||
/* VisibleForTesting */
|
||||
static final int PROGRESS_DIALOG = 2;
|
||||
public static final String EXTRA_TRACK_ID = "track_id";
|
||||
public static final String EXTRA_TRACK_FILE_FORMAT = "track_file_format";
|
||||
public static final String EXTRA_SHARE_TRACK = "share_track";
|
||||
public static final String EXTRA_PLAY_TRACK = "play_track";
|
||||
|
||||
private static final String TAG = SaveActivity.class.getSimpleName();
|
||||
|
||||
private static final int DIALOG_PROGRESS_ID = 0;
|
||||
private static final int DIALOG_RESULT_ID = 1;
|
||||
|
||||
private MyTracksProviderUtils providerUtils;
|
||||
private long trackId;
|
||||
private TrackWriter writer;
|
||||
private boolean shareFile;
|
||||
private boolean playFile;
|
||||
private TrackFileFormat format;
|
||||
private WriteProgressController controller;
|
||||
private TrackFileFormat trackFileFormat;
|
||||
private boolean shareTrack;
|
||||
private boolean playTrack;
|
||||
|
||||
private SaveAsyncTask saveAsyncTask;
|
||||
private ProgressDialog progressDialog;
|
||||
|
||||
// result from the AsyncTask
|
||||
private boolean success;
|
||||
|
||||
// message id from the AsyncTask
|
||||
private int messageId;
|
||||
|
||||
// path of the saved file
|
||||
private String filePath;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
providerUtils = MyTracksProviderUtils.Factory.get(this);
|
||||
Intent intent = getIntent();
|
||||
trackId = intent.getLongExtra(EXTRA_TRACK_ID, -1L);
|
||||
if (trackId < 0) {
|
||||
Log.d(TAG, "Invalid track id");
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
trackFileFormat = intent.getParcelableExtra(EXTRA_TRACK_FILE_FORMAT);
|
||||
shareTrack = intent.getBooleanExtra(EXTRA_SHARE_TRACK, false);
|
||||
playTrack = intent.getBooleanExtra(EXTRA_PLAY_TRACK, false);
|
||||
|
||||
Object retained = getLastNonConfigurationInstance();
|
||||
if (retained instanceof SaveAsyncTask) {
|
||||
saveAsyncTask = (SaveAsyncTask) retained;
|
||||
saveAsyncTask.setActivity(this);
|
||||
} else {
|
||||
TrackWriter trackWriter = TrackWriterFactory.newWriter(
|
||||
this, MyTracksProviderUtils.Factory.get(this), trackId, trackFileFormat);
|
||||
if (trackWriter == null) {
|
||||
Log.e(TAG, "Track writer is null");
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
if (shareTrack || playTrack) {
|
||||
// Save to the temp directory
|
||||
String dirName = new FileUtils().buildExternalDirectoryPath(
|
||||
trackFileFormat.getExtension(), "tmp");
|
||||
trackWriter.setDirectory(new File(dirName));
|
||||
}
|
||||
saveAsyncTask = new SaveAsyncTask(this, trackWriter);
|
||||
saveAsyncTask.execute();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
public Object onRetainNonConfigurationInstance() {
|
||||
saveAsyncTask.setActivity(null);
|
||||
return saveAsyncTask;
|
||||
}
|
||||
|
||||
Intent intent = getIntent();
|
||||
String action = intent.getAction();
|
||||
String type = intent.getType();
|
||||
Uri data = intent.getData();
|
||||
if (!getString(R.string.track_action_save).equals(action)
|
||||
|| !TracksColumns.CONTENT_ITEMTYPE.equals(type)
|
||||
|| !UriUtils.matchesContentUri(data, TracksColumns.CONTENT_URI)) {
|
||||
Log.e(TAG, "Got bad save intent: " + intent);
|
||||
finish();
|
||||
return;
|
||||
@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.setMessage(getString(R.string.sd_card_progress_write_file));
|
||||
progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
saveAsyncTask.cancel(true);
|
||||
finish();
|
||||
}
|
||||
});
|
||||
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
|
||||
progressDialog.setTitle(R.string.generic_progress_title);
|
||||
return progressDialog;
|
||||
case DIALOG_RESULT_ID:
|
||||
return new AlertDialog.Builder(this)
|
||||
.setCancelable(true)
|
||||
.setIcon(success
|
||||
? android.R.drawable.ic_dialog_info : android.R.drawable.ic_dialog_alert)
|
||||
.setMessage(messageId)
|
||||
.setOnCancelListener(new OnCancelListener() {
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
dialog.dismiss();
|
||||
onPostResultDialog();
|
||||
}
|
||||
})
|
||||
.setPositiveButton(R.string.generic_ok, new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int arg1) {
|
||||
dialog.dismiss();
|
||||
onPostResultDialog();
|
||||
}
|
||||
})
|
||||
.setTitle(success ? R.string.generic_success_title : R.string.generic_error_title)
|
||||
.create();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
trackId = ContentUris.parseId(data);
|
||||
/**
|
||||
* Invokes when the associated AsyncTask completes.
|
||||
*
|
||||
* @param isSuccess true if the AsyncTask is successful
|
||||
* @param aMessageId the id of the AsyncTask message
|
||||
* @param aPath the path of the saved file
|
||||
*/
|
||||
public void onAsyncTaskCompleted(boolean isSuccess, int aMessageId, String aPath) {
|
||||
this.success = isSuccess;
|
||||
this.messageId = aMessageId;
|
||||
this.filePath = aPath;
|
||||
removeDialog(DIALOG_PROGRESS_ID);
|
||||
showDialog(DIALOG_RESULT_ID);
|
||||
}
|
||||
|
||||
int formatIdx = intent.getIntExtra(EXTRA_FILE_FORMAT, -1);
|
||||
format = TrackFileFormat.values()[formatIdx];
|
||||
shareFile = intent.getBooleanExtra(EXTRA_SHARE_FILE, false);
|
||||
playFile = intent.getBooleanExtra(EXTRA_PLAY_FILE, false);
|
||||
|
||||
writer = TrackWriterFactory.newWriter(this, providerUtils, trackId, format);
|
||||
if (writer == null) {
|
||||
Log.e(TAG, "Unable to build writer");
|
||||
finish();
|
||||
return;
|
||||
/**
|
||||
* Shows the progress dialog.
|
||||
*/
|
||||
public void showProgressDialog() {
|
||||
showDialog(DIALOG_PROGRESS_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the progress dialog value.
|
||||
*
|
||||
* @param number the number of points saved
|
||||
* @param max the maximum number of points
|
||||
*/
|
||||
public void setProgressDialogValue(int number, int max) {
|
||||
if (progressDialog != null) {
|
||||
progressDialog.setIndeterminate(false);
|
||||
progressDialog.setMax(max);
|
||||
progressDialog.setProgress(Math.min(number, max));
|
||||
}
|
||||
|
||||
if (shareFile || playFile) {
|
||||
// If the file is for sending, save it to a temporary location instead.
|
||||
FileUtils fileUtils = new FileUtils();
|
||||
String extension = format.getExtension();
|
||||
String dirName = fileUtils.buildExternalDirectoryPath(extension, "tmp");
|
||||
|
||||
File dir = new File(dirName);
|
||||
writer.setDirectory(dir);
|
||||
}
|
||||
|
||||
controller = new WriteProgressController(this, writer, PROGRESS_DIALOG);
|
||||
controller.setOnCompletionListener(new WriteProgressController.OnCompletionListener() {
|
||||
@Override
|
||||
public void onComplete() {
|
||||
showDialog(RESULT_DIALOG);
|
||||
}
|
||||
});
|
||||
controller.startWrite();
|
||||
}
|
||||
|
||||
/**
|
||||
* To be invoked after showing the result dialog.
|
||||
*/
|
||||
private void onPostResultDialog() {
|
||||
if (writer.wasSuccess()) {
|
||||
if (shareFile) {
|
||||
shareWrittenFile();
|
||||
} else if (playFile) {
|
||||
playWrittenFile();
|
||||
if (success) {
|
||||
if (shareTrack) {
|
||||
Intent intent = new Intent(Intent.ACTION_SEND)
|
||||
.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(filePath)))
|
||||
.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.share_track_subject))
|
||||
.putExtra(Intent.EXTRA_TEXT, getString(R.string.share_track_file_body_format))
|
||||
.putExtra(getString(R.string.track_id_broadcast_extra), trackId)
|
||||
.setType(trackFileFormat.getMimeType());
|
||||
startActivity(Intent.createChooser(intent, getString(R.string.share_track_picker_title)));
|
||||
} else if (playTrack) {
|
||||
Intent intent = new Intent()
|
||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
.putExtra(PlayTrackUtils.TOUR_FEATURE_ID, KmlTrackWriter.TOUR_FEATURE_ID)
|
||||
.setClassName(PlayTrackUtils.GOOGLE_EARTH_PACKAGE, PlayTrackUtils.GOOGLE_EARTH_CLASS)
|
||||
.setDataAndType(Uri.fromFile(new File(filePath)), PlayTrackUtils.KML_MIME_TYPE);
|
||||
startActivity(intent);
|
||||
}
|
||||
}
|
||||
finish();
|
||||
}
|
||||
|
||||
private void shareWrittenFile() {
|
||||
// Share the file.
|
||||
Intent shareIntent = new Intent(Intent.ACTION_SEND);
|
||||
shareIntent.putExtra(Intent.EXTRA_SUBJECT,
|
||||
getResources().getText(R.string.share_track_subject).toString());
|
||||
shareIntent.putExtra(Intent.EXTRA_TEXT,
|
||||
getResources().getText(R.string.share_track_file_body_format)
|
||||
.toString());
|
||||
shareIntent.setType(format.getMimeType());
|
||||
Uri u = Uri.fromFile(new File(writer.getAbsolutePath()));
|
||||
shareIntent.putExtra(Intent.EXTRA_STREAM, u);
|
||||
shareIntent.putExtra(getString(R.string.track_id_broadcast_extra), trackId);
|
||||
startActivity(Intent.createChooser(shareIntent,
|
||||
getResources().getText(R.string.share_track_picker_title).toString()));
|
||||
}
|
||||
|
||||
private void playWrittenFile() {
|
||||
Uri uri = Uri.fromFile(new File(writer.getAbsolutePath()));
|
||||
Intent intent = new Intent()
|
||||
.setClassName(PlayTrackUtils.GOOGLE_EARTH_PACKAGE, PlayTrackUtils.GOOGLE_EARTH_CLASS)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
.setDataAndType(uri, PlayTrackUtils.KML_MIME_TYPE)
|
||||
.putExtra(PlayTrackUtils.TOUR_FEATURE_ID, KmlTrackWriter.TOUR_FEATURE_ID);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Dialog onCreateDialog(int id) {
|
||||
switch (id) {
|
||||
case RESULT_DIALOG:
|
||||
return createResultDialog();
|
||||
case PROGRESS_DIALOG:
|
||||
if (controller != null) {
|
||||
return controller.createProgressDialog();
|
||||
}
|
||||
//$FALL-THROUGH$
|
||||
default:
|
||||
return super.onCreateDialog(id);
|
||||
}
|
||||
}
|
||||
|
||||
private Dialog createResultDialog() {
|
||||
boolean success = writer.wasSuccess();
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setMessage(writer.getErrorMessage());
|
||||
builder.setPositiveButton(R.string.generic_ok, new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int arg1) {
|
||||
dialog.dismiss();
|
||||
onPostResultDialog();
|
||||
}
|
||||
});
|
||||
builder.setOnCancelListener(new OnCancelListener() {
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
dialog.dismiss();
|
||||
onPostResultDialog();
|
||||
}
|
||||
});
|
||||
builder.setIcon(success ? android.R.drawable.ic_dialog_info :
|
||||
android.R.drawable.ic_dialog_alert);
|
||||
builder.setTitle(success ? R.string.generic_success_title : R.string.generic_error_title);
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
public static void handleExportTrackAction(Context ctx, long trackId, int actionCode) {
|
||||
if (trackId < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
TrackFileFormat exportFormat = null;
|
||||
switch (actionCode) {
|
||||
case Constants.SAVE_GPX_FILE:
|
||||
case Constants.SHARE_GPX_FILE:
|
||||
exportFormat = TrackFileFormat.GPX;
|
||||
break;
|
||||
case Constants.SAVE_KML_FILE:
|
||||
case Constants.SHARE_KML_FILE:
|
||||
exportFormat = TrackFileFormat.KML;
|
||||
break;
|
||||
case Constants.SAVE_CSV_FILE:
|
||||
case Constants.SHARE_CSV_FILE:
|
||||
exportFormat = TrackFileFormat.CSV;
|
||||
break;
|
||||
case Constants.SAVE_TCX_FILE:
|
||||
case Constants.SHARE_TCX_FILE:
|
||||
exportFormat = TrackFileFormat.TCX;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Warning unhandled action code: " + actionCode);
|
||||
}
|
||||
|
||||
boolean shareFile = false;
|
||||
switch (actionCode) {
|
||||
case Constants.SHARE_GPX_FILE:
|
||||
case Constants.SHARE_KML_FILE:
|
||||
case Constants.SHARE_CSV_FILE:
|
||||
case Constants.SHARE_TCX_FILE:
|
||||
shareFile = true;
|
||||
}
|
||||
|
||||
Uri uri = ContentUris.withAppendedId(TracksColumns.CONTENT_URI, trackId);
|
||||
|
||||
Intent intent = new Intent(ctx, SaveActivity.class);
|
||||
intent.setAction(ctx.getString(R.string.track_action_save));
|
||||
intent.setDataAndType(uri, TracksColumns.CONTENT_ITEMTYPE);
|
||||
intent.putExtra(EXTRA_FILE_FORMAT, exportFormat.ordinal());
|
||||
intent.putExtra(EXTRA_SHARE_FILE, shareFile);
|
||||
ctx.startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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.io.file;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
|
||||
/**
|
||||
* Async Task to save a track to the SD card.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class SaveAsyncTask extends AsyncTask<Void, Integer, Boolean> {
|
||||
|
||||
private SaveActivity saveActivity;
|
||||
private final TrackWriter trackWriter;
|
||||
|
||||
// true if the AsyncTask result is success
|
||||
private boolean success;
|
||||
|
||||
// true if the AsyncTask has completed
|
||||
private boolean completed;
|
||||
|
||||
/**
|
||||
* Creates an AsyncTask.
|
||||
*
|
||||
* @param saveActivity the {@link SaveActivity} currently associated with this
|
||||
* AsyncTask
|
||||
* @param trackWriter the track writer
|
||||
*/
|
||||
public SaveAsyncTask(SaveActivity saveActivity, TrackWriter trackWriter) {
|
||||
this.saveActivity = saveActivity;
|
||||
this.trackWriter = trackWriter;
|
||||
success = false;
|
||||
completed = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current {@link SaveActivity} associated with this AyncTask.
|
||||
*
|
||||
* @param saveActivity the current {@link SaveActivity}, can be null
|
||||
*/
|
||||
public void setActivity(SaveActivity saveActivity) {
|
||||
this.saveActivity = saveActivity;
|
||||
if (completed && saveActivity != null) {
|
||||
saveActivity.onAsyncTaskCompleted(
|
||||
success, trackWriter.getErrorMessage(), trackWriter.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
if (saveActivity != null) {
|
||||
saveActivity.showProgressDialog();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... params) {
|
||||
trackWriter.setOnWriteListener(new TrackWriter.OnWriteListener() {
|
||||
@Override
|
||||
public void onWrite(int number, int max) {
|
||||
// Update the progress dialog once every 500 points
|
||||
if (number % 500 == 0) {
|
||||
publishProgress(number, max);
|
||||
}
|
||||
}
|
||||
});
|
||||
trackWriter.writeTrack();
|
||||
return trackWriter.wasSuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onProgressUpdate(Integer... values) {
|
||||
if (saveActivity != null) {
|
||||
saveActivity.setProgressDialogValue(values[0], values[1]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean result) {
|
||||
success = result;
|
||||
completed = true;
|
||||
if (saveActivity != null) {
|
||||
saveActivity.onAsyncTaskCompleted(
|
||||
success, trackWriter.getErrorMessage(), trackWriter.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCancelled() {
|
||||
trackWriter.stopWriteTrack();
|
||||
}
|
||||
}
|
||||
@@ -27,10 +27,6 @@ import java.io.File;
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
public interface TrackWriter {
|
||||
/** This listener is used to signal completion of track write */
|
||||
public interface OnCompletionListener {
|
||||
public void onComplete();
|
||||
}
|
||||
|
||||
/** This listener is used to signal track writes. */
|
||||
public interface OnWriteListener {
|
||||
@@ -43,11 +39,6 @@ public interface TrackWriter {
|
||||
public void onWrite(int number, int max);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets listener to be invoked when the writer has finished.
|
||||
*/
|
||||
void setOnCompletionListener(OnCompletionListener onCompletionListener);
|
||||
|
||||
/**
|
||||
* Sets a listener to be invoked for each location writer.
|
||||
*/
|
||||
@@ -63,12 +54,6 @@ public interface TrackWriter {
|
||||
*/
|
||||
String getAbsolutePath();
|
||||
|
||||
/**
|
||||
* Writes the given track id to the SD card.
|
||||
* This is non-blocking.
|
||||
*/
|
||||
void writeTrackAsync();
|
||||
|
||||
/**
|
||||
* Writes the given track id to the SD card.
|
||||
* This is blocking.
|
||||
|
||||
@@ -22,6 +22,8 @@ import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
@@ -34,7 +36,7 @@ public class TrackWriterFactory {
|
||||
/**
|
||||
* Definition of all possible track formats.
|
||||
*/
|
||||
public enum TrackFileFormat {
|
||||
public enum TrackFileFormat implements Parcelable {
|
||||
GPX {
|
||||
@Override
|
||||
TrackFormatWriter newFormatWriter(Context context) {
|
||||
@@ -60,6 +62,28 @@ public class TrackWriterFactory {
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(final Parcel dest, final int flags) {
|
||||
dest.writeInt(ordinal());
|
||||
}
|
||||
|
||||
public static final Creator<TrackFileFormat> CREATOR = new Creator<TrackFileFormat>() {
|
||||
@Override
|
||||
public TrackFileFormat createFromParcel(final Parcel source) {
|
||||
return TrackFileFormat.values()[source.readInt()];
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrackFileFormat[] newArray(final int size) {
|
||||
return new TrackFileFormat[size];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates and returns a new format writer for each format.
|
||||
*/
|
||||
|
||||
@@ -57,7 +57,6 @@ class TrackWriterImpl implements TrackWriter {
|
||||
private int errorMessage = -1;
|
||||
private File directory = null;
|
||||
private File file = null;
|
||||
private OnCompletionListener onCompletionListener;
|
||||
private OnWriteListener onWriteListener;
|
||||
private Thread writeThread;
|
||||
|
||||
@@ -70,11 +69,6 @@ class TrackWriterImpl implements TrackWriter {
|
||||
this.fileUtils = new FileUtils();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnCompletionListener(OnCompletionListener onCompletionListener) {
|
||||
this.onCompletionListener = onCompletionListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnWriteListener(OnWriteListener onWriteListener) {
|
||||
this.onWriteListener = onWriteListener;
|
||||
@@ -90,8 +84,7 @@ class TrackWriterImpl implements TrackWriter {
|
||||
return file.getAbsolutePath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTrackAsync() {
|
||||
private void writeTrackAsync() {
|
||||
writeThread = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -131,7 +124,6 @@ class TrackWriterImpl implements TrackWriter {
|
||||
}
|
||||
}
|
||||
}
|
||||
finished();
|
||||
}
|
||||
|
||||
public void stopWriteTrack() {
|
||||
@@ -163,18 +155,6 @@ class TrackWriterImpl implements TrackWriter {
|
||||
* ===============
|
||||
*/
|
||||
|
||||
private void finished() {
|
||||
if (onCompletionListener != null) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onCompletionListener.onComplete();
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the given runnable in the UI thread.
|
||||
*/
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 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.io.file;
|
||||
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.DialogInterface;
|
||||
|
||||
/**
|
||||
* Given a {@link TrackWriter}, this class manages the process of writing the
|
||||
* data in the track represented by the writer. This includes the display of
|
||||
* a progress dialog, updating the progress bar in said dialog, and notifying
|
||||
* interested parties when the write completes.
|
||||
*
|
||||
* @author Matthew Simmons
|
||||
*/
|
||||
class WriteProgressController {
|
||||
/**
|
||||
* This listener is used to notify interested parties when the write has
|
||||
* completed.
|
||||
*/
|
||||
public interface OnCompletionListener {
|
||||
/**
|
||||
* When this method is invoked, the write has completed, and the progress
|
||||
* dialog has been dismissed. Whether the write succeeded can be
|
||||
* determined by examining the {@link TrackWriter}.
|
||||
*/
|
||||
public void onComplete();
|
||||
}
|
||||
|
||||
private final Activity activity;
|
||||
private final TrackWriter writer;
|
||||
private ProgressDialog dialog;
|
||||
|
||||
private OnCompletionListener onCompletionListener;
|
||||
private final int progressDialogId;
|
||||
|
||||
/**
|
||||
* @param activity the activity associated with this write
|
||||
* @param writer the writer which writes the track to disk. Note that this
|
||||
* class will use the writer's completion listener. If callers are
|
||||
* interested in notification upon completion of the write, they should
|
||||
* use {@link #setOnCompletionListener}.
|
||||
*/
|
||||
public WriteProgressController(Activity activity, TrackWriter writer, int progressDialogId) {
|
||||
this.activity = activity;
|
||||
this.writer = writer;
|
||||
this.progressDialogId = progressDialogId;
|
||||
|
||||
writer.setOnCompletionListener(writerCompleteListener);
|
||||
writer.setOnWriteListener(writerWriteListener);
|
||||
}
|
||||
|
||||
/** Set a listener to be invoked when the write completes. */
|
||||
public void setOnCompletionListener(OnCompletionListener onCompletionListener) {
|
||||
this.onCompletionListener = onCompletionListener;
|
||||
}
|
||||
|
||||
// For testing purpose
|
||||
OnCompletionListener getOnCompletionListener() {
|
||||
return onCompletionListener;
|
||||
}
|
||||
|
||||
public ProgressDialog createProgressDialog() {
|
||||
dialog = new ProgressDialog(activity);
|
||||
dialog.setIcon(android.R.drawable.ic_dialog_info);
|
||||
dialog.setTitle(activity.getString(R.string.generic_progress_title));
|
||||
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
|
||||
dialog.setMessage(activity.getString(R.string.sd_card_progress_write_file));
|
||||
dialog.setIndeterminate(true);
|
||||
dialog.setOnCancelListener(dialogCancelListener);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
/** Initiate an asynchronous write. */
|
||||
public void startWrite() {
|
||||
activity.showDialog(progressDialogId);
|
||||
writer.writeTrackAsync();
|
||||
}
|
||||
|
||||
/** VisibleForTesting */
|
||||
ProgressDialog getDialog() {
|
||||
return dialog;
|
||||
}
|
||||
|
||||
private final DialogInterface.OnCancelListener dialogCancelListener =
|
||||
new DialogInterface.OnCancelListener() {
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialogInterface) {
|
||||
writer.stopWriteTrack();
|
||||
}
|
||||
};
|
||||
|
||||
private final TrackWriter.OnCompletionListener writerCompleteListener =
|
||||
new TrackWriter.OnCompletionListener() {
|
||||
@Override
|
||||
public void onComplete() {
|
||||
activity.dismissDialog(progressDialogId);
|
||||
|
||||
if (onCompletionListener != null) {
|
||||
onCompletionListener.onComplete();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final TrackWriter.OnWriteListener writerWriteListener =
|
||||
new TrackWriter.OnWriteListener() {
|
||||
@Override
|
||||
public void onWrite(int number, int max) {
|
||||
if (number % 500 == 0) {
|
||||
dialog.setIndeterminate(false);
|
||||
dialog.setMax(max);
|
||||
dialog.setProgress(Math.min(number, max));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user