Merge pull request #111 from andOTP/google-backups

Allow auto backups to Google sync
This commit is contained in:
Jakob Nixdorf 2018-02-21 15:32:14 +01:00 committed by GitHub
commit cbec5458da
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 126 additions and 11 deletions

View file

@ -6,7 +6,9 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="false"
android:allowBackup="true"
android:backupAgent=".Utilities.BackupAgent"
android:fullBackupOnly="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"

View file

@ -22,18 +22,26 @@
package org.shadowice.flocke.andotp.Activities;
import android.app.KeyguardManager;
import android.app.backup.BackupManager;
import android.app.backup.RestoreObserver;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceCategory;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.support.design.widget.Snackbar;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.view.ViewStub;
import android.widget.CheckBox;
import android.widget.Toast;
import org.openintents.openpgp.util.OpenPgpAppPreference;
@ -114,10 +122,24 @@ public class SettingsActivity extends BaseActivity
}
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
BackupManager backupManager = new BackupManager(this);
backupManager.dataChanged();
if (key.equals(getString(R.string.settings_key_theme)) ||
key.equals(getString(R.string.settings_key_locale)) ||
key.equals(getString(R.string.settings_key_special_features))) {
recreate();
}else if(key.equals(getString(R.string.settings_key_encryption))) {
if(settings.getEncryption() != EncryptionType.PASSWORD) {
boolean wasSyncEnabled = settings.getAndroidBackupServiceEnabled();
settings.setAndroidBackupServiceEnabled(false);
if(wasSyncEnabled) {
UIHelper.showGenericDialog(this,
R.string.settings_dialog_title_android_sync,
R.string.settings_dialog_msg_android_sync_disabled_encryption);
}
}
}
}
@ -207,7 +229,8 @@ public class SettingsActivity extends BaseActivity
}
}
public static class SettingsFragment extends PreferenceFragment {
public static class SettingsFragment extends PreferenceFragment
implements SharedPreferences.OnSharedPreferenceChangeListener{
PreferenceCategory catSecurity;
Settings settings;
@ -216,6 +239,13 @@ public class SettingsActivity extends BaseActivity
OpenPgpAppPreference pgpProvider;
OpenPgpKeyPreference pgpKey;
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
CheckBoxPreference useAndroidSync = (CheckBoxPreference) findPreference(getString(R.string.settings_key_enable_android_backup_service));
useAndroidSync.setEnabled(settings.getEncryption() == EncryptionType.PASSWORD);
if(!useAndroidSync.isEnabled())
useAndroidSync.setChecked(false);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@ -223,6 +253,7 @@ public class SettingsActivity extends BaseActivity
settings = new Settings(getActivity());
final SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity().getBaseContext());
sharedPref.registerOnSharedPreferenceChangeListener(this);
addPreferencesFromResource(R.xml.preferences);
CredentialsPreference credentialsPreference = (CredentialsPreference) findPreference(getString(R.string.settings_key_auth));
@ -278,6 +309,8 @@ public class SettingsActivity extends BaseActivity
});
pgpKey.setDefaultUserId("Alice <alice@example.com>");
CheckBoxPreference useAndroidSync = (CheckBoxPreference) findPreference(getString(R.string.settings_key_enable_android_backup_service));
useAndroidSync.setEnabled(settings.getEncryption() == EncryptionType.PASSWORD);
if (sharedPref.contains(getString(R.string.settings_key_special_features)) &&
sharedPref.getBoolean(getString(R.string.settings_key_special_features), false)) {

View file

@ -0,0 +1,49 @@
package org.shadowice.flocke.andotp.Utilities;
import android.app.backup.BackupAgentHelper;
import android.app.backup.BackupDataInput;
import android.app.backup.BackupDataOutput;
import android.app.backup.FileBackupHelper;
import android.app.backup.SharedPreferencesBackupHelper;
import android.os.ParcelFileDescriptor;
import java.io.IOException;
public class BackupAgent extends BackupAgentHelper {
static final String PREFS_BACKUP_KEY = "prefs";
static final String FILES_BACKUP_KEY = "files";
// PreferenceManager.getDefaultSharedPreferencesName is only available in API > 24, this is its implementation
String getDefaultSharedPreferencesName() {
return getPackageName() + "_preferences";
}
@Override
public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState) throws IOException {
Settings settings = new Settings(this);
if(settings.getAndroidBackupServiceEnabled()) {
synchronized (DatabaseHelper.DatabaseFileLock) {
super.onBackup(oldState, data, newState);
}
}
}
@Override
public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) throws IOException {
synchronized (DatabaseHelper.DatabaseFileLock) {
super.onRestore(data, appVersionCode, newState);
}
}
@Override
public void onCreate() {
String prefs = getDefaultSharedPreferencesName();
SharedPreferencesBackupHelper sharedPreferencesBackupHelper = new SharedPreferencesBackupHelper(this, prefs);
addHelper(PREFS_BACKUP_KEY, sharedPreferencesBackupHelper);
FileBackupHelper fileBackupHelper = new FileBackupHelper(this, Constants.FILENAME_DATABASE, Constants.FILENAME_DATABASE_BACKUP);
addHelper(FILES_BACKUP_KEY, fileBackupHelper);
}
}

