summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--vdrmanager/AndroidManifest.xml7
-rw-r--r--vdrmanager/res/values/backup.xml61
-rw-r--r--vdrmanager/res/xml/backup_settings.xml31
-rw-r--r--vdrmanager/res/xml/preferences.xml7
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/backup/AbstractSettingsActivity.java70
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/backup/Api10Adapter.java30
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/backup/Api11Adapter.java112
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/backup/Api14Adapter.java73
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/backup/Api7Adapter.java107
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/backup/Api8Adapter.java32
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/backup/Api8BackupPreferencesListener.java43
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/backup/Api9Adapter.java58
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/backup/ApiAdapter.java152
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/backup/ApiAdapterFactory.java56
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/backup/BackupActivity.java89
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/backup/BackupAsyncTask.java110
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/backup/BackupPreferencesListener.java27
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/backup/BackupSettingsActivity.java121
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/backup/Constants.java135
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/backup/ContentTypeIds.java33
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/backup/ContextualActionModeCallback.java34
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/backup/DialogUtils.java101
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/backup/ExternalFileBackup.java276
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/backup/FileUtils.java199
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/backup/IOUtils.java217
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/backup/IntentUtils.java47
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/backup/LineIterator.java5
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/backup/PreferenceBackupHelper.java172
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/backup/RestoreActivity.java114
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/backup/RestoreAsyncTask.java136
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/backup/RestoreChooserActivity.java127
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/data/db/OrmDatabaseHelper.java6
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/gui/BaseActivity.java6
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/gui/PreferencesActivity.java13
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/gui/Utils.java14
35 files changed, 2819 insertions, 2 deletions
diff --git a/vdrmanager/AndroidManifest.xml b/vdrmanager/AndroidManifest.xml
index afece76..13377ad 100644
--- a/vdrmanager/AndroidManifest.xml
+++ b/vdrmanager/AndroidManifest.xml
@@ -7,7 +7,7 @@
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
-
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="14" />
@@ -94,6 +94,11 @@
<activity android:name=".gui.VdrListActivity" android:configChanges="orientation|locale"/>
<activity android:name=".gui.VdrPreferencesActivity" android:configChanges="orientation|locale"/>
+
+ <activity android:name=".backup.BackupActivity" android:configChanges="orientation|locale"/>
+ <activity android:name=".backup.RestoreActivity" android:configChanges="orientation|locale" />
+ <activity android:name=".backup.RestoreChooserActivity" android:configChanges="orientation|locale" />
+ <activity android:name=".backup.BackupSettingsActivity" android:configChanges="orientation|locale"/>
</application>
diff --git a/vdrmanager/res/values/backup.xml b/vdrmanager/res/values/backup.xml
new file mode 100644
index 0000000..4759e4d
--- /dev/null
+++ b/vdrmanager/res/values/backup.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="generic_progress_title" translation_description="The title on a progress dialog asking the user to wait."> Please wait...</string>
+ <string name="generic_confirm_title" translation_description="The title on a confirmation dialog asking the user if he is sure?"> Are you sure?</string>
+
+ <!-- SD Card -->
+ <string name="sd_card_canceled" translation_description="When importing/saving to the SD card, the message indicating that the
+ operation was canceled."> The operation was canceled.</string>
+ <string name="sd_card_error_no_storage" translation_description="When importing/saving to the SD card, the error message indicating that
+ no SD card is found."> No SD card is found.</string>
+ <string name="sd_card_import_error" translation_description="When importing from the SD card, the error message indicating not able
+ to import."> Unable to import from SD card.</string>
+ <string name="sd_card_import_error_no_file" translation_description="When importing from the SD card, the error message indicating that no
+ file is found on a SD card directory.
+
+ %1$s: the SD card directory. E.g., &apos;/mnt/sdcard/mybillingbuddy/&apos;."> No file found in %1$s.</string>
+ <string name="sd_card_import_progress_message" translation_description="When importing from the SD card, the progress message."> Importing from SD card...</string>
+ <string name="sd_card_import_success" translation_description="When importing from the SD card, the success message."> Finished importing from SD card.</string>
+ <string name="sd_card_save_error" translation_description="When saving to the SD card, the error message indicating not able to
+ save."> Unable to save to SD card.</string>
+ <string name="sd_card_save_error_create_dir" translation_description="When saving to the SD card, the error message indicating not able to
+ create a directory on the SD card."> Unable to create a directory on SD card.</string>
+ <string name="sd_card_save_progress_message" translation_description="When saving to the SD card, the progress message."> Saving to SD card...</string>
+ <string name="sd_card_save_success" translation_description="When saving to the SD card, the success message"> Finished saving to SD card.</string>
+ <!-- Settings Backup -->
+
+ <string name="settings_backup_summary">Backup/Restore you data and settings</string>
+ <string name="settings_backup_now" translation_description="In the &apos;Backup&apos; settings, under the &apos;SD card&apos; section, the
+ option to backup to the SD card now.
+
+ Character limit: ~26 (1 line)"> Backup now</string>
+ <string name="settings_backup_now_summary">Creates a snapshot of the current data and the settings</string>
+ <string name="settings_backup_now_progress_message" translation_description="In the &apos;Backup&apos; settings, after pressing the &apos;Backup now&apos; option, the
+ progress message telling the user that it is writing all data and settings to the SD card."> Writing all data and settings...</string>
+ <string name="settings_backup_restore" translation_description="In the &apos;Backup&apos; settings, under the &apos;SD card&apos; section, the
+ option to restore everything from the SD card.
+
+ Character limit: ~26 (1 line)"> Restore now</string>
+ <string name="settings_backup_restore_summary">Restore a snapshot of the settings and the data</string>
+ <!-- Settings Backup -->
+ <string name="settings_backup" translation_description="In the &apos;Settings&apos; page, the option to change the data backup related
+ settings.
+
+ Character limit: ~26 (1 line)"> Backup</string>
+ <string name="settings_backup_restore_confirm_message" translation_description="In the &apos;Backup&apos; settings, after pressing the &apos;Restore now&apos; option, the
+ message in the alert dialog asking the user to confirm that he wants to restore from a backup
+ and it will overwrite all the current data and settings."> Restoring a backup from the SD card will overwrite all your current data and settings.</string>
+ <string name="settings_backup_restore_no_backup" translation_description="In the &apos;Backup&apos; settings, after pressing the &apos;Restore now&apos; option, the
+ message in the alert dialog informing the user that there is no backup to restore from."> No backup found.</string>
+ <string name="settings_backup_restore_progress_message" translation_description="In the &apos;Backup&apos; settings, after pressing the &apos;Restore now&apos; option, the
+ progress message informing that My Billinbg Buddy is reading all data and settings from the backup
+ on the SD card."> Reading all data and settings...</string>
+ <string name="settings_backup_restore_select_title" translation_description="In the &apos;Backup&apos; settings, after pressing the &apos;Restore now&apos; option, the
+ title in the picker dialog asking the user to select a backup."> Select a backup to restore</string>
+ <string name="settings_backup_key">settingsBackup</string>
+ <string name="settings_backup_now_key">settingsBackupNow</string>
+ <string name="settings_backup_restore_key">settingsBackupRestore</string>
+ <string name="choose">Choose a backup file</string>
+
+</resources> \ No newline at end of file
diff --git a/vdrmanager/res/xml/backup_settings.xml b/vdrmanager/res/xml/backup_settings.xml
new file mode 100644
index 0000000..dfe91c6
--- /dev/null
+++ b/vdrmanager/res/xml/backup_settings.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+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.
+-->
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ android:title="@string/settings_backup" android:summary="@string/settings_backup_summary">
+ <Preference
+ android:key="@string/settings_backup_now_key"
+ android:persistent="false"
+ android:title="@string/settings_backup_now"
+ android:summary="@string/settings_backup_now_summary"
+ />
+ <Preference
+ android:key="@string/settings_backup_restore_key"
+ android:persistent="false"
+ android:title="@string/settings_backup_restore"
+ android:summary="@string/settings_backup_restore_summary"
+ />
+</PreferenceScreen> \ No newline at end of file
diff --git a/vdrmanager/res/xml/preferences.xml b/vdrmanager/res/xml/preferences.xml
index 8a819dd..dffe0ab 100644
--- a/vdrmanager/res/xml/preferences.xml
+++ b/vdrmanager/res/xml/preferences.xml
@@ -72,4 +72,11 @@
android:title="@string/gui_custom_locale_title" />
</PreferenceCategory>
+
+ <Preference
+ android:key="@string/settings_backup_key"
+ android:persistent="false"
+ android:summary="@string/settings_backup_summary"
+ android:title="@string/settings_backup" />
+
</PreferenceScreen> \ No newline at end of file
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/backup/AbstractSettingsActivity.java b/vdrmanager/src/de/bjusystems/vdrmanager/backup/AbstractSettingsActivity.java
new file mode 100644
index 0000000..ef6dd5e
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/backup/AbstractSettingsActivity.java
@@ -0,0 +1,70 @@
+/*
+ * 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 de.bjusystems.vdrmanager.backup;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceManager;
+import android.speech.tts.TextToSpeech;
+import android.view.MenuItem;
+
+/**
+ * An abstract activity for all the settings activities.
+ *
+ * @author Jimmy Shih
+ */
+public class AbstractSettingsActivity extends PreferenceActivity {
+
+ private BackupPreferencesListener backupPreferencesListener;
+
+ @SuppressWarnings("deprecation")
+ @Override
+ protected void onCreate(Bundle bundle) {
+ super.onCreate(bundle);
+ setVolumeControlStream(TextToSpeech.Engine.DEFAULT_STREAM);
+ ApiAdapterFactory.getApiAdapter().configureActionBarHomeAsUp(this);
+
+ PreferenceManager preferenceManager = getPreferenceManager();
+ preferenceManager.setSharedPreferencesName(Constants.SETTINGS_NAME);
+ preferenceManager.setSharedPreferencesMode(Context.MODE_PRIVATE);
+
+ // Set up automatic preferences backup
+ backupPreferencesListener = ApiAdapterFactory.getApiAdapter()
+ .getBackupPreferencesListener(this);
+ preferenceManager.getSharedPreferences()
+ .registerOnSharedPreferenceChangeListener(backupPreferencesListener);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() != android.R.id.home) {
+ return super.onOptionsItemSelected(item);
+ }
+ finish();
+ return true;
+ }
+
+ @SuppressWarnings("deprecation")
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ PreferenceManager preferenceManager = getPreferenceManager();
+ preferenceManager.getSharedPreferences()
+ .unregisterOnSharedPreferenceChangeListener(backupPreferencesListener);
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/backup/Api10Adapter.java b/vdrmanager/src/de/bjusystems/vdrmanager/backup/Api10Adapter.java
new file mode 100644
index 0000000..0527f89
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/backup/Api10Adapter.java
@@ -0,0 +1,30 @@
+/*
+ * 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 de.bjusystems.vdrmanager.backup;
+
+import android.annotation.TargetApi;
+
+
+/**
+ * API level 10 specific implementation of the {@link ApiAdapter}.
+ *
+ * @author Jimmy Shih
+ */
+@TargetApi(10)
+public class Api10Adapter extends Api9Adapter {
+
+
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/backup/Api11Adapter.java b/vdrmanager/src/de/bjusystems/vdrmanager/backup/Api11Adapter.java
new file mode 100644
index 0000000..ec26635
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/backup/Api11Adapter.java
@@ -0,0 +1,112 @@
+/*
+ * 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 de.bjusystems.vdrmanager.backup;
+
+
+import java.util.List;
+
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.app.SearchManager;
+import android.content.Context;
+import android.view.MenuItem;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.SearchView;
+
+/**
+ * API level 11 specific implementation of the {@link ApiAdapter}.
+ *
+ * @author Jimmy Shih
+ */
+@TargetApi(11)
+public class Api11Adapter extends Api10Adapter {
+
+ @Override
+ public void hideTitle(Activity activity) {
+ // Do nothing
+ }
+
+ @Override
+ public void configureActionBarHomeAsUp(Activity activity) {
+ activity.getActionBar().setDisplayHomeAsUpEnabled(true);
+ }
+
+ @Override
+ public void configureListViewContextualMenu(final Activity activity, ListView listView,
+ final ContextualActionModeCallback contextualActionModeCallback) {
+ /*
+
+ listView.setOnItemLongClickListener(new OnItemLongClickListener() {
+ ActionMode actionMode;
+ @Override
+ public boolean onItemLongClick(
+ AdapterView<?> parent, View view, final int position, final long id) {
+ if (actionMode != null) {
+ return false;
+ }
+ actionMode = activity.startActionMode(new ActionMode.Callback() {
+ @Override
+ public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+ mode.getMenuInflater().inflate(R.menu.list_context_menu, menu);
+ return true;
+ }
+ @Override
+ public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+ // Return false to indicate no change.
+ return false;
+ }
+ @Override
+ public void onDestroyActionMode(ActionMode mode) {
+ actionMode = null;
+ }
+ @Override
+ public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+ mode.finish();
+ return contextualActionModeCallback.onClick(item.getItemId(), position, id);
+ }
+ });
+ TextView textView = (TextView) view.findViewById(R.id.list_item_name);
+ if (textView != null) {
+ actionMode.setTitle(textView.getText());
+ }
+ view.setSelected(true);
+ return true;
+ }
+ });
+ */
+ };
+
+ @Override
+ public void configureSearchWidget(Activity activity, final MenuItem menuItem) {
+ SearchManager searchManager = (SearchManager) activity.getSystemService(Context.SEARCH_SERVICE);
+ SearchView searchView = (SearchView) menuItem.getActionView();
+ searchView.setSearchableInfo(searchManager.getSearchableInfo(activity.getComponentName()));
+ searchView.setQueryRefinementEnabled(true);
+ }
+
+ @Override
+ public boolean handleSearchMenuSelection(Activity activity) {
+ // Returns false to allow the platform to expand the search widget.
+ return false;
+ }
+
+ @Override
+ public <T> void addAllToArrayAdapter(ArrayAdapter<T> arrayAdapter, List<T> items) {
+ arrayAdapter.addAll(items);
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/backup/Api14Adapter.java b/vdrmanager/src/de/bjusystems/vdrmanager/backup/Api14Adapter.java
new file mode 100644
index 0000000..0425191
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/backup/Api14Adapter.java
@@ -0,0 +1,73 @@
+/*
+ * 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 de.bjusystems.vdrmanager.backup;
+
+import android.annotation.TargetApi;
+import android.app.ActionBar;
+import android.app.Activity;
+import android.view.MenuItem;
+import android.widget.SearchView;
+
+/**
+ * API level 14 specific implementation of the {@link ApiAdapter}.
+ *
+ * @author Jimmy Shih
+ */
+@TargetApi(14)
+public class Api14Adapter extends Api11Adapter {
+
+ @Override
+ public void configureActionBarHomeAsUp(Activity activity) {
+ ActionBar actionBar = activity.getActionBar();
+ actionBar.setHomeButtonEnabled(true);
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ }
+
+ @Override
+ public void configureSearchWidget(Activity activity, final MenuItem menuItem) {
+ super.configureSearchWidget(activity, menuItem);
+ SearchView searchView = (SearchView) menuItem.getActionView();
+ searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
+ @Override
+ public boolean onQueryTextSubmit(String query) {
+ menuItem.collapseActionView();
+ return false;
+ }
+ @Override
+ public boolean onQueryTextChange(String newText) {
+ return false;
+ }
+ });
+ searchView.setOnSuggestionListener(new SearchView.OnSuggestionListener() {
+ @Override
+ public boolean onSuggestionSelect(int position) {
+ return false;
+ }
+ @Override
+ public boolean onSuggestionClick(int position) {
+ menuItem.collapseActionView();
+ return false;
+ }
+ });
+ }
+
+ @Override
+ public boolean handleSearchKey(MenuItem menuItem) {
+ menuItem.expandActionView();
+ return true;
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/backup/Api7Adapter.java b/vdrmanager/src/de/bjusystems/vdrmanager/backup/Api7Adapter.java
new file mode 100644
index 0000000..b89168a
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/backup/Api7Adapter.java
@@ -0,0 +1,107 @@
+/*
+ * 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 de.bjusystems.vdrmanager.backup;
+
+
+import java.util.List;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.view.MenuItem;
+import android.view.Window;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+/**
+ * API level 7 specific implementation of the {@link ApiAdapter}.
+ *
+ * @author Bartlomiej Niechwiej
+ */
+public class Api7Adapter implements ApiAdapter {
+
+
+ @Override
+ public BackupPreferencesListener getBackupPreferencesListener(Context context) {
+ return new BackupPreferencesListener() {
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+ // Do nothing
+ }
+ };
+ }
+
+ @Override
+ public void applyPreferenceChanges(Editor editor) {
+ editor.commit();
+ }
+
+ @Override
+ public void enableStrictMode() {
+ // Not supported
+ }
+
+ @Override
+ public byte[] copyByteArray(byte[] input, int start, int end) {
+ int length = end - start;
+ byte[] output = new byte[length];
+ System.arraycopy(input, start, output, 0, length);
+ return output;
+ }
+
+
+
+ @Override
+ public void hideTitle(Activity activity) {
+ activity.requestWindowFeature(Window.FEATURE_NO_TITLE);
+ }
+
+ @Override
+ public void configureActionBarHomeAsUp(Activity activity) {
+ // Do nothing
+ }
+
+ @Override
+ public void configureListViewContextualMenu(Activity activity, ListView listView,
+ ContextualActionModeCallback contextualActionModeCallback) {
+ activity.registerForContextMenu(listView);
+ }
+
+ @Override
+ public void configureSearchWidget(Activity activity, MenuItem menuItem) {
+ // Do nothing
+ }
+
+ @Override
+ public boolean handleSearchMenuSelection(Activity activity) {
+ activity.onSearchRequested();
+ return true;
+ }
+
+ @Override
+ public <T> void addAllToArrayAdapter(ArrayAdapter<T> arrayAdapter, List<T> items) {
+ for (T item : items) {
+ arrayAdapter.add(item);
+ }
+ }
+
+ @Override
+ public boolean handleSearchKey(MenuItem menuItem) {
+ // Return false and allow the framework to handle the search key.
+ return false;
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/backup/Api8Adapter.java b/vdrmanager/src/de/bjusystems/vdrmanager/backup/Api8Adapter.java
new file mode 100644
index 0000000..1fc61d3
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/backup/Api8Adapter.java
@@ -0,0 +1,32 @@
+/*
+ * 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 de.bjusystems.vdrmanager.backup;
+
+import android.content.Context;
+
+/**
+ * API level 8 specific implementation of the {@link ApiAdapter}.
+ *
+ * @author Jimmy Shih
+ */
+public class Api8Adapter extends Api7Adapter {
+
+
+ @Override
+ public BackupPreferencesListener getBackupPreferencesListener(Context context) {
+ return new Api8BackupPreferencesListener(context);
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/backup/Api8BackupPreferencesListener.java b/vdrmanager/src/de/bjusystems/vdrmanager/backup/Api8BackupPreferencesListener.java
new file mode 100644
index 0000000..90e3976
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/backup/Api8BackupPreferencesListener.java
@@ -0,0 +1,43 @@
+/*
+ * 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 de.bjusystems.vdrmanager.backup;
+
+import android.annotation.TargetApi;
+import android.app.backup.BackupManager;
+import android.content.Context;
+import android.content.SharedPreferences;
+
+/**
+ * Implementation of {@link BackupPreferencesListener} that calls the
+ * {@link BackupManager}. <br>
+ * For API Level 8 or higher.
+ *
+ * @author Jimmy Shih
+ */
+@TargetApi(8)
+public class Api8BackupPreferencesListener implements BackupPreferencesListener {
+
+ private final BackupManager backupManager;
+
+ public Api8BackupPreferencesListener(Context context) {
+ this.backupManager = new BackupManager(context);
+ }
+
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+ backupManager.dataChanged();
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/backup/Api9Adapter.java b/vdrmanager/src/de/bjusystems/vdrmanager/backup/Api9Adapter.java
new file mode 100644
index 0000000..151f317
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/backup/Api9Adapter.java
@@ -0,0 +1,58 @@
+/*
+ * 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 de.bjusystems.vdrmanager.backup;
+
+import java.util.Arrays;
+
+import android.annotation.TargetApi;
+import android.content.SharedPreferences.Editor;
+import android.os.StrictMode;
+import android.util.Log;
+
+/**
+ * API level 9 specific implementation of the {@link ApiAdapter}.
+ *
+ * @author Rodrigo Damazio
+ */
+@TargetApi(9)
+public class Api9Adapter extends Api8Adapter {
+
+ @Override
+ public void applyPreferenceChanges(Editor editor) {
+ // Apply asynchronously
+ editor.apply();
+ }
+
+ @Override
+ public void enableStrictMode() {
+ Log.d(Constants.TAG, "Enabling strict mode");
+ StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
+ .detectDiskWrites()
+ .detectNetwork()
+ .penaltyLog()
+ .build());
+ StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
+ .detectAll()
+ .penaltyLog()
+ .build());
+ }
+
+ @Override
+ public byte[] copyByteArray(byte[] input, int start, int end) {
+ return Arrays.copyOfRange(input, start, end);
+ }
+
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/backup/ApiAdapter.java b/vdrmanager/src/de/bjusystems/vdrmanager/backup/ApiAdapter.java
new file mode 100644
index 0000000..aa13297
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/backup/ApiAdapter.java
@@ -0,0 +1,152 @@
+/*
+ * 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 de.bjusystems.vdrmanager.backup;
+
+import java.util.List;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.view.MenuItem;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+/**
+ * A set of methods that may be implemented differently depending on the Android
+ * API level.
+ *
+ * @author Bartlomiej Niechwiej
+ */
+public interface ApiAdapter {
+
+
+
+ /**
+ * Gets a {@link BackupPreferencesListener}.
+ * <p>
+ * Due to changes in API level 8.
+ *
+ * @param context the context
+ */
+ public BackupPreferencesListener getBackupPreferencesListener(Context context);
+
+ /**
+ * Applies all the changes done to a given preferences editor. Changes may or
+ * may not be applied immediately.
+ * <p>
+ * Due to changes in API level 9.
+ *
+ * @param editor the editor
+ */
+ public void applyPreferenceChanges(SharedPreferences.Editor editor);
+
+ /**
+ * Enables strict mode where supported, only if this is a development build.
+ * <p>
+ * Due to changes in API level 9.
+ */
+ public void enableStrictMode();
+
+ /**
+ * Copies elements from an input byte array into a new byte array, from
+ * indexes start (inclusive) to end (exclusive). The end index must be less
+ * than or equal to the input length.
+ * <p>
+ * Due to changes in API level 9.
+ *
+ * @param input the input byte array
+ * @param start the start index
+ * @param end the end index
+ * @return a new array containing elements from the input byte array.
+ */
+ public byte[] copyByteArray(byte[] input, int start, int end);
+
+
+
+
+ /**
+ * Hides the title. If the platform supports the action bar, do nothing.
+ * Ideally, with the action bar, we would like to collapse the navigation tabs
+ * into the action bar. However, collapsing is not supported by the
+ * compatibility library.
+ * <p>
+ * Due to changes in API level 11.
+ *
+ * @param activity the activity
+ */
+ public void hideTitle(Activity activity);
+
+ /**
+ * Configures the action bar with the Home button as an Up button. If the
+ * platform doesn't support the action bar, do nothing.
+ * <p>
+ * Due to changes in API level 11.
+ *
+ * @param activity the activity
+ */
+ public void configureActionBarHomeAsUp(Activity activity);
+
+ /**
+ * Configures the list view context menu.
+ * <p>
+ * Due to changes in API level 11.
+ *
+ * @param activity the activity
+ * @param listView the list view
+ * @param contextualActionModeCallback the callback when an item is selected
+ * in the contextual action mode
+ */
+ public void configureListViewContextualMenu(Activity activity, ListView listView,
+ ContextualActionModeCallback contextualActionModeCallback);
+
+ /**
+ * Configures the search widget.
+ *
+ * Due to changes in API level 11.
+ *
+ * @param activity the activity
+ * @param menuItem the search menu item
+ */
+ public void configureSearchWidget(Activity activity, MenuItem menuItem);
+
+ /**
+ * Handles the search menu selection. Returns true if handled.
+ *
+ * Due to changes in API level 11.
+ *
+ * @param activity the activity
+ */
+ public boolean handleSearchMenuSelection(Activity activity);
+
+ /**
+ * Adds all items to an array adapter.
+ *
+ * Due to changes in API level 11.
+ *s
+ * @param arrayAdapter the array adapter
+ * @param items list of items
+ */
+ public <T> void addAllToArrayAdapter(ArrayAdapter<T> arrayAdapter, List<T> items);
+
+ /**
+ * Handles the search key press. Returns true if handled.
+ *
+ * Due to changes in API level 14.
+ *
+ * @param menu the search menu
+ */
+ public boolean handleSearchKey(MenuItem menu);
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/backup/ApiAdapterFactory.java b/vdrmanager/src/de/bjusystems/vdrmanager/backup/ApiAdapterFactory.java
new file mode 100644
index 0000000..5a14c10
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/backup/ApiAdapterFactory.java
@@ -0,0 +1,56 @@
+/*
+ * 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 de.bjusystems.vdrmanager.backup;
+
+import android.os.Build;
+
+/**
+ * A factory to get the {@link ApiAdapter} for the current device.
+ *
+ * @author Rodrigo Damazio
+ */
+public class ApiAdapterFactory {
+
+ private static ApiAdapter apiAdapter;
+
+ /**
+ * Gets the {@link ApiAdapter} for the current device.
+ */
+ public static ApiAdapter getApiAdapter() {
+ if (apiAdapter == null) {
+ if (Build.VERSION.SDK_INT >= 14) {
+ apiAdapter = new Api14Adapter();
+ return apiAdapter;
+ } else if (Build.VERSION.SDK_INT >= 11) {
+ apiAdapter = new Api11Adapter();
+ return apiAdapter;
+ } else if (Build.VERSION.SDK_INT >= 10) {
+ apiAdapter = new Api10Adapter();
+ return apiAdapter;
+ } else if (Build.VERSION.SDK_INT >= 9) {
+ apiAdapter = new Api9Adapter();
+ return apiAdapter;
+ } else if (Build.VERSION.SDK_INT >= 8) {
+ apiAdapter = new Api8Adapter();
+ return apiAdapter;
+ } else {
+ apiAdapter = new Api7Adapter();
+ return apiAdapter;
+ }
+ }
+ return apiAdapter;
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/backup/BackupActivity.java b/vdrmanager/src/de/bjusystems/vdrmanager/backup/BackupActivity.java
new file mode 100644
index 0000000..ed0da12
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/backup/BackupActivity.java
@@ -0,0 +1,89 @@
+/*
+ * 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 de.bjusystems.vdrmanager.backup;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.widget.Toast;
+import de.bjusystems.vdrmanager.R;
+
+/**
+ * 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;
+
+ @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) {
+ if (id != DIALOG_PROGRESS_ID) {
+ return null;
+ }
+ return DialogUtils.createSpinnerProgressDialog(
+ this, R.string.settings_backup_now_progress_message, new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ finish();
+ }
+ });
+ }
+
+ /**
+ * 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);
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/backup/BackupAsyncTask.java b/vdrmanager/src/de/bjusystems/vdrmanager/backup/BackupAsyncTask.java
new file mode 100644
index 0000000..8e98ac0
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/backup/BackupAsyncTask.java
@@ -0,0 +1,110 @@
+/*
+ * 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 de.bjusystems.vdrmanager.backup;
+
+
+import java.io.IOException;
+
+import android.os.AsyncTask;
+import android.util.Log;
+import de.bjusystems.vdrmanager.R;
+
+/**
+ * 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);
+ success = false;
+ completed = false;
+ messageId = R.string.sd_card_save_error;
+ }
+
+ /**
+ * 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) {
+ if (!FileUtils.isSdCardAvailable()) {
+ messageId = R.string.sd_card_error_no_storage;
+ return false;
+ }
+
+ if (!externalFileBackup.isBackupsDirectoryAvailable(true)) {
+ messageId = R.string.sd_card_save_error_create_dir;
+ return false;
+ }
+
+ try {
+ externalFileBackup.writeToDefaultFile();
+ messageId = R.string.sd_card_save_success;
+ 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);
+ }
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/backup/BackupPreferencesListener.java b/vdrmanager/src/de/bjusystems/vdrmanager/backup/BackupPreferencesListener.java
new file mode 100644
index 0000000..c9a5b2f
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/backup/BackupPreferencesListener.java
@@ -0,0 +1,27 @@
+/*
+ * 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 de.bjusystems.vdrmanager.backup;
+
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+
+/**
+ * Shared preferences listener which notifies the backup system about new data
+ * being available for backup.
+ *
+ * @author Rodrigo Damazio
+ */
+public interface BackupPreferencesListener extends OnSharedPreferenceChangeListener {
+} \ No newline at end of file
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/backup/BackupSettingsActivity.java b/vdrmanager/src/de/bjusystems/vdrmanager/backup/BackupSettingsActivity.java
new file mode 100644
index 0000000..e906a20
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/backup/BackupSettingsActivity.java
@@ -0,0 +1,121 @@
+/*
+ * 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 de.bjusystems.vdrmanager.backup;
+
+
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceClickListener;
+import android.preference.PreferenceManager;
+import de.bjusystems.vdrmanager.R;
+
+/**
+ * An activity for accessing the backup settings.
+ *
+ * @author Jimmy Shih
+ */
+public class BackupSettingsActivity extends AbstractSettingsActivity {
+
+ private static final int DIALOG_CONFIRM_RESTORE_ID = 0;
+
+ Preference backupPreference;
+ Preference restorePreference;
+
+ /*
+ * Note that sharedPreferenceChangeListenr cannot be an anonymous inner class.
+ * Anonymous inner class will get garbage collected.
+ */
+ private final OnSharedPreferenceChangeListener
+ sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() {
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
+ // Note that key can be null
+ //if (PreferencesUtils.getKey(BackupSettingsActivity.this, R.string.recording_track_id_key)
+ // .equals(key)) {
+ //updateUi();
+ //}
+ }
+ };
+
+ @SuppressWarnings("deprecation")
+ @Override
+ protected void onCreate(Bundle bundle) {
+ super.onCreate(bundle);
+ PreferenceManager.getDefaultSharedPreferences(this)
+ .registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
+
+ addPreferencesFromResource(R.xml.backup_settings);
+ backupPreference = findPreference(getString(R.string.settings_backup_now_key));
+ backupPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ Intent intent = IntentUtils.newIntent(BackupSettingsActivity.this, BackupActivity.class);
+ startActivity(intent);
+ return true;
+ }
+ });
+ restorePreference = findPreference(getString(R.string.settings_backup_restore_key));
+ restorePreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ showDialog(DIALOG_CONFIRM_RESTORE_ID);
+ return true;
+ }
+ });
+ }
+
+ @Override
+ protected Dialog onCreateDialog(int id) {
+ if (id != DIALOG_CONFIRM_RESTORE_ID) {
+ return null;
+ }
+ return DialogUtils.createConfirmationDialog(this,
+ R.string.settings_backup_restore_confirm_message, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ Intent intent = IntentUtils.newIntent(
+ BackupSettingsActivity.this, RestoreChooserActivity.class);
+ startActivity(intent);
+ }
+ });
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ //updateUi();
+ }
+
+// /**
+// * Updates the UI based on the recording state.
+// */
+// private void updateUi() {
+// boolean isRecording = PreferencesUtils.getLong(this, R.string.recording_track_id_key)
+// != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
+// backupPreference.setEnabled(!isRecording);
+// restorePreference.setEnabled(!isRecording);
+// backupPreference.setSummary(isRecording ? R.string.settings_not_while_recording
+// : R.string.settings_backup_now_summary);
+// restorePreference.setSummary(isRecording ? R.string.settings_not_while_recording
+// : R.string.settings_backup_restore_summary);
+// }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/backup/Constants.java b/vdrmanager/src/de/bjusystems/vdrmanager/backup/Constants.java
new file mode 100644
index 0000000..491ec6f
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/backup/Constants.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2008 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 de.bjusystems.vdrmanager.backup;
+
+/**
+ * Constants used by the MyTracks application.
+ *
+ * @author Leif Hendrik Wilden
+ */
+public abstract class Constants {
+
+ /**
+ * Should be used by all log statements
+ */
+ public static final String TAG = "vdrmanager";
+
+ /**
+ * Name of the top-level directory inside the SD card where our files will
+ * be read from/written to.
+ */
+ public static final String SDCARD_TOP_DIR = "vdrmanager";
+
+ /**
+ * The number of distance readings to smooth to get a stable signal.
+ */
+ public static final int DISTANCE_SMOOTHING_FACTOR = 25;
+
+ /**
+ * The number of elevation readings to smooth to get a somewhat accurate
+ * signal.
+ */
+ public static final int ELEVATION_SMOOTHING_FACTOR = 25;
+
+ /**
+ * The number of grade readings to smooth to get a somewhat accurate signal.
+ */
+ public static final int GRADE_SMOOTHING_FACTOR = 5;
+
+ /**
+ * The number of speed reading to smooth to get a somewhat accurate signal.
+ */
+ public static final int SPEED_SMOOTHING_FACTOR = 25;
+
+ /**
+ * Maximum number of track points displayed by the map overlay.
+ */
+ public static final int MAX_DISPLAYED_TRACK_POINTS = 10000;
+
+ /**
+ * Target number of track points displayed by the map overlay.
+ * We may display more than this number of points.
+ */
+ public static final int TARGET_DISPLAYED_TRACK_POINTS = 5000;
+
+ /**
+ * Maximum number of track points ever loaded at once from the provider into
+ * memory.
+ * With a recording frequency of 2 seconds, 15000 corresponds to 8.3 hours.
+ */
+ public static final int MAX_LOADED_TRACK_POINTS = 20000;
+
+ /**
+ * Maximum number of track points ever loaded at once from the provider into
+ * memory in a single call to read points.
+ */
+ public static final int MAX_LOADED_TRACK_POINTS_PER_BATCH = 1000;
+
+ /**
+ * Maximum number of way points displayed by the map overlay.
+ */
+ public static final int MAX_DISPLAYED_WAYPOINTS_POINTS = 128;
+
+ /**
+ * Maximum number of way points that will be loaded at one time.
+ */
+ public static final int MAX_LOADED_WAYPOINTS_POINTS = 10000;
+
+ /**
+ * Any time segment where the distance traveled is less than this value will
+ * not be considered moving.
+ */
+ public static final double MAX_NO_MOVEMENT_DISTANCE = 2;
+
+ /**
+ * Anything faster than that (in meters per second) will be considered moving.
+ */
+ public static final double MAX_NO_MOVEMENT_SPEED = 0.224;
+
+ /**
+ * Ignore any acceleration faster than this.
+ * Will ignore any speeds that imply accelaration greater than 2g's
+ * 2g = 19.6 m/s^2 = 0.0002 m/ms^2 = 0.02 m/(m*ms)
+ */
+ public static final double MAX_ACCELERATION = 0.02;
+
+ /** Maximum age of a GPS location to be considered current. */
+ public static final long MAX_LOCATION_AGE_MS = 60 * 1000; // 1 minute
+
+ /** Maximum age of a network location to be considered current. */
+ public static final long MAX_NETWORK_AGE_MS = 1000 * 60 * 10; // 10 minutes
+
+ /**
+ * The type of account that we can use for gdata uploads.
+ */
+ public static final String ACCOUNT_TYPE = "com.google";
+
+ /**
+ * The name of extra intent property to indicate whether we want to resume
+ * a previously recorded track.
+ */
+ public static final String
+ RESUME_TRACK_EXTRA_NAME = "com.google.android.apps.mytracks.RESUME_TRACK";
+
+ public static final String MAPSHOP_BASE_URL = "https://maps.google.com/maps/ms";
+
+ public static final String SETTINGS_NAME = "SettingsActivity";
+
+ /**
+ * This is an abstract utility class.
+ */
+ protected Constants() { }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/backup/ContentTypeIds.java b/vdrmanager/src/de/bjusystems/vdrmanager/backup/ContentTypeIds.java
new file mode 100644
index 0000000..bf48983
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/backup/ContentTypeIds.java
@@ -0,0 +1,33 @@
+/*
+ * 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 de.bjusystems.vdrmanager.backup;
+
+/**
+ * Utilities for serializing primitive types.
+ *
+ * @author Rodrigo Damazio
+ */
+public class ContentTypeIds {
+ public static final byte BOOLEAN_TYPE_ID = 0;
+ public static final byte LONG_TYPE_ID = 1;
+ public static final byte INT_TYPE_ID = 2;
+ public static final byte FLOAT_TYPE_ID = 3;
+ public static final byte DOUBLE_TYPE_ID = 4;
+ public static final byte STRING_TYPE_ID = 5;
+ public static final byte BLOB_TYPE_ID = 6;
+
+ private ContentTypeIds() { /* Not instantiable */ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/backup/ContextualActionModeCallback.java b/vdrmanager/src/de/bjusystems/vdrmanager/backup/ContextualActionModeCallback.java
new file mode 100644
index 0000000..d79d4be
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/backup/ContextualActionModeCallback.java
@@ -0,0 +1,34 @@
+/*
+ * 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 de.bjusystems.vdrmanager.backup;
+
+/**
+ * Callback when an item in the contextual action mode is selected.
+ *
+ * @author Jimmy Shih
+ */
+public interface ContextualActionModeCallback {
+
+ /**
+ * Invoked when an item is selected.
+ *
+ * @param itemId the context menu item id
+ * @param position the position of the selected row
+ * @param id the id of the selected row, if available
+ */
+ public boolean onClick(int itemId, int position, long id);
+} \ No newline at end of file
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/backup/DialogUtils.java b/vdrmanager/src/de/bjusystems/vdrmanager/backup/DialogUtils.java
new file mode 100644
index 0000000..c9b716c
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/backup/DialogUtils.java
@@ -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 de.bjusystems.vdrmanager.backup;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import de.bjusystems.vdrmanager.R;
+
+/**
+ * Utilities for creating dialogs.
+ *
+ * @author Jimmy Shih
+ */
+public class DialogUtils {
+
+ private DialogUtils() {}
+
+ /**
+ * Creates a confirmation dialog.
+ *
+ * @param context the context
+ * @param messageId the confirmation message id
+ * @param onClickListener the listener to invoke when the user clicks OK
+ */
+ public static Dialog createConfirmationDialog(
+ Context context, int messageId, DialogInterface.OnClickListener onClickListener) {
+ return new AlertDialog.Builder(context)
+ .setCancelable(true)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setMessage(context.getString(messageId))
+ .setNegativeButton(android.R.string.cancel, null)
+ .setPositiveButton(android.R.string.ok, onClickListener)
+ .setTitle(R.string.generic_confirm_title)
+ .create();
+ }
+
+ /**
+ * Creates a spinner progress dialog.
+ *
+ * @param context the context
+ * @param messageId the progress message id
+ * @param onCancelListener the cancel listener
+ */
+ public static ProgressDialog createSpinnerProgressDialog(
+ Context context, int messageId, DialogInterface.OnCancelListener onCancelListener) {
+ return createProgressDialog(true, context, messageId, onCancelListener);
+ }
+
+ /**
+ * Creates a horizontal progress dialog.
+ *
+ * @param context the context
+ * @param messageId the progress message id
+ * @param onCancelListener the cancel listener
+ * @param formatArgs the format arguments for the messageId
+ */
+ public static ProgressDialog createHorizontalProgressDialog(Context context, int messageId,
+ DialogInterface.OnCancelListener onCancelListener, Object... formatArgs) {
+ return createProgressDialog(false, context, messageId, onCancelListener, formatArgs);
+ }
+
+ /**
+ * Creates a progress dialog.
+ *
+ * @param spinner true to use the spinner style
+ * @param context the context
+ * @param messageId the progress message id
+ * @param onCancelListener the cancel listener
+ * @param formatArgs the format arguments for the message id
+ */
+ private static ProgressDialog createProgressDialog(boolean spinner, Context context,
+ int messageId, DialogInterface.OnCancelListener onCancelListener, Object... formatArgs) {
+ ProgressDialog progressDialog = new ProgressDialog(context);
+ progressDialog.setCancelable(true);
+ progressDialog.setIcon(android.R.drawable.ic_dialog_info);
+ progressDialog.setIndeterminate(true);
+ progressDialog.setMessage(context.getString(messageId, formatArgs));
+ progressDialog.setOnCancelListener(onCancelListener);
+ progressDialog.setProgressStyle(spinner ? ProgressDialog.STYLE_SPINNER
+ : ProgressDialog.STYLE_HORIZONTAL);
+ progressDialog.setTitle(R.string.generic_progress_title);
+ return progressDialog;
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/backup/ExternalFileBackup.java b/vdrmanager/src/de/bjusystems/vdrmanager/backup/ExternalFileBackup.java
new file mode 100644
index 0000000..22bb1dd
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/backup/ExternalFileBackup.java
@@ -0,0 +1,276 @@
+/*
+ * 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 de.bjusystems.vdrmanager.backup;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.TimeZone;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipOutputStream;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+import android.util.Log;
+import de.bjusystems.vdrmanager.data.db.OrmDatabaseHelper;
+
+/**
+ * Handler for writing or reading single-file backups.
+ *
+ * @author Rodrigo Damazio
+ */
+class ExternalFileBackup {
+ // Filename format - in UTC
+ private static final SimpleDateFormat BACKUP_FILENAME_FORMAT = new SimpleDateFormat(
+ "'backup-'yyyy-MM-dd_HH-mm-ss'.zip'");
+ static {
+ BACKUP_FILENAME_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
+ }
+
+ private static final String BACKUPS_SUBDIR = "backups";
+ private static final int BACKUP_FORMAT_VERSION = 1;
+ private static final String ZIP_ENTRY_NAME = "backup.mybillingbuddy.v"
+ + BACKUP_FORMAT_VERSION;
+ private static final int COMPRESSION_LEVEL = 8;
+
+ private final Context context;
+
+ public ExternalFileBackup(Context context) {
+ this.context = context;
+ }
+
+ /**
+ * Returns whether the backups directory is (or can be made) available.
+ *
+ * @param create
+ * whether to try creating the directory if it doesn't exist
+ */
+ public boolean isBackupsDirectoryAvailable(boolean create) {
+ return getBackupsDirectory(create) != null;
+ }
+
+ /**
+ * Returns the backup directory, or null if not available.
+ *
+ * @param create
+ * whether to try creating the directory if it doesn't exist
+ */
+ private File getBackupsDirectory(boolean create) {
+ String dirName = FileUtils.buildExternalDirectoryPath(BACKUPS_SUBDIR);
+ final File dir = new File(dirName);
+ Log.d(Constants.TAG, "Dir: " + dir.getAbsolutePath());
+ if (create) {
+ // Try to create - if that fails, return null
+ return FileUtils.ensureDirectoryExists(dir) ? dir : null;
+ } else {
+ // Return it if it already exists, otherwise return null
+ return dir.isDirectory() ? dir : null;
+ }
+ }
+
+ /**
+ * Returns a list of available backups to be restored.
+ */
+ public Date[] getAvailableBackups() {
+ File dir = getBackupsDirectory(false);
+ if (dir == null) {
+ return null;
+ }
+ String[] fileNames = dir.list();
+
+ List<Date> backupDates = new ArrayList<Date>(fileNames.length);
+ for (int i = 0; i < fileNames.length; i++) {
+ String fileName = fileNames[i];
+ try {
+ backupDates.add(BACKUP_FILENAME_FORMAT.parse(fileName));
+ } catch (ParseException e) {
+ // Not a backup file, ignore
+ }
+ }
+
+ return backupDates.toArray(new Date[backupDates.size()]);
+ }
+
+ /**
+ * Writes the backup to the default file.
+ */
+ public void writeToDefaultFile() throws IOException {
+ writeToFile(getFileForDate(new Date()));
+ }
+
+ /**
+ * Restores the backup from the given date.
+ */
+ public void restoreFromDate(Date when) throws IOException {
+ restoreFromFile(getFileForDate(when));
+ }
+
+ public void restoreFromFile(String path ) throws IOException {
+ restoreFromFile(new File(path));
+ }
+
+ /**
+ * Produces the proper file descriptor for the given backup date.
+ */
+ private File getFileForDate(Date when) {
+ File dir = getBackupsDirectory(false);
+ String fileName = BACKUP_FILENAME_FORMAT.format(when);
+ File file = new File(dir, fileName);
+ return file;
+ }
+
+ /**
+ * Synchronously writes a backup to the given file.
+ */
+ private void writeToFile(File outputFile) throws IOException {
+ Log.d(Constants.TAG,
+ "Writing backup to file " + outputFile.getAbsolutePath());
+
+ // Create all the auxiliary classes that will do the writing
+ //DatabaseDumper trackDumper = new DatabaseDumper(
+ // BackupColumns.TRACKS_BACKUP_COLUMNS,
+ //BackupColumns.TRACKS_BACKUP_COLUMN_TYPES, false);
+ //DatabaseDumper waypointDumper = new DatabaseDumper(
+ // BackupColumns.WAYPOINTS_BACKUP_COLUMNS,
+ //BackupColumns.WAYPOINTS_BACKUP_COLUMN_TYPES, false);
+ //DatabaseDumper pointDumper = new DatabaseDumper(
+ // BackupColumns.POINTS_BACKUP_COLUMNS,
+ //BackupColumns.POINTS_BACKUP_COLUMN_TYPES, false);
+
+ // Open the target for writing
+ FileOutputStream outputStream = new FileOutputStream(outputFile);
+ ZipOutputStream compressedStream = new ZipOutputStream(outputStream);
+ compressedStream.setLevel(COMPRESSION_LEVEL);
+ compressedStream.putNextEntry(new ZipEntry(ZIP_ENTRY_NAME));
+ DataOutputStream outWriter = new DataOutputStream(compressedStream);
+
+ try {
+ // Dump the entire contents of each table
+// ContentResolver contentResolver = context.getContentResolver();
+// Cursor tracksCursor = contentResolver.query(
+// TracksColumns.CONTENT_URI, null, null, null, null);
+// try {
+// trackDumper.writeAllRows(tracksCursor, outWriter);
+// } finally {
+// tracksCursor.close();
+// }
+//
+// Cursor waypointsCursor = contentResolver.query(
+// WaypointsColumns.CONTENT_URI, null, null, null, null);
+// try {
+// waypointDumper.writeAllRows(waypointsCursor, outWriter);
+// } finally {
+// waypointsCursor.close();
+// }
+//
+// Cursor pointsCursor = contentResolver.query(
+// TrackPointsColumns.CONTENT_URI, null, null, null, null);
+// try {
+// pointDumper.writeAllRows(pointsCursor, outWriter);
+// } finally {
+// pointsCursor.close();
+// }
+
+ // Dump preferences
+ SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
+ PreferenceBackupHelper preferencesHelper = new PreferenceBackupHelper();
+ preferencesHelper.exportPreferences(preferences, outWriter);
+
+
+ File f = new File(OrmDatabaseHelper.getDataBaseFile());
+ if(f.exists()){
+ compressedStream.putNextEntry(new ZipEntry(OrmDatabaseHelper.DATABASE_NAME));
+ IOUtils.copy(new FileInputStream(OrmDatabaseHelper.getDataBaseFile()), outWriter);
+ }
+
+
+
+
+
+
+ } catch (IOException e) {
+ // We tried to delete the partially created file, but do nothing
+ // if that also fails.
+ if (!outputFile.delete()) {
+ Log.w(Constants.TAG,
+ "Failed to delete file " + outputFile.getAbsolutePath());
+ }
+
+ throw e;
+ } finally {
+ compressedStream.closeEntry();
+ compressedStream.close();
+ }
+ }
+
+ /**
+ * Synchronously restores the backup from the given file.
+ */
+ private void restoreFromFile(File inputFile) throws IOException {
+ Log.d(Constants.TAG,
+ "Restoring from file " + inputFile.getAbsolutePath());
+
+
+
+ ZipFile zipFile = new ZipFile(inputFile, ZipFile.OPEN_READ);
+ 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 {
+
+ // Restore preferences
+ SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
+ PreferenceBackupHelper preferencesHelper = new PreferenceBackupHelper();
+ preferencesHelper.importPreferences(reader, preferences);
+
+
+
+
+ zipEntry = zipFile.getEntry(OrmDatabaseHelper.DATABASE_NAME);
+ if (zipEntry != null) {
+ IOUtils.copy(zipFile.getInputStream(zipEntry), new FileOutputStream(OrmDatabaseHelper.getDataBaseFile()));
+ deleteJournal(OrmDatabaseHelper.getDataBaseFile());
+ }
+
+ } finally {
+ compressedStream.close();
+ zipFile.close();
+ }
+ }
+
+ private static void deleteJournal(String db){
+ if(db == null){
+ return;
+ }
+ new File(db+"-journal").delete();
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/backup/FileUtils.java b/vdrmanager/src/de/bjusystems/vdrmanager/backup/FileUtils.java
new file mode 100644
index 0000000..d53a80b
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/backup/FileUtils.java
@@ -0,0 +1,199 @@
+/*
+ * 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 de.bjusystems.vdrmanager.backup;
+
+
+import android.os.Environment;
+
+import java.io.File;
+
+/**
+ * Utilities for dealing with files.
+ *
+ * @author Rodrigo Damazio
+ */
+public class FileUtils {
+
+ private FileUtils() {}
+
+ /**
+ * The maximum FAT32 path length. See the FAT32 spec at
+ * http://msdn.microsoft.com/en-us/windows/hardware/gg463080
+ */
+ static final int MAX_FAT32_PATH_LENGTH = 260;
+
+ /**
+ * Returns whether the SD card is available.
+ */
+ public static boolean isSdCardAvailable() {
+ return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
+ }
+
+ /**
+ * Ensures the given directory exists by creating it and its parents if
+ * necessary.
+ *
+ * @return whether the directory exists (either already existed or was
+ * successfully created)
+ */
+ public static boolean ensureDirectoryExists(File dir) {
+ if (dir.exists() && dir.isDirectory()) {
+ return true;
+ }
+ if (dir.mkdirs()) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Builds a path inside the My Tracks directory in the SD card.
+ *
+ * @param components the path components inside the mytracks directory
+ * @return the full path to the destination
+ */
+ public static String buildExternalDirectoryPath(String... components) {
+ StringBuilder dirNameBuilder = new StringBuilder();
+ dirNameBuilder.append(Environment.getExternalStorageDirectory());
+ dirNameBuilder.append(File.separatorChar);
+ dirNameBuilder.append(Constants.SDCARD_TOP_DIR);
+ for (String component : components) {
+ dirNameBuilder.append(File.separatorChar);
+ dirNameBuilder.append(component);
+ }
+ return dirNameBuilder.toString();
+ }
+
+ /**
+ * Builds a filename with the given base name (prefix) and the given
+ * extension, possibly adding a suffix to ensure the file doesn't exist.
+ *
+ * @param directory the directory the file will live in
+ * @param fileBaseName the prefix for the file name
+ * @param extension the file's extension
+ * @return the complete file name, without the directory
+ */
+ public static synchronized String buildUniqueFileName(
+ File directory, String fileBaseName, String extension) {
+ return buildUniqueFileName(directory, fileBaseName, extension, 0);
+ }
+
+ /**
+ * Builds a filename with the given base and the given extension, possibly
+ * adding a suffix to ensure the file doesn't exist.
+ *
+ * @param directory the directory the filename will be located in
+ * @param base the base for the filename
+ * @param extension the extension for the filename
+ * @param suffix the first numeric suffix to try to use, or 0 for none
+ * @return the complete filename, without the directory
+ */
+ private static String buildUniqueFileName(
+ File directory, String base, String extension, int suffix) {
+ String suffixName = "";
+ if (suffix > 0) {
+ suffixName += "(" + Integer.toString(suffix) + ")";
+ }
+ suffixName += "." + extension;
+
+ String baseName = sanitizeFileName(base);
+ baseName = truncateFileName(directory, baseName, suffixName);
+ String fullName = baseName + suffixName;
+
+ if (!new File(directory, fullName).exists()) {
+ return fullName;
+ }
+ return buildUniqueFileName(directory, base, extension, suffix + 1);
+ }
+
+ /**
+ * Sanitizes the name as a valid fat32 filename. For simplicity, fat32
+ * filename characters may be any combination of letters, digits, or
+ * characters with code point values greater than 127. Replaces the invalid
+ * characters with "_" and collapses multiple "_" together.
+ *
+ * @param name name
+ */
+ static String sanitizeFileName(String name) {
+ StringBuffer buffer = new StringBuffer(name.length());
+ for (int i = 0; i < name.length(); i++) {
+ int codePoint = name.codePointAt(i);
+ char character = name.charAt(i);
+ if (Character.isLetterOrDigit(character) || codePoint > 127 || isSpecialFat32(character)) {
+ buffer.appendCodePoint(codePoint);
+ } else {
+ buffer.append("_");
+ }
+ }
+ String result = buffer.toString();
+ return result.replaceAll("_+", "_");
+ }
+
+ /**
+ * Returns true if it is a special FAT32 character.
+ *
+ * @param character the character
+ */
+ private static boolean isSpecialFat32(char character) {
+ switch (character) {
+ case '$':
+ case '%':
+ case '\'':
+ case '-':
+ case '_':
+ case '@':
+ case '~':
+ case '`':
+ case '!':
+ case '(':
+ case ')':
+ case '{':
+ case '}':
+ case '^':
+ case '#':
+ case '&':
+ case '+':
+ case ',':
+ case ';':
+ case '=':
+ case '[':
+ case ']':
+ case ' ':
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Truncates the name if necessary so the filename path length (directory +
+ * name + suffix) meets the Fat32 path limit.
+ *
+ * @param directory directory
+ * @param name name
+ * @param suffix suffix
+ */
+ static String truncateFileName(File directory, String name, String suffix) {
+ // 1 at the end accounts for the FAT32 filename trailing NUL character
+ int requiredLength = directory.getPath().length() + suffix.length() + 1;
+ if (name.length() + requiredLength > MAX_FAT32_PATH_LENGTH) {
+ int limit = MAX_FAT32_PATH_LENGTH - requiredLength;
+ return name.substring(0, limit);
+ } else {
+ return name;
+ }
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/backup/IOUtils.java b/vdrmanager/src/de/bjusystems/vdrmanager/backup/IOUtils.java
new file mode 100644
index 0000000..53be61c
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/backup/IOUtils.java
@@ -0,0 +1,217 @@
+package de.bjusystems.vdrmanager.backup;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You 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.
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+/**
+ * General IO stream manipulation utilities.
+ * <p>
+ * This class provides static utility methods for input/output operations.
+ * <ul>
+ * <li>closeQuietly - these methods close a stream ignoring nulls and exceptions
+ * <li>toXxx/read - these methods read data from a stream
+ * <li>write - these methods write data to a stream
+ * <li>copy - these methods copy all the data from one stream to another
+ * <li>contentEquals - these methods compare the content of two streams
+ * </ul>
+ * <p>
+ * The byte-to-char methods and char-to-byte methods involve a conversion step.
+ * Two methods are provided in each case, one that uses the platform default
+ * encoding and the other which allows you to specify an encoding. You are
+ * encouraged to always specify an encoding because relying on the platform
+ * default can lead to unexpected results, for example when moving from
+ * development to production.
+ * <p>
+ * All the methods in this class that read a stream are buffered internally.
+ * This means that there is no cause to use a <code>BufferedInputStream</code>
+ * or <code>BufferedReader</code>. The default buffer size of 4K has been shown
+ * to be efficient in tests.
+ * <p>
+ * Wherever possible, the methods in this class do <em>not</em> flush or close
+ * the stream. This is to avoid making non-portable assumptions about the
+ * streams' origin and further use. Thus the caller is still responsible for
+ * closing streams after use.
+ * <p>
+ * Origin of code: Excalibur.
+ *
+ * @author Peter Donald
+ * @author Jeff Turner
+ * @author Matthew Hawthorne
+ * @author Stephen Colebourne
+ * @author Gareth Davis
+ * @author Ian Springer
+ * @author Niall Pemberton
+ * @author Sandy McArthur
+ * @version $Id: IOUtils.java 481854 2006-12-03 18:30:07Z scolebourne $
+ */
+public class IOUtils {
+ // NOTE: This class is focussed on InputStream, OutputStream, Reader and
+ // Writer. Each method should take at least one of these as a parameter,
+ // or return one of them.
+
+ /**
+ * The Unix directory separator character.
+ */
+ public static final char DIR_SEPARATOR_UNIX = '/';
+ /**
+ * The Windows directory separator character.
+ */
+ public static final char DIR_SEPARATOR_WINDOWS = '\\';
+ /**
+ * The system directory separator character.
+ */
+ public static final char DIR_SEPARATOR = File.separatorChar;
+ /**
+ * The Unix line separator string.
+ */
+ public static final String LINE_SEPARATOR_UNIX = "\n";
+ /**
+ * The Windows line separator string.
+ */
+ public static final String LINE_SEPARATOR_WINDOWS = "\r\n";
+ /**
+ * The system line separator string.
+ */
+ public static final String LINE_SEPARATOR;
+ static {
+ // avoid security issues
+ StringWriter buf = new StringWriter(4);
+ PrintWriter out = new PrintWriter(buf);
+ out.println();
+ LINE_SEPARATOR = buf.toString();
+ }
+
+ /**
+ * The default buffer size to use.
+ */
+ private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
+
+ /**
+ * Instances should NOT be constructed in standard programming.
+ */
+ public IOUtils() {
+ super();
+ }
+
+ // copy from InputStream
+ // -----------------------------------------------------------------------
+ /**
+ * Copy bytes from an <code>InputStream</code> to an
+ * <code>OutputStream</code>.
+ * <p>
+ * This method buffers the input internally, so there is no need to use a
+ * <code>BufferedInputStream</code>.
+ * <p>
+ * Large streams (over 2GB) will return a bytes copied value of
+ * <code>-1</code> after the copy has completed since the correct number of
+ * bytes cannot be returned as an int. For large streams use the
+ * <code>copyLarge(InputStream, OutputStream)</code> method.
+ *
+ * @param input
+ * the <code>InputStream</code> to read from
+ * @param output
+ * the <code>OutputStream</code> to write to
+ * @return the number of bytes copied
+ * @throws NullPointerException
+ * if the input or output is null
+ * @throws IOException
+ * if an I/O error occurs
+ * @throws ArithmeticException
+ * if the byte count is too large
+ * @since Commons IO 1.1
+ */
+ public static int copy(final InputStream input, final OutputStream output)
+ throws IOException {
+ long count = copyLarge(input, output);
+ if (count > Integer.MAX_VALUE) {
+ return -1;
+ }
+ return (int) count;
+ }
+
+ /**
+ * Copy bytes from a large (over 2GB) <code>InputStream</code> to an
+ * <code>OutputStream</code>.
+ * <p>
+ * This method buffers the input internally, so there is no need to use a
+ * <code>BufferedInputStream</code>.
+ *
+ * @param input
+ * the <code>InputStream</code> to read from
+ * @param output
+ * the <code>OutputStream</code> to write to
+ * @return the number of bytes copied
+ * @throws NullPointerException
+ * if the input or output is null
+ * @throws IOException
+ * if an I/O error occurs
+ * @since Commons IO 1.3
+ */
+ public static long copyLarge(final InputStream input,
+ final OutputStream output) throws IOException {
+ byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
+ long count = 0;
+ int n = 0;
+ while (-1 != (n = input.read(buffer))) {
+ output.write(buffer, 0, n);
+ count += n;
+ }
+ return count;
+ }
+ /**
+ * Unconditionally close an <code>InputStream</code>.
+ * <p>
+ * Equivalent to {@link InputStream#close()}, except any exceptions will be ignored.
+ * This is typically used in finally blocks.
+ *
+ * @param input the InputStream to close, may be null or already closed
+ */
+ public static void closeQuietly(InputStream input) {
+ try {
+ if (input != null) {
+ input.close();
+ }
+ } catch (IOException ioe) {
+ // ignore
+ }
+ }
+
+ /**
+ * Unconditionally close an <code>OutputStream</code>.
+ * <p>
+ * Equivalent to {@link OutputStream#close()}, except any exceptions will be ignored.
+ * This is typically used in finally blocks.
+ *
+ * @param output the OutputStream to close, may be null or already closed
+ */
+ public static void closeQuietly(OutputStream output) {
+ try {
+ if (output != null) {
+ output.close();
+ }
+ } catch (IOException ioe) {
+ // ignore
+ }
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/backup/IntentUtils.java b/vdrmanager/src/de/bjusystems/vdrmanager/backup/IntentUtils.java
new file mode 100644
index 0000000..43131b4
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/backup/IntentUtils.java
@@ -0,0 +1,47 @@
+/*
+ * 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 de.bjusystems.vdrmanager.backup;
+
+
+import android.content.Context;
+import android.content.Intent;
+
+/**
+ * Utilities for creating intents.
+ *
+ * @author Jimmy Shih
+ */
+public class IntentUtils {
+
+ public static final String TEXT_PLAIN_TYPE = "text/plain";
+
+ private IntentUtils() {}
+
+ /**
+ * Creates an intent with {@link Intent#FLAG_ACTIVITY_CLEAR_TOP} and
+ * {@link Intent#FLAG_ACTIVITY_NEW_TASK}.
+ *
+ * @param context the context
+ * @param cls the class
+ */
+ public static final Intent newIntent(Context context, Class<?> cls) {
+ return new Intent(context, cls).addFlags(
+ Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
+ }
+
+
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/backup/LineIterator.java b/vdrmanager/src/de/bjusystems/vdrmanager/backup/LineIterator.java
new file mode 100644
index 0000000..c60ee66
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/backup/LineIterator.java
@@ -0,0 +1,5 @@
+package de.bjusystems.vdrmanager.backup;
+
+public class LineIterator {
+
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/backup/PreferenceBackupHelper.java b/vdrmanager/src/de/bjusystems/vdrmanager/backup/PreferenceBackupHelper.java
new file mode 100644
index 0000000..30a32b4
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/backup/PreferenceBackupHelper.java
@@ -0,0 +1,172 @@
+/*
+ * 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 de.bjusystems.vdrmanager.backup;
+
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+
+/**
+ * Helper for backing up and restoring shared preferences.
+ *
+ * @author Rodrigo Damazio
+ */
+class PreferenceBackupHelper {
+
+ private static final int BUFFER_SIZE = 2048;
+
+ /**
+ * Exports all shared preferences from the given object as a byte array.
+ *
+ * @param preferences the preferences to export
+ * @return the corresponding byte array
+ * @throws IOException if there are any errors while writing to the byte array
+ */
+ public byte[] exportPreferences(SharedPreferences preferences)
+ throws IOException {
+ ByteArrayOutputStream bufStream = new ByteArrayOutputStream(BUFFER_SIZE);
+ DataOutputStream outWriter = new DataOutputStream(bufStream);
+ exportPreferences(preferences, outWriter);
+
+ return bufStream.toByteArray();
+ }
+
+ /**
+ * Exports all shared preferences from the given object into the given output
+ * stream.
+ *
+ * @param preferences the preferences to export
+ * @param outWriter the stream to write them to
+ * @throws IOException if there are any errors while writing the output
+ */
+ public void exportPreferences(
+ SharedPreferences preferences,
+ DataOutputStream outWriter) throws IOException {
+ Map<String, ?> values = preferences.getAll();
+
+ outWriter.writeInt(values.size());
+ for (Map.Entry<String, ?> entry : values.entrySet()) {
+ writePreference(entry.getKey(), entry.getValue(), outWriter);
+ }
+ outWriter.flush();
+ }
+
+ /**
+ * Imports all preferences from the given byte array.
+ *
+ * @param data the byte array to read preferences from
+ * @param preferences the shared preferences to edit
+ * @throws IOException if there are any errors while reading
+ */
+ public void importPreferences(byte[] data, SharedPreferences preferences)
+ throws IOException {
+ ByteArrayInputStream bufStream = new ByteArrayInputStream(data);
+ DataInputStream reader = new DataInputStream(bufStream);
+
+ importPreferences(reader, preferences);
+ }
+
+ /**
+ * Imports all preferences from the given stream.
+ *
+ * @param reader the stream to read from
+ * @param preferences the shared preferences to edit
+ * @throws IOException if there are any errors while reading
+ */
+ public void importPreferences(DataInputStream reader,
+ SharedPreferences preferences) throws IOException {
+ Editor editor = preferences.edit();
+ editor.clear();
+
+ int numPreferences = reader.readInt();
+ for (int i = 0; i < numPreferences; i++) {
+ String name = reader.readUTF();
+ byte typeId = reader.readByte();
+ readAndSetPreference(name, typeId, reader, editor);
+ }
+ ApiAdapterFactory.getApiAdapter().applyPreferenceChanges(editor);
+ }
+
+ /**
+ * Reads a single preference and sets it into the given editor.
+ *
+ * @param name the name of the preference to read
+ * @param typeId the type ID of the preference to read
+ * @param reader the reader to read from
+ * @param editor the editor to set the preference in
+ * @throws IOException if there are errors while reading
+ */
+ private void readAndSetPreference(String name, byte typeId,
+ DataInputStream reader, Editor editor) throws IOException {
+ switch (typeId) {
+ case ContentTypeIds.BOOLEAN_TYPE_ID:
+ editor.putBoolean(name, reader.readBoolean());
+ return;
+ case ContentTypeIds.LONG_TYPE_ID:
+ editor.putLong(name, reader.readLong());
+ return;
+ case ContentTypeIds.FLOAT_TYPE_ID:
+ editor.putFloat(name, reader.readFloat());
+ return;
+ case ContentTypeIds.INT_TYPE_ID:
+ editor.putInt(name, reader.readInt());
+ return;
+ case ContentTypeIds.STRING_TYPE_ID:
+ editor.putString(name, reader.readUTF());
+ return;
+ }
+ }
+
+ /**
+ * Writes a single preference.
+ *
+ * @param name the name of the preference to write
+ * @param value the correctly-typed value of the preference
+ * @param writer the writer to write to
+ * @throws IOException if there are errors while writing
+ */
+ private void writePreference(String name, Object value, DataOutputStream writer)
+ throws IOException {
+ writer.writeUTF(name);
+
+ if (value instanceof Boolean) {
+ writer.writeByte(ContentTypeIds.BOOLEAN_TYPE_ID);
+ writer.writeBoolean((Boolean) value);
+ } else if (value instanceof Integer) {
+ writer.writeByte(ContentTypeIds.INT_TYPE_ID);
+ writer.writeInt((Integer) value);
+ } else if (value instanceof Long) {
+ writer.writeByte(ContentTypeIds.LONG_TYPE_ID);
+ writer.writeLong((Long) value);
+ } else if (value instanceof Float) {
+ writer.writeByte(ContentTypeIds.FLOAT_TYPE_ID);
+ writer.writeFloat((Float) value);
+ } else if (value instanceof String) {
+ writer.writeByte(ContentTypeIds.STRING_TYPE_ID);
+ writer.writeUTF((String) value);
+ } else {
+ throw new IllegalArgumentException(
+ "Type " + value.getClass().getName() + " not supported");
+ }
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/backup/RestoreActivity.java b/vdrmanager/src/de/bjusystems/vdrmanager/backup/RestoreActivity.java
new file mode 100644
index 0000000..97e4749
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/backup/RestoreActivity.java
@@ -0,0 +1,114 @@
+/*
+ * 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 de.bjusystems.vdrmanager.backup;
+
+
+
+import java.util.Date;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.widget.Toast;
+import de.bjusystems.vdrmanager.R;
+import de.bjusystems.vdrmanager.gui.PreferencesActivity;
+
+/**
+ * An activity to restore data from the SD card.
+ *
+ * @author Jimmy Shih
+ */
+public class RestoreActivity extends Activity {
+
+ public static final String EXTRA_DATE = "date";
+ public static final String EXTRA_FILE = "file";
+
+ private static final String TAG = RestoreActivity.class.getSimpleName();
+ private static final int DIALOG_PROGRESS_ID = 0;
+
+ private RestoreAsyncTask restoreAsyncTask;
+
+ @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 = -1L;
+ String file = getIntent().getStringExtra(EXTRA_FILE);
+ if(file != null){
+ restoreAsyncTask = new RestoreAsyncTask(this, file);
+ } else if( (date = getIntent().getLongExtra(EXTRA_DATE, -1L)) != -1L) {
+ restoreAsyncTask = new RestoreAsyncTask(this, new Date(date));
+ } else {
+ Log.d(TAG, "Invalid date or file");
+ finish();
+ return;
+ }
+ restoreAsyncTask.execute();
+ }
+ }
+
+ @Override
+ public Object onRetainNonConfigurationInstance() {
+ restoreAsyncTask.setActivity(null);
+ return restoreAsyncTask;
+ }
+
+ @Override
+ protected Dialog onCreateDialog(int id) {
+ if (id != DIALOG_PROGRESS_ID) {
+ return null;
+ }
+ return DialogUtils.createSpinnerProgressDialog(this,
+ R.string.settings_backup_restore_progress_message, new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ finish();
+ }
+ });
+ }
+
+ /**
+ * 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();
+ //Intent intent = IntentUtils.newIntent(this, FixUpJobs.class);
+ //intent.putExtra(Extras.AFTER_RESTORE, Boolean.TRUE);
+ Intent intent = IntentUtils.newIntent(this, PreferencesActivity.class);
+ startActivity(intent);
+ }
+
+ /**
+ * Shows the progress dialog.
+ */
+ public void showProgressDialog() {
+ showDialog(DIALOG_PROGRESS_ID);
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/backup/RestoreAsyncTask.java b/vdrmanager/src/de/bjusystems/vdrmanager/backup/RestoreAsyncTask.java
new file mode 100644
index 0000000..37373f3
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/backup/RestoreAsyncTask.java
@@ -0,0 +1,136 @@
+/*
+ * 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 de.bjusystems.vdrmanager.backup;
+
+import java.io.IOException;
+import java.util.Date;
+
+import android.os.AsyncTask;
+import android.util.Log;
+import de.bjusystems.vdrmanager.R;
+
+/**
+ * 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 String path;
+ 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, date, null);
+ }
+
+ /**
+ * Creates an AsyncTask.
+ *
+ * @param restoreActivity
+ * the activity currently associated with this AsyncTask
+ * @param date
+ * the date to retore from
+ */
+ public RestoreAsyncTask(RestoreActivity restoreActivity, String path) {
+ this(restoreActivity, null, path);
+ }
+
+ /**
+ * 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,
+ String path) {
+ this.restoreActivity = restoreActivity;
+ this.date = date;
+ this.path = path;
+ this.externalFileBackup = new ExternalFileBackup(restoreActivity);
+ success = false;
+ completed = false;
+ messageId = R.string.sd_card_import_error;
+ }
+
+ /**
+ * 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 {
+ if (path != null) {
+ externalFileBackup.restoreFromFile(path);
+ } else {
+ externalFileBackup.restoreFromDate(date);
+ }
+ messageId = R.string.sd_card_import_success;
+ 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);
+ }
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/backup/RestoreChooserActivity.java b/vdrmanager/src/de/bjusystems/vdrmanager/backup/RestoreChooserActivity.java
new file mode 100644
index 0000000..cba6ab0
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/backup/RestoreChooserActivity.java
@@ -0,0 +1,127 @@
+/*
+ * 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 de.bjusystems.vdrmanager.backup;
+
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Date;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.Bundle;
+import android.widget.Toast;
+import de.bjusystems.vdrmanager.R;
+import de.bjusystems.vdrmanager.gui.Utils;
+
+/**
+ * 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);
+
+ ExternalFileBackup externalFileBackup = new ExternalFileBackup(this);
+
+ // 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;
+ }
+ doStuff(externalFileBackup);
+
+ }
+
+ private void doStuff(ExternalFileBackup externalFileBackup) {
+ 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) {
+ Intent intent = IntentUtils.newIntent(this, RestoreActivity.class)
+ .putExtra(RestoreActivity.EXTRA_DATE,
+ backupDates[0].getTime());
+ startActivity(intent);
+ finish();
+ return;
+ }
+
+ Arrays.sort(backupDates, REVERSE_DATE_ORDER);
+ showDialog(DIALOG_CHOOSER_ID);
+ }
+
+ @Override
+ protected Dialog onCreateDialog(int id) {
+ if (id != DIALOG_CHOOSER_ID) {
+ return null;
+ }
+ String items[] = new String[backupDates.length];
+ for (int i = 0; i < backupDates.length; i++) {
+ items[i] = Utils.formatDateTime(this, backupDates[i].getTime());
+ }
+ return new AlertDialog.Builder(this)
+ .setCancelable(true)
+ .setItems(items, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ Intent intent = IntentUtils.newIntent(
+ RestoreChooserActivity.this,
+ RestoreActivity.class).putExtra(
+ RestoreActivity.EXTRA_DATE,
+ backupDates[which].getTime());
+ startActivity(intent);
+ finish();
+ }
+ }).setOnCancelListener(new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ finish();
+ }
+ }).setTitle(R.string.settings_backup_restore_select_title)
+ .create();
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/data/db/OrmDatabaseHelper.java b/vdrmanager/src/de/bjusystems/vdrmanager/data/db/OrmDatabaseHelper.java
index ab4a0ed..3feb8b0 100644
--- a/vdrmanager/src/de/bjusystems/vdrmanager/data/db/OrmDatabaseHelper.java
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/data/db/OrmDatabaseHelper.java
@@ -31,7 +31,7 @@ public class OrmDatabaseHelper extends OrmLiteSqliteOpenHelper {
public static final String TAG = OrmDatabaseHelper.class.getName();
// name of the database file for your application -- change to something
// appropriate for your app
- private static final String DATABASE_NAME = "vdrmanager.db";
+ public static final String DATABASE_NAME = "vdrmanager.db";
// any time you make changes to your database objects, you may have to
// increase the database version
private static final int DATABASE_VERSION = 2;
@@ -42,6 +42,10 @@ public class OrmDatabaseHelper extends OrmLiteSqliteOpenHelper {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
+
+ public static String getDataBaseFile(){
+ return "/data/data/de.bjusystems.vdrmanager/databases/" + DATABASE_NAME;
+ }
/**
* This is called when the database is first created. Usually you should
* call createTable statements here to create the tables that will store
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/gui/BaseActivity.java b/vdrmanager/src/de/bjusystems/vdrmanager/gui/BaseActivity.java
index 0257d16..466a31d 100644
--- a/vdrmanager/src/de/bjusystems/vdrmanager/gui/BaseActivity.java
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/gui/BaseActivity.java
@@ -3,6 +3,7 @@ package de.bjusystems.vdrmanager.gui;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Intent;
+import android.content.res.Configuration;
import android.os.Bundle;
import android.view.Gravity;
import android.view.Menu;
@@ -80,6 +81,11 @@ public abstract class BaseActivity<Result, T extends ListView> extends ICSBaseAc
}
@Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ Preferences.setLocale(this);
+ super.onConfigurationChanged(newConfig);
+ }
+ @Override
protected void onResume() {
Preferences.setLocale(this);
// Preferences.init(this);
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/gui/PreferencesActivity.java b/vdrmanager/src/de/bjusystems/vdrmanager/gui/PreferencesActivity.java
index 0015492..9555e8a 100644
--- a/vdrmanager/src/de/bjusystems/vdrmanager/gui/PreferencesActivity.java
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/gui/PreferencesActivity.java
@@ -11,6 +11,7 @@ import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceManager;
import de.bjusystems.vdrmanager.R;
import de.bjusystems.vdrmanager.app.VdrManagerApp;
+import de.bjusystems.vdrmanager.backup.BackupSettingsActivity;
import de.bjusystems.vdrmanager.data.Preferences;
public class PreferencesActivity extends BasePreferencesActivity implements
@@ -34,6 +35,18 @@ public class PreferencesActivity extends BasePreferencesActivity implements
Preferences.getPreferenceFile(this));
this.addPreferencesFromResource(R.xml.preferences);
+
+ Preference backupPreference = findPreference(getString(R.string.settings_backup_key));
+ backupPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ Intent intent = new Intent(PreferencesActivity.this, BackupSettingsActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(intent);
+ return true;
+ }
+ });
+
updateChildPreferences();
}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/gui/Utils.java b/vdrmanager/src/de/bjusystems/vdrmanager/gui/Utils.java
index e7832bb..50e472c 100644
--- a/vdrmanager/src/de/bjusystems/vdrmanager/gui/Utils.java
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/gui/Utils.java
@@ -20,6 +20,7 @@ import android.net.Uri;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextUtils;
+import android.text.format.DateUtils;
import android.text.style.ForegroundColorSpan;
import android.util.Log;
import android.util.Pair;
@@ -354,4 +355,17 @@ public class Utils {
t.setGravity(Gravity.CENTER, 0, 0);
t.show();
}
+
+ /**
+ * Formats the date and time based on user's phone date/time preferences.
+ *
+ * @param context the context
+ * @param time the time in milliseconds
+ */
+
+ public static String formatDateTime(Context context, long time) {
+ return android.text.format.DateFormat.getDateFormat(context).format(time) + " "
+ + DateUtils.formatDateTime(context, time, DateUtils.FORMAT_SHOW_TIME).toString();
+ }
+
}