Broadcast backup improvements
* Add setting to enable backup types as discusses in #157 * Add different notification channels
This commit is contained in:
parent
8563679b17
commit
76edcb900a
11 changed files with 160 additions and 74 deletions
|
@ -60,6 +60,7 @@ import org.shadowice.flocke.andotp.R;
|
||||||
import org.shadowice.flocke.andotp.Utilities.Constants;
|
import org.shadowice.flocke.andotp.Utilities.Constants;
|
||||||
import org.shadowice.flocke.andotp.Utilities.EncryptionHelper;
|
import org.shadowice.flocke.andotp.Utilities.EncryptionHelper;
|
||||||
import org.shadowice.flocke.andotp.Utilities.KeyStoreHelper;
|
import org.shadowice.flocke.andotp.Utilities.KeyStoreHelper;
|
||||||
|
import org.shadowice.flocke.andotp.Utilities.NotificationHelper;
|
||||||
import org.shadowice.flocke.andotp.Utilities.TokenCalculator;
|
import org.shadowice.flocke.andotp.Utilities.TokenCalculator;
|
||||||
import org.shadowice.flocke.andotp.View.EntriesCardAdapter;
|
import org.shadowice.flocke.andotp.View.EntriesCardAdapter;
|
||||||
import org.shadowice.flocke.andotp.View.FloatingActionMenu;
|
import org.shadowice.flocke.andotp.View.FloatingActionMenu;
|
||||||
|
@ -222,6 +223,7 @@ public class MainActivity extends BaseActivity
|
||||||
ItemTouchHelper touchHelper = new ItemTouchHelper(touchHelperCallback);
|
ItemTouchHelper touchHelper = new ItemTouchHelper(touchHelperCallback);
|
||||||
touchHelper.attachToRecyclerView(recList);
|
touchHelper.attachToRecyclerView(recList);
|
||||||
|
|
||||||
|
NotificationHelper.initializeNotificationChannels(this);
|
||||||
restoreSortMode();
|
restoreSortMode();
|
||||||
|
|
||||||
float durationScale = android.provider.Settings.Global.getFloat(this.getContentResolver(), android.provider.Settings.Global.ANIMATOR_DURATION_SCALE, 0);
|
float durationScale = android.provider.Settings.Global.getFloat(this.getContentResolver(), android.provider.Settings.Global.ANIMATOR_DURATION_SCALE, 0);
|
||||||
|
|
|
@ -24,33 +24,28 @@
|
||||||
package org.shadowice.flocke.andotp.Receivers;
|
package org.shadowice.flocke.andotp.Receivers;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.app.NotificationChannel;
|
|
||||||
import android.app.NotificationManager;
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.os.Build;
|
|
||||||
import android.support.v4.app.NotificationCompat;
|
|
||||||
import android.support.v4.content.ContextCompat;
|
import android.support.v4.content.ContextCompat;
|
||||||
|
|
||||||
import org.shadowice.flocke.andotp.R;
|
import org.shadowice.flocke.andotp.R;
|
||||||
|
import org.shadowice.flocke.andotp.Utilities.Constants;
|
||||||
import org.shadowice.flocke.andotp.Utilities.NotificationHelper;
|
import org.shadowice.flocke.andotp.Utilities.NotificationHelper;
|
||||||
import org.shadowice.flocke.andotp.Utilities.Settings;
|
import org.shadowice.flocke.andotp.Utilities.Settings;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
import static android.content.Context.NOTIFICATION_SERVICE;
|
|
||||||
|
|
||||||
public abstract class BackupBroadcastReceiver extends BroadcastReceiver {
|
public abstract class BackupBroadcastReceiver extends BroadcastReceiver {
|
||||||
|
|
||||||
protected boolean canSaveBackup(Context context) {
|
protected boolean canSaveBackup(Context context) {
|
||||||
if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
||||||
NotificationHelper.notify(context, R.string.backup_receiver_title_backup_failed, R.string.backup_receiver_read_permission_failed);
|
NotificationHelper.notify(context, Constants.NotificationChannel.BACKUP_FAILED, R.string.backup_receiver_title_backup_failed, R.string.backup_receiver_read_permission_failed);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
||||||
NotificationHelper.notify(context, R.string.backup_receiver_title_backup_failed, R.string.backup_receiver_write_permission_failed);
|
NotificationHelper.notify(context, Constants.NotificationChannel.BACKUP_FAILED, R.string.backup_receiver_title_backup_failed, R.string.backup_receiver_write_permission_failed);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,48 +43,53 @@ import java.util.ArrayList;
|
||||||
|
|
||||||
import javax.crypto.SecretKey;
|
import javax.crypto.SecretKey;
|
||||||
|
|
||||||
|
// Use the following command to test in the dev version:
|
||||||
|
// adb shell am broadcast -a org.shadowice.flocke.andotp.broadcast.ENCRYPTED_BACKUP org.shadowice.flocke.andotp.dev
|
||||||
public class EncryptedBackupBroadcastReceiver extends BackupBroadcastReceiver {
|
public class EncryptedBackupBroadcastReceiver extends BackupBroadcastReceiver {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
if(!canSaveBackup(context))
|
|
||||||
return;
|
|
||||||
|
|
||||||
Settings settings = new Settings(context);
|
Settings settings = new Settings(context);
|
||||||
Uri savePath = Tools.buildUri(settings.getBackupDir(), FileHelper.backupFilename(context, Constants.BackupType.ENCRYPTED));
|
|
||||||
|
|
||||||
String password = settings.getBackupPasswordEnc();
|
if (settings.isEncryptedBackupBroadcastEnabled()) {
|
||||||
|
if (!canSaveBackup(context))
|
||||||
|
return;
|
||||||
|
|
||||||
if (password.isEmpty()) {
|
Uri savePath = Tools.buildUri(settings.getBackupDir(), FileHelper.backupFilename(context, Constants.BackupType.ENCRYPTED));
|
||||||
NotificationHelper.notify(context, R.string.backup_receiver_title_backup_failed, R.string.backup_toast_crypt_password_not_set);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SecretKey encryptionKey = null;
|
String password = settings.getBackupPasswordEnc();
|
||||||
|
|
||||||
if (settings.getEncryption() == Constants.EncryptionType.KEYSTORE) {
|
if (password.isEmpty()) {
|
||||||
encryptionKey = KeyStoreHelper.loadEncryptionKeyFromKeyStore(context, false);
|
NotificationHelper.notify(context, Constants.NotificationChannel.BACKUP_FAILED, R.string.backup_receiver_title_backup_failed, R.string.backup_toast_crypt_password_not_set);
|
||||||
} else {
|
return;
|
||||||
NotificationHelper.notify(context, R.string.backup_receiver_title_backup_failed, R.string.backup_receiver_custom_encryption_failed );
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Tools.isExternalStorageWritable()) {
|
SecretKey encryptionKey = null;
|
||||||
ArrayList<Entry> entries = DatabaseHelper.loadDatabase(context, encryptionKey);
|
|
||||||
String plain = DatabaseHelper.entriesToString(entries);
|
|
||||||
|
|
||||||
boolean success = true;
|
if (settings.getEncryption() == Constants.EncryptionType.KEYSTORE) {
|
||||||
|
encryptionKey = KeyStoreHelper.loadEncryptionKeyFromKeyStore(context, false);
|
||||||
|
} else {
|
||||||
|
NotificationHelper.notify(context, Constants.NotificationChannel.BACKUP_FAILED, R.string.backup_receiver_title_backup_failed, R.string.backup_receiver_custom_encryption_failed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
if (Tools.isExternalStorageWritable()) {
|
||||||
SecretKey key = EncryptionHelper.generateSymmetricKeyFromPassword(password);
|
ArrayList<Entry> entries = DatabaseHelper.loadDatabase(context, encryptionKey);
|
||||||
byte[] encrypted = EncryptionHelper.encrypt(key, plain.getBytes(StandardCharsets.UTF_8));
|
String plain = DatabaseHelper.entriesToString(entries);
|
||||||
FileHelper.writeBytesToFile(context, savePath, encrypted);
|
|
||||||
NotificationHelper.notify(context, R.string.backup_receiver_title_backup_success, savePath.getPath());
|
try {
|
||||||
} catch (Exception e) {
|
SecretKey key = EncryptionHelper.generateSymmetricKeyFromPassword(password);
|
||||||
e.printStackTrace();
|
byte[] encrypted = EncryptionHelper.encrypt(key, plain.getBytes(StandardCharsets.UTF_8));
|
||||||
NotificationHelper.notify(context, R.string.backup_receiver_title_backup_failed, R.string.backup_toast_export_failed);
|
FileHelper.writeBytesToFile(context, savePath, encrypted);
|
||||||
|
NotificationHelper.notify(context, Constants.NotificationChannel.BACKUP_SUCCESS, R.string.backup_receiver_title_backup_success, savePath.getPath());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
NotificationHelper.notify(context, Constants.NotificationChannel.BACKUP_FAILED, R.string.backup_receiver_title_backup_failed, R.string.backup_toast_export_failed);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
NotificationHelper.notify(context, Constants.NotificationChannel.BACKUP_FAILED, R.string.backup_receiver_title_backup_failed, R.string.backup_toast_storage_not_accessible);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
NotificationHelper.notify(context, R.string.backup_receiver_title_backup_failed, R.string.backup_toast_storage_not_accessible);
|
NotificationHelper.notify(context, Constants.NotificationChannel.BACKUP_FAILED, R.string.backup_receiver_title_backup_failed, R.string.backup_receiver_encrypted_disabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,38 +41,41 @@ import java.util.ArrayList;
|
||||||
|
|
||||||
import javax.crypto.SecretKey;
|
import javax.crypto.SecretKey;
|
||||||
|
|
||||||
//Test with: adb shell am broadcast -n org.shadowice.flocke.andotp/.Receivers.PlainTextBackupBroadcastReceiver
|
// Use the following command to test in the dev version:
|
||||||
|
// adb shell am broadcast -a org.shadowice.flocke.andotp.broadcast.PLAIN_TEXT_BACKUP org.shadowice.flocke.andotp.dev
|
||||||
public class PlainTextBackupBroadcastReceiver extends BackupBroadcastReceiver {
|
public class PlainTextBackupBroadcastReceiver extends BackupBroadcastReceiver {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
NotificationHelper.notify(context, R.string.backup_receiver_title_backup_failed, R.string.backup_receiver_disabled);
|
|
||||||
|
|
||||||
/*if(!canSaveBackup(context))
|
|
||||||
return;
|
|
||||||
|
|
||||||
Settings settings = new Settings(context);
|
Settings settings = new Settings(context);
|
||||||
|
|
||||||
Uri savePath = Tools.buildUri(settings.getBackupDir(), FileHelper.backupFilename(context, Constants.BackupType.PLAIN_TEXT));
|
if (settings.isPlainTextBackupBroadcastEnabled()) {
|
||||||
|
if (!canSaveBackup(context))
|
||||||
|
return;
|
||||||
|
|
||||||
SecretKey encryptionKey = null;
|
Uri savePath = Tools.buildUri(settings.getBackupDir(), FileHelper.backupFilename(context, Constants.BackupType.PLAIN_TEXT));
|
||||||
|
|
||||||
if (settings.getEncryption() == Constants.EncryptionType.KEYSTORE) {
|
SecretKey encryptionKey = null;
|
||||||
encryptionKey = KeyStoreHelper.loadEncryptionKeyFromKeyStore(context, false);
|
|
||||||
} else {
|
|
||||||
NotificationHelper.notify(context, R.string.backup_receiver_title_backup_failed, R.string.backup_receiver_custom_encryption_failed);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Tools.isExternalStorageWritable()) {
|
if (settings.getEncryption() == Constants.EncryptionType.KEYSTORE) {
|
||||||
ArrayList<Entry> entries = DatabaseHelper.loadDatabase(context, encryptionKey);
|
encryptionKey = KeyStoreHelper.loadEncryptionKeyFromKeyStore(context, false);
|
||||||
|
|
||||||
if (FileHelper.writeStringToFile(context, savePath, DatabaseHelper.entriesToString(entries))) {
|
|
||||||
NotificationHelper.notify(context, R.string.backup_receiver_title_backup_success, savePath.getPath());
|
|
||||||
} else {
|
} else {
|
||||||
NotificationHelper.notify(context, R.string.backup_receiver_title_backup_failed, R.string.backup_toast_export_failed);
|
NotificationHelper.notify(context, Constants.NotificationChannel.BACKUP_FAILED, R.string.backup_receiver_title_backup_failed, R.string.backup_receiver_custom_encryption_failed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Tools.isExternalStorageWritable()) {
|
||||||
|
ArrayList<Entry> entries = DatabaseHelper.loadDatabase(context, encryptionKey);
|
||||||
|
|
||||||
|
if (FileHelper.writeStringToFile(context, savePath, DatabaseHelper.entriesToString(entries))) {
|
||||||
|
NotificationHelper.notify(context, Constants.NotificationChannel.BACKUP_SUCCESS, R.string.backup_receiver_title_backup_success, savePath.getPath());
|
||||||
|
} else {
|
||||||
|
NotificationHelper.notify(context, Constants.NotificationChannel.BACKUP_FAILED, R.string.backup_receiver_title_backup_failed, R.string.backup_toast_export_failed);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
NotificationHelper.notify(context, Constants.NotificationChannel.BACKUP_FAILED, R.string.backup_receiver_title_backup_failed, R.string.backup_toast_storage_not_accessible);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
NotificationHelper.notify(context, R.string.backup_receiver_title_backup_failed, R.string.backup_toast_storage_not_accessible);
|
NotificationHelper.notify(context, Constants.NotificationChannel.BACKUP_FAILED, R.string.backup_receiver_title_backup_failed, R.string.backup_receiver_plain_disabled);
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,10 @@ public class Constants {
|
||||||
OR, AND, SINGLE
|
OR, AND, SINGLE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum NotificationChannel {
|
||||||
|
BACKUP_FAILED, BACKUP_SUCCESS
|
||||||
|
}
|
||||||
|
|
||||||
// Intents (Format: A0x with A = parent Activity, x = number of the intent)
|
// Intents (Format: A0x with A = parent Activity, x = number of the intent)
|
||||||
public final static int INTENT_MAIN_AUTHENTICATE = 100;
|
public final static int INTENT_MAIN_AUTHENTICATE = 100;
|
||||||
public final static int INTENT_MAIN_SETTINGS = 101;
|
public final static int INTENT_MAIN_SETTINGS = 101;
|
||||||
|
|
|
@ -34,31 +34,63 @@ import org.shadowice.flocke.andotp.R;
|
||||||
import static android.content.Context.NOTIFICATION_SERVICE;
|
import static android.content.Context.NOTIFICATION_SERVICE;
|
||||||
|
|
||||||
public class NotificationHelper {
|
public class NotificationHelper {
|
||||||
public static void notify(Context context, int resIdTitle, int resIdBody) {
|
private static String channelId(Constants.NotificationChannel channel) {
|
||||||
notify(context, resIdTitle, context.getText(resIdBody).toString());
|
return "andOTP_" + channel.name().toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void notify(Context context, int resIdTitle, String resBody) {
|
private static void createNotificationChannel(Context context, Constants.NotificationChannel channel) {
|
||||||
String channelId = "andOTP_channel";
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
NotificationChannel channel = null;
|
NotificationChannel notificationChannel = new NotificationChannel(channelId(channel), context.getString(R.string.app_name), NotificationManager.IMPORTANCE_DEFAULT);
|
||||||
|
|
||||||
|
switch(channel) {
|
||||||
|
case BACKUP_FAILED:
|
||||||
|
notificationChannel.setName(context.getString(R.string.notification_channel_name_backup_failed));
|
||||||
|
notificationChannel.setDescription(context.getString(R.string.notification_channel_desc_backup_failed));
|
||||||
|
notificationChannel.setImportance(NotificationManager.IMPORTANCE_HIGH);
|
||||||
|
break;
|
||||||
|
case BACKUP_SUCCESS:
|
||||||
|
notificationChannel.setName(context.getString(R.string.notification_channel_name_backup_success));
|
||||||
|
notificationChannel.setDescription(context.getString(R.string.notification_channel_desc_backup_success));
|
||||||
|
notificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
NotificationManager notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
|
||||||
|
notificationManager.createNotificationChannel(notificationChannel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void initializeNotificationChannels(Context context) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
for (Constants.NotificationChannel channel : Constants.NotificationChannel.values()) {
|
||||||
|
NotificationHelper.createNotificationChannel(context, channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void notify(Context context, Constants.NotificationChannel channel, int resIdTitle, int resIdBody) {
|
||||||
|
notify(context, channel, resIdTitle, context.getText(resIdBody).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void notify(Context context, Constants.NotificationChannel channel , int resIdTitle, String resBody) {
|
||||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, null)
|
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, null)
|
||||||
.setSmallIcon(R.mipmap.ic_launcher)
|
.setSmallIcon(R.mipmap.ic_launcher)
|
||||||
.setContentTitle(context.getText(resIdTitle))
|
.setContentTitle(context.getText(resIdTitle))
|
||||||
.setContentText(resBody);
|
.setStyle(new NotificationCompat.BigTextStyle()
|
||||||
|
.bigText(resBody));
|
||||||
|
|
||||||
NotificationManager notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
channel = new NotificationChannel(channelId, context.getString(R.string.app_name), NotificationManager.IMPORTANCE_HIGH);
|
|
||||||
notificationManager.createNotificationChannel(channel);
|
|
||||||
} else {
|
|
||||||
builder.setPriority(NotificationCompat.PRIORITY_HIGH);
|
builder.setPriority(NotificationCompat.PRIORITY_HIGH);
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.setChannelId(channelId);
|
createNotificationChannel(context, channel);
|
||||||
|
builder.setChannelId(channelId(channel));
|
||||||
|
|
||||||
int notificationId = 1;
|
int notificationId = 1;
|
||||||
|
|
||||||
|
NotificationManager notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
|
||||||
notificationManager.notify(notificationId, builder.build());
|
notificationManager.notify(notificationId, builder.build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -391,6 +391,18 @@ public class Settings {
|
||||||
return password;
|
return password;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Set<String> getBackupBroadcasts() {
|
||||||
|
return settings.getStringSet(getResString(R.string.settings_key_backup_broadcasts), Collections.<String>emptySet());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPlainTextBackupBroadcastEnabled() {
|
||||||
|
return getBackupBroadcasts().contains("plain");
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEncryptedBackupBroadcastEnabled() {
|
||||||
|
return getBackupBroadcasts().contains("encrypted");
|
||||||
|
}
|
||||||
|
|
||||||
public String getOpenPGPProvider() {
|
public String getOpenPGPProvider() {
|
||||||
return getString(R.string.settings_key_openpgp_provider, "");
|
return getString(R.string.settings_key_openpgp_provider, "");
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
<string name="settings_key_backup_directory" translatable="false">pref_backup_directory</string>
|
<string name="settings_key_backup_directory" translatable="false">pref_backup_directory</string>
|
||||||
<string name="settings_key_backup_password" translatable="false">pref_backup_password</string> <!-- Deprecated -->
|
<string name="settings_key_backup_password" translatable="false">pref_backup_password</string> <!-- Deprecated -->
|
||||||
<string name="settings_key_backup_password_enc" translatable="false">pref_backup_password_enc</string>
|
<string name="settings_key_backup_password_enc" translatable="false">pref_backup_password_enc</string>
|
||||||
|
<string name="settings_key_backup_broadcasts" translatable="false">pref_backup_broadcasts</string>
|
||||||
<string name="settings_key_openpgp_provider" translatable="false">pref_openpgp_provider</string>
|
<string name="settings_key_openpgp_provider" translatable="false">pref_openpgp_provider</string>
|
||||||
<string name="settings_key_openpgp_keyid" translatable="false">pref_openpgp_keyid</string>
|
<string name="settings_key_openpgp_keyid" translatable="false">pref_openpgp_keyid</string>
|
||||||
<string name="settings_key_openpgp_sign" translatable="false">pref_openpgp_sign</string>
|
<string name="settings_key_openpgp_sign" translatable="false">pref_openpgp_sign</string>
|
||||||
|
@ -123,6 +124,11 @@
|
||||||
<item>single</item>
|
<item>single</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="settings_values_backup_broadcasts" translatable="false">
|
||||||
|
<item>plain</item>
|
||||||
|
<item>encrypted</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
<string-array name="settings_entries_lang" translatable="false">
|
<string-array name="settings_entries_lang" translatable="false">
|
||||||
<item>@string/settings_lang_sys_default</item>
|
<item>@string/settings_lang_sys_default</item>
|
||||||
<item>Català</item>
|
<item>Català</item>
|
||||||
|
|
|
@ -48,8 +48,10 @@
|
||||||
<string name="backup_receiver_title_backup_failed">Backup failed</string>
|
<string name="backup_receiver_title_backup_failed">Backup failed</string>
|
||||||
<string name="backup_receiver_title_backup_success">Backup successful</string>
|
<string name="backup_receiver_title_backup_success">Backup successful</string>
|
||||||
|
|
||||||
<string name="backup_receiver_disabled">Plain text backups are temporary disabled for security
|
<string name="backup_receiver_plain_disabled">Plain-text backups are currently not allowed,
|
||||||
reasons. Please wait for the next release.</string>
|
please go to the Settings to enable them</string>
|
||||||
|
<string name="backup_receiver_encrypted_disabled">Encrypted backups are currently not allowed,
|
||||||
|
please go to the Settings to enable them</string>
|
||||||
|
|
||||||
<string name="backup_receiver_read_permission_failed">Read permission not granted, please do
|
<string name="backup_receiver_read_permission_failed">Read permission not granted, please do
|
||||||
this before attempting backup</string>
|
this before attempting backup</string>
|
||||||
|
@ -58,6 +60,14 @@
|
||||||
<string name="backup_receiver_custom_encryption_failed">Password/PIN based encryption not
|
<string name="backup_receiver_custom_encryption_failed">Password/PIN based encryption not
|
||||||
supported with broadcast backup</string>
|
supported with broadcast backup</string>
|
||||||
|
|
||||||
|
<!-- Notification channels -->
|
||||||
|
<string name="notification_channel_name_backup_failed">Automatic backup failed</string>
|
||||||
|
<string name="notification_channel_name_backup_success">Automatic backup successful</string>
|
||||||
|
|
||||||
|
<string name="notification_channel_desc_backup_failed">These notifications are shown when an
|
||||||
|
automatic backup has failed for some reason</string>
|
||||||
|
<string name="notification_channel_desc_backup_success">These notifications are shown when an
|
||||||
|
automatic backup was successful</string>
|
||||||
|
|
||||||
<!-- Toast messages -->
|
<!-- Toast messages -->
|
||||||
<string name="backup_toast_mkdir_failed">Failed to create backup directory</string>
|
<string name="backup_toast_mkdir_failed">Failed to create backup directory</string>
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
<string name="settings_title_backup_ask">Ask for filename</string>
|
<string name="settings_title_backup_ask">Ask for filename</string>
|
||||||
<string name="settings_title_backup_directory">Backup directory</string>
|
<string name="settings_title_backup_directory">Backup directory</string>
|
||||||
<string name="settings_title_backup_password">Backup password</string>
|
<string name="settings_title_backup_password">Backup password</string>
|
||||||
|
<string name="settings_title_backup_broadcasts">Backup Broadcasts</string>
|
||||||
<string name="settings_title_openpgp_provider">Select OpenPGP provider</string>
|
<string name="settings_title_openpgp_provider">Select OpenPGP provider</string>
|
||||||
<string name="settings_title_openpgp_keyid">Select OpenPGP key</string>
|
<string name="settings_title_openpgp_keyid">Select OpenPGP key</string>
|
||||||
<string name="settings_title_openpgp_sign">Sign encrypted backups</string>
|
<string name="settings_title_openpgp_sign">Sign encrypted backups</string>
|
||||||
|
@ -57,6 +58,9 @@
|
||||||
<string name="settings_desc_backup_password">Set the password that is used to encrypt the
|
<string name="settings_desc_backup_password">Set the password that is used to encrypt the
|
||||||
backups</string>
|
backups</string>
|
||||||
|
|
||||||
|
<string name="settings_desc_backup_broadcasts">Select which backup types can be triggered by
|
||||||
|
3rd-party apps using Broadcasts</string>
|
||||||
|
|
||||||
<string name="settings_desc_openpgp_sign">Every encrypted backup is additionally signed with
|
<string name="settings_desc_openpgp_sign">Every encrypted backup is additionally signed with
|
||||||
your key (requires password)</string>
|
your key (requires password)</string>
|
||||||
<string name="settings_desc_openpgp_verify">Encrypted backups are only imported if they are
|
<string name="settings_desc_openpgp_verify">Encrypted backups are only imported if they are
|
||||||
|
@ -166,6 +170,11 @@
|
||||||
<item>Switch between tags (only allow one tag to be selected at a time)</item>
|
<item>Switch between tags (only allow one tag to be selected at a time)</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="settings_entries_backup_broadcasts">
|
||||||
|
<item>Plain-text backups</item>
|
||||||
|
<item>Encrypted backups</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
<!-- Special -->
|
<!-- Special -->
|
||||||
<string name="settings_lang_sys_default">System default</string>
|
<string name="settings_lang_sys_default">System default</string>
|
||||||
|
|
||||||
|
|
|
@ -134,6 +134,14 @@
|
||||||
android:title="@string/settings_title_backup_password"
|
android:title="@string/settings_title_backup_password"
|
||||||
android:summary="@string/settings_desc_backup_password" />
|
android:summary="@string/settings_desc_backup_password" />
|
||||||
|
|
||||||
|
<MultiSelectListPreference
|
||||||
|
android:key="@string/settings_key_backup_broadcasts"
|
||||||
|
android:title="@string/settings_title_backup_broadcasts"
|
||||||
|
android:summary="@string/settings_desc_backup_broadcasts"
|
||||||
|
android:entries="@array/settings_entries_backup_broadcasts"
|
||||||
|
android:entryValues="@array/settings_values_backup_broadcasts"
|
||||||
|
android:defaultValue="@array/settings_empty_array" />
|
||||||
|
|
||||||
<org.openintents.openpgp.util.OpenPgpAppPreference
|
<org.openintents.openpgp.util.OpenPgpAppPreference
|
||||||
android:key="@string/settings_key_openpgp_provider"
|
android:key="@string/settings_key_openpgp_provider"
|
||||||
android:title="@string/settings_title_openpgp_provider" />
|
android:title="@string/settings_title_openpgp_provider" />
|
||||||
|
|
Loading…
Reference in a new issue