Adding compression to the backup: assuming that backups/restore are infrequent, the added CPU/battery usage is not an issue

This commit is contained in:
Rodrigo Damazio
2010-08-24 22:39:29 -03:00
parent aa95e3abcd
commit 59846280a8
2 changed files with 29 additions and 17 deletions
@@ -16,6 +16,7 @@
package com.google.android.apps.mytracks.io.backup; package com.google.android.apps.mytracks.io.backup;
import com.google.android.apps.mytracks.MyTracks; import com.google.android.apps.mytracks.MyTracks;
import com.google.android.apps.mytracks.MyTracksConstants;
import com.google.android.apps.mytracks.util.FileUtils; import com.google.android.apps.mytracks.util.FileUtils;
import com.google.android.maps.mytracks.R; import com.google.android.maps.mytracks.R;
@@ -27,6 +28,7 @@ import android.app.ProgressDialog;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener; import android.content.DialogInterface.OnClickListener;
import android.content.Intent; import android.content.Intent;
import android.util.Log;
import android.widget.Toast; import android.widget.Toast;
import java.io.IOException; import java.io.IOException;
@@ -95,6 +97,7 @@ public class BackupActivityHelper {
backup.writeToDefaultFile(); backup.writeToDefaultFile();
showToast(R.string.io_write_finished); showToast(R.string.io_write_finished);
} catch (IOException e) { } catch (IOException e) {
Log.e(MyTracksConstants.TAG, "Failed to write backup", e);
showToast(R.string.io_write_failed); showToast(R.string.io_write_failed);
} finally { } finally {
dismissDialog(progressDialog); dismissDialog(progressDialog);
@@ -196,6 +199,7 @@ public class BackupActivityHelper {
backup.restoreFromDate(date); backup.restoreFromDate(date);
showToast(R.string.io_read_finished); showToast(R.string.io_read_finished);
} catch (IOException e) { } catch (IOException e) {
Log.e(MyTracksConstants.TAG, "Failed to restore backup", e);
showToast(R.string.io_read_failed); showToast(R.string.io_read_failed);
} finally { } finally {
dismissDialog(progressDialog); dismissDialog(progressDialog);
@@ -31,15 +31,18 @@ import android.util.Log;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.TimeZone; import java.util.TimeZone;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
/** /**
* Handler for writing or reading single-file backups. * Handler for writing or reading single-file backups.
@@ -49,13 +52,16 @@ import java.util.TimeZone;
class ExternalFileBackup { class ExternalFileBackup {
// Filename format - in UTC // Filename format - in UTC
private static final SimpleDateFormat BACKUP_FILENAME_FORMAT = private static final SimpleDateFormat BACKUP_FILENAME_FORMAT =
new SimpleDateFormat("'backup-'yyyy-MM-dd_HH-mm-ss'.mytracks'"); new SimpleDateFormat("'backup-'yyyy-MM-dd_HH-mm-ss'.zip'");
static { static {
BACKUP_FILENAME_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC")); BACKUP_FILENAME_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
} }
private static final String BACKUPS_SUBDIR = "backups"; private static final String BACKUPS_SUBDIR = "backups";
private static final int BACKUP_FILE_VERSION = 1; private static final int BACKUP_FORMAT_VERSION = 1;
private static final String ZIP_ENTRY_NAME =
"backup.mytracks.v" + BACKUP_FORMAT_VERSION;
private static final int COMPRESSION_LEVEL = 8;
private final Context context; private final Context context;
private final FileUtils fileUtils; private final FileUtils fileUtils;
@@ -161,12 +167,12 @@ class ExternalFileBackup {
// Open the target for writing // Open the target for writing
FileOutputStream outputStream = new FileOutputStream(outputFile); FileOutputStream outputStream = new FileOutputStream(outputFile);
DataOutputStream outWriter = new DataOutputStream(outputStream); ZipOutputStream compressedStream = new ZipOutputStream(outputStream);
compressedStream.setLevel(COMPRESSION_LEVEL);
compressedStream.putNextEntry(new ZipEntry(ZIP_ENTRY_NAME));
DataOutputStream outWriter = new DataOutputStream(compressedStream);
try { try {
// Output a version header
outWriter.writeInt(BACKUP_FILE_VERSION);
// Dump the entire contents of each table // Dump the entire contents of each table
ContentResolver contentResolver = context.getContentResolver(); ContentResolver contentResolver = context.getContentResolver();
Cursor tracksCursor = contentResolver.query( Cursor tracksCursor = contentResolver.query(
@@ -204,8 +210,8 @@ class ExternalFileBackup {
throw e; throw e;
} finally { } finally {
outputStream.flush(); compressedStream.closeEntry();
outputStream.close(); compressedStream.close();
} }
} }
@@ -225,15 +231,16 @@ class ExternalFileBackup {
DatabaseImporter pointImporter = DatabaseImporter pointImporter =
new DatabaseImporter(TrackPointsColumns.CONTENT_URI, resolver, false); new DatabaseImporter(TrackPointsColumns.CONTENT_URI, resolver, false);
FileInputStream inputStream = new FileInputStream(inputFile); ZipFile zipFile = new ZipFile(inputFile, ZipFile.OPEN_READ);
DataInputStream reader = new DataInputStream(inputStream); ZipEntry zipEntry = zipFile.getEntry(ZIP_ENTRY_NAME);
if (zipEntry == null) {
throw new IOException("Invalid backup ZIP file");
}
InputStream compressedStream = zipFile.getInputStream(zipEntry);
DataInputStream reader = new DataInputStream(compressedStream);
try { try {
int backupVersion = reader.readInt();
if (backupVersion != BACKUP_FILE_VERSION) {
throw new IOException("Unknown backup file version " + backupVersion);
}
// Delete all previous contents of the tables and preferences. // Delete all previous contents of the tables and preferences.
resolver.delete(TracksColumns.CONTENT_URI, null, null); resolver.delete(TracksColumns.CONTENT_URI, null, null);
resolver.delete(TrackPointsColumns.CONTENT_URI, null, null); resolver.delete(TrackPointsColumns.CONTENT_URI, null, null);
@@ -249,7 +256,8 @@ class ExternalFileBackup {
context.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0); context.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
preferencesHelper.importPreferences(reader, preferences); preferencesHelper.importPreferences(reader, preferences);
} finally { } finally {
inputStream.close(); compressedStream.close();
zipFile.close();
} }
} }
} }