View file

@ -23,6 +23,7 @@
package org.shadowice.flocke.andotp.Utilities;
import android.app.backup.BackupManager;
import android.content.Context;
import android.widget.Toast;
@ -42,6 +43,8 @@ import javax.crypto.SecretKey;
public class DatabaseHelper {
static final Object DatabaseFileLock = new Object();
public static void wipeDatabase(Context context) {
File db = new File(context.getFilesDir() + "/" + Constants.FILENAME_DATABASE);
File dbBackup = new File(context.getFilesDir() + "/" + Constants.FILENAME_DATABASE_BACKUP);
@ -102,15 +105,19 @@ public class DatabaseHelper {
String jsonString = entriesToString(entries);
try {
synchronized (DatabaseHelper.DatabaseFileLock) {
byte[] data = EncryptionHelper.encrypt(encryptionKey, jsonString.getBytes());
FileHelper.writeBytesToFile(new File(context.getFilesDir() + "/" + Constants.FILENAME_DATABASE), data);
}
} catch (Exception error) {
error.printStackTrace();
return false;
}
BackupManager backupManager = new BackupManager(context);
backupManager.dataChanged();
return true;
}
@ -119,10 +126,12 @@ public class DatabaseHelper {
if (encryptionKey != null) {
try {
synchronized (DatabaseHelper.DatabaseFileLock) {
byte[] data = FileHelper.readFileToBytes(new File(context.getFilesDir() + "/" + Constants.FILENAME_DATABASE));
data = EncryptionHelper.decrypt(encryptionKey, data);
entries = stringToEntries(new String(data));
}
} catch (Exception error) {
error.printStackTrace();
}

View file

@ -469,6 +469,14 @@ public class Settings {
setBoolean(R.string.settings_key_last_used_dialog_shown, value);
}
public boolean getAndroidBackupServiceEnabled() {
return getBoolean(R.string.settings_key_enable_android_backup_service, false);
}
public void setAndroidBackupServiceEnabled(boolean value) {
setBoolean(R.string.settings_key_enable_android_backup_service, value);
}
public boolean getIsAppendingDateTimeToBackups() {
return getBoolean(R.string.settings_key_backup_append_date_time, false);
}

View file

@ -43,6 +43,7 @@
<string name="settings_key_tags_toggles" translatable="false">pref_tags_toggles</string>
<string name="settings_key_enable_screenshot" translatable="false">pref_enable_screenshot</string>
<string name="settings_key_enable_android_backup_service" translatable="false">pref_enable_android_backup_service</string>
<string name="settings_key_clear_keystore" translatable="false">pref_clear_keystore</string>
<string name="settings_key_last_used_dialog_shown" translatable="false">pref_last_used_dialog_shown</string>

View file

@ -35,6 +35,7 @@
<string name="settings_title_special_features">Enable special features</string>
<string name="settings_title_enable_screenshot">Enable screenshots</string>
<string name="settings_title_enable_android_backup_service">Enable android sync</string>
<string name="settings_title_clear_keystore">Clear KeyStore</string>
<!-- Descriptions -->
@ -64,6 +65,8 @@
<string name="settings_desc_special_features">Uncheck to disable the special features again</string>
<string name="settings_desc_enable_screenshot">Allow to take screenshots of the main screen
(disabled by default for security reasons)</string>
<string name="settings_desc_enable_android_backup_service">Enables andOTP to use android\'s
built in backup service to bacup keys and preferences</string>
<string name="settings_desc_clear_keystore">Delete the encryption key from the KeyStore</string>
<!-- Toasts -->
@ -91,6 +94,7 @@
<string name="settings_dialog_title_error">Error</string>
<string name="settings_dialog_title_clear_keystore">Clear the KeyStore?</string>
<string name="settings_dialog_title_android_sync">Android sync</string>
<string name="settings_dialog_msg_auth_invalid_with_encryption">You can only use Password or PIN as
long as the database encryption is set to \"Password / PIN\"!</string>
@ -110,6 +114,9 @@
your accounts. Make sure you have a backup!\n\n<b>Are you really sure you want to clear the
KeyStore?</b></string>
<string name="settings_dialog_msg_android_sync_disabled_encryption">Android sync can not be used with keystore
encryption, <b>you should perform a manual backup!</b></string>
<!-- List entries -->
<string-array name="settings_entries_auth">
<item>None</item>

View file

@ -104,6 +104,12 @@
<PreferenceCategory
android:title="@string/settings_category_title_backup">
<CheckBoxPreference
android:key="@string/settings_key_enable_android_backup_service"
android:title="@string/settings_title_enable_android_backup_service"
android:summary="@string/settings_desc_enable_android_backup_service"
android:defaultValue="false" />
<CheckBoxPreference
android:key="@string/settings_key_backup_append_date_time"
android:title="@string/settings_title_backup_append_date"