forked from upstream-mirrors/OpenTracks
Support screen rotation for back and restore
from the SD card.
This commit is contained in:
@@ -274,7 +274,10 @@ limitations under the License.
|
|||||||
<activity android:name="com.google.android.apps.mytracks.io.sendtogoogle.UploadResultActivity"/>
|
<activity android:name="com.google.android.apps.mytracks.io.sendtogoogle.UploadResultActivity"/>
|
||||||
<activity android:name="com.google.android.apps.mytracks.io.sendtogoogle.UploadServiceChooserActivity"/>
|
<activity android:name="com.google.android.apps.mytracks.io.sendtogoogle.UploadServiceChooserActivity"/>
|
||||||
<activity android:name="com.google.android.apps.mytracks.ExportAllActivity"/>
|
<activity android:name="com.google.android.apps.mytracks.ExportAllActivity"/>
|
||||||
|
<activity android:name="com.google.android.apps.mytracks.io.backup.BackupActivity"/>
|
||||||
|
<activity android:name="com.google.android.apps.mytracks.io.backup.RestoreActivity"/>
|
||||||
|
<activity android:name="com.google.android.apps.mytracks.io.backup.RestoreChooserActivity"/>
|
||||||
|
|
||||||
<service android:name="com.google.android.apps.mytracks.services.TrackRecordingService"
|
<service android:name="com.google.android.apps.mytracks.services.TrackRecordingService"
|
||||||
android:label="@string/my_tracks_recording_service"
|
android:label="@string/my_tracks_recording_service"
|
||||||
android:icon="@drawable/arrow_320"
|
android:icon="@drawable/arrow_320"
|
||||||
|
|||||||
@@ -1537,8 +1537,7 @@ limitations under the License.
|
|||||||
and it will overwrite all the current tracks and settings.
|
and it will overwrite all the current tracks and settings.
|
||||||
|
|
||||||
Screenshot: settings_backup_restore_confirm_message.png">
|
Screenshot: settings_backup_restore_confirm_message.png">
|
||||||
Restoring a backup from the SD card will overwrite all your current tracks and settings. Are you
|
Restoring a backup from the SD card will overwrite all your current tracks and settings.
|
||||||
sure?
|
|
||||||
</string>
|
</string>
|
||||||
<string name="settings_backup_restore_no_backup"
|
<string name="settings_backup_restore_no_backup"
|
||||||
translation_description="In the 'Backup' settings, after pressing the 'Restore now' option, the
|
translation_description="In the 'Backup' settings, after pressing the 'Restore now' option, the
|
||||||
|
|||||||
@@ -17,8 +17,9 @@ package com.google.android.apps.mytracks;
|
|||||||
|
|
||||||
import static com.google.android.apps.mytracks.Constants.TAG;
|
import static com.google.android.apps.mytracks.Constants.TAG;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.io.backup.BackupActivityHelper;
|
import com.google.android.apps.mytracks.io.backup.BackupActivity;
|
||||||
import com.google.android.apps.mytracks.io.backup.BackupPreferencesListener;
|
import com.google.android.apps.mytracks.io.backup.BackupPreferencesListener;
|
||||||
|
import com.google.android.apps.mytracks.io.backup.RestoreChooserActivity;
|
||||||
import com.google.android.apps.mytracks.services.sensors.ant.AntUtils;
|
import com.google.android.apps.mytracks.services.sensors.ant.AntUtils;
|
||||||
import com.google.android.apps.mytracks.util.ApiAdapterFactory;
|
import com.google.android.apps.mytracks.util.ApiAdapterFactory;
|
||||||
import com.google.android.apps.mytracks.util.BluetoothDeviceUtils;
|
import com.google.android.apps.mytracks.util.BluetoothDeviceUtils;
|
||||||
@@ -62,8 +63,9 @@ import java.util.Set;
|
|||||||
*/
|
*/
|
||||||
public class SettingsActivity extends PreferenceActivity {
|
public class SettingsActivity extends PreferenceActivity {
|
||||||
|
|
||||||
private static final int DIALOG_CONFIRM_RESET = 0;
|
private static final int DIALOG_CONFIRM_RESET_ID = 0;
|
||||||
private static final int DIALOG_CONFIRM_ACCESS = 1;
|
private static final int DIALOG_CONFIRM_ACCESS_ID = 1;
|
||||||
|
private static final int DIALOG_CONFIRM_RESTORE_ID = 2;
|
||||||
|
|
||||||
// Value when the task frequency is off.
|
// Value when the task frequency is off.
|
||||||
private static final String TASK_FREQUENCY_OFF = "0";
|
private static final String TASK_FREQUENCY_OFF = "0";
|
||||||
@@ -150,7 +152,7 @@ public class SettingsActivity extends PreferenceActivity {
|
|||||||
resetPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
resetPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onPreferenceClick(Preference arg0) {
|
public boolean onPreferenceClick(Preference arg0) {
|
||||||
showDialog(DIALOG_CONFIRM_RESET);
|
showDialog(DIALOG_CONFIRM_RESET_ID);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -162,7 +164,7 @@ public class SettingsActivity extends PreferenceActivity {
|
|||||||
@Override
|
@Override
|
||||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||||
if ((Boolean) newValue) {
|
if ((Boolean) newValue) {
|
||||||
showDialog(DIALOG_CONFIRM_ACCESS);
|
showDialog(DIALOG_CONFIRM_ACCESS_ID);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
@@ -174,7 +176,7 @@ public class SettingsActivity extends PreferenceActivity {
|
|||||||
@Override
|
@Override
|
||||||
protected Dialog onCreateDialog(int id) {
|
protected Dialog onCreateDialog(int id) {
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case DIALOG_CONFIRM_RESET:
|
case DIALOG_CONFIRM_RESET_ID:
|
||||||
return DialogUtils.createConfirmationDialog(
|
return DialogUtils.createConfirmationDialog(
|
||||||
this, R.string.settings_reset_confirm_message, new OnClickListener() {
|
this, R.string.settings_reset_confirm_message, new OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
@@ -182,7 +184,7 @@ public class SettingsActivity extends PreferenceActivity {
|
|||||||
onResetPreferencesConfirmed();
|
onResetPreferencesConfirmed();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
case DIALOG_CONFIRM_ACCESS:
|
case DIALOG_CONFIRM_ACCESS_ID:
|
||||||
return DialogUtils.createConfirmationDialog(
|
return DialogUtils.createConfirmationDialog(
|
||||||
this, R.string.settings_sharing_allow_access_confirm_message, new OnClickListener() {
|
this, R.string.settings_sharing_allow_access_confirm_message, new OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
@@ -192,6 +194,14 @@ public class SettingsActivity extends PreferenceActivity {
|
|||||||
pref.setChecked(true);
|
pref.setChecked(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
case DIALOG_CONFIRM_RESTORE_ID:
|
||||||
|
return DialogUtils.createConfirmationDialog(
|
||||||
|
this, R.string.settings_backup_restore_confirm_message, new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
startActivity(new Intent(SettingsActivity.this, RestoreChooserActivity.class));
|
||||||
|
}
|
||||||
|
});
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -354,9 +364,7 @@ public class SettingsActivity extends PreferenceActivity {
|
|||||||
new OnPreferenceClickListener() {
|
new OnPreferenceClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
public boolean onPreferenceClick(Preference preference) {
|
||||||
BackupActivityHelper backupHelper =
|
startActivity(new Intent(SettingsActivity.this, BackupActivity.class));
|
||||||
new BackupActivityHelper(SettingsActivity.this);
|
|
||||||
backupHelper.writeBackup();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -364,9 +372,7 @@ public class SettingsActivity extends PreferenceActivity {
|
|||||||
new OnPreferenceClickListener() {
|
new OnPreferenceClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
public boolean onPreferenceClick(Preference preference) {
|
||||||
BackupActivityHelper backupHelper =
|
showDialog(DIALOG_CONFIRM_RESTORE_ID);
|
||||||
new BackupActivityHelper(SettingsActivity.this);
|
|
||||||
backupHelper.restoreBackup();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user