mirror of
https://github.com/ArcaneChat/android.git
synced 2026-07-03 14:05:24 +02:00
add backup functionality
This commit is contained in:
@@ -1128,6 +1128,8 @@
|
||||
<string name="preferences__read_receipts">Read receipts</string>
|
||||
<string name="preferences__if_read_receipts_are_disabled_you_wont_be_able_to_see_read_receipts">If read receipts are disabled, you won\'t be able to see read receipts from others.</string>
|
||||
<string name="preferences__request_keyboard_to_disable_personalized_learning">Request keyboard to disable personalized learning</string>
|
||||
<string name="preferences__backup">Backup</string>
|
||||
<string name="preferences__manage_keys">Manage keys</string>
|
||||
<string name="preferences_app_protection__blocked_contacts">Blocked contacts</string>
|
||||
<string name="preferences_chats__when_using_mobile_data">When using mobile data</string>
|
||||
<string name="preferences_chats__when_using_wifi">When using Wi-Fi</string>
|
||||
@@ -1152,6 +1154,19 @@
|
||||
<string name="preferences_chats__message_text_size">Message font size</string>
|
||||
<string name="preferences_events__contact_joined_signal">Contact joined Delta Chat</string>
|
||||
<string name="preferences_notifications__priority">Priority</string>
|
||||
<string name="preferences_backup__export_explain">A backup helps you to set up a new installation on this or on another device.\n\nThe backup will contain all messages, contacts and chats and your end-to-end Autocrypt setup. Keep the backup file in a safe place or delete it as soon as possible.</string>
|
||||
<string name="preferences_backup__export_start_button">Start backup</string>
|
||||
<string name="preferences_backup__backup_written_to_x">Backup written successfully to %1$s</string>
|
||||
<string name="preferences_backup__ask_for_storage_permission">Delta Chat needs access to your files in order to create backups.</string>
|
||||
<string name="preferences_managekeys__menu_title">Manage keys</string>
|
||||
<string name="preferences_managekeys__ask_for_storage_permission">Delta Chat needs access to your files to import/export keys.</string>
|
||||
<string name="preferences_managekeys__export_secret_keys">Export secret keys</string>
|
||||
<string name="preferences_managekeys__export_explain">Export secret keys to \"%1$s\"?</string>
|
||||
<string name="preferences_managekeys__import_secret_keys">Import secret keys</string>
|
||||
<string name="preferences_managekeys__import_explain">Import secret keys from \"%1$s\"?\n\n• Existing secret keys will not be deleted\n\n• The last imported key will be used as the new default key unless it has the word \"legacy\" in its filename</string>
|
||||
<string name="preferences_managekeys__secret_keys_exported_to_x">Secret keys written successfully to \"%1$s\".</string>
|
||||
<string name="preferences_managekeys__secret_keys_imported_from_x">Secret keys imported from \"%1$s\".</string>
|
||||
|
||||
|
||||
<!-- **************************************** -->
|
||||
<!-- menus -->
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<org.thoughtcrime.securesms.components.SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="pref_toggle_push_messaging"
|
||||
android:title="@string/preferences__signal_messages_and_calls"
|
||||
android:summary="@string/preferences__free_private_messages_and_calls"/>
|
||||
<Preference android:key="pref_backup"
|
||||
android:title="@string/preferences__backup"/>
|
||||
|
||||
<Preference android:key="pref_choose_identity"
|
||||
android:title="@string/preferences__choose_identity"
|
||||
android:summary="@string/preferences__choose_your_contact_entry_from_the_contacts_list"/>
|
||||
<Preference android:key="pref_manage_keys"
|
||||
android:title="@string/preferences__manage_keys"/>
|
||||
|
||||
<Preference android:key="pref_submit_debug_logs"
|
||||
android:title="@string/preferences__submit_debug_log"/>
|
||||
|
||||
@@ -1,58 +1,66 @@
|
||||
package org.thoughtcrime.securesms.preferences;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.Manifest;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.provider.ContactsContract;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.preference.CheckBoxPreference;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.android.gms.gcm.GoogleCloudMessaging;
|
||||
import com.b44t.messenger.DcContext;
|
||||
import com.b44t.messenger.DcEventCenter;
|
||||
|
||||
import org.thoughtcrime.securesms.ApplicationPreferencesActivity;
|
||||
import org.thoughtcrime.securesms.LogSubmitActivity;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.RegistrationActivity;
|
||||
import org.thoughtcrime.securesms.contacts.ContactAccessor;
|
||||
import org.thoughtcrime.securesms.contacts.ContactIdentityManager;
|
||||
import org.thoughtcrime.securesms.push.AccountManagerFactory;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.task.ProgressDialogAsyncTask;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException;
|
||||
import org.thoughtcrime.securesms.connect.ApplicationDcContext;
|
||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.File;
|
||||
|
||||
public class AdvancedPreferenceFragment extends CorrectedPreferenceFragment {
|
||||
|
||||
public class AdvancedPreferenceFragment extends CorrectedPreferenceFragment
|
||||
implements DcEventCenter.DcEventDelegate
|
||||
{
|
||||
private static final String TAG = AdvancedPreferenceFragment.class.getSimpleName();
|
||||
|
||||
private static final String PUSH_MESSAGING_PREF = "pref_toggle_push_messaging";
|
||||
private static final String BACKUP_PREF = "pref_backup";
|
||||
private static final String MANAGE_KEYS_PREF = "pref_manage_keys";
|
||||
private static final String SUBMIT_DEBUG_LOG_PREF = "pref_submit_debug_logs";
|
||||
|
||||
private static final int PICK_IDENTITY_CONTACT = 1;
|
||||
private ApplicationDcContext dcContext;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle paramBundle) {
|
||||
super.onCreate(paramBundle);
|
||||
|
||||
initializeIdentitySelection();
|
||||
dcContext = DcHelper.getContext(getContext());
|
||||
dcContext.eventCenter.addObserver(this, DcContext.DC_EVENT_IMEX_PROGRESS);
|
||||
|
||||
Preference backup = this.findPreference(BACKUP_PREF);
|
||||
backup.setOnPreferenceClickListener(new BackupListener());
|
||||
|
||||
Preference manageKeys = this.findPreference(MANAGE_KEYS_PREF);
|
||||
manageKeys.setOnPreferenceClickListener(new ManageKeysListener());
|
||||
|
||||
Preference submitDebugLog = this.findPreference(SUBMIT_DEBUG_LOG_PREF);
|
||||
submitDebugLog.setOnPreferenceClickListener(new SubmitDebugLogListener());
|
||||
submitDebugLog.setSummary(getVersion(getActivity()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
dcContext.eventCenter.removeObservers(this);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(@Nullable Bundle savedInstanceState, String rootKey) {
|
||||
addPreferencesFromResource(R.xml.preferences_advanced);
|
||||
@@ -63,51 +71,6 @@ public class AdvancedPreferenceFragment extends CorrectedPreferenceFragment {
|
||||
super.onResume();
|
||||
((ApplicationPreferencesActivity) getActivity()).getSupportActionBar().setTitle(R.string.preferences__advanced);
|
||||
|
||||
initializePushMessagingToggle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int reqCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(reqCode, resultCode, data);
|
||||
|
||||
Log.w(TAG, "Got result: " + resultCode + " for req: " + reqCode);
|
||||
if (resultCode == Activity.RESULT_OK && reqCode == PICK_IDENTITY_CONTACT) {
|
||||
handleIdentitySelection(data);
|
||||
}
|
||||
}
|
||||
|
||||
private void initializePushMessagingToggle() {
|
||||
CheckBoxPreference preference = (CheckBoxPreference)this.findPreference(PUSH_MESSAGING_PREF);
|
||||
|
||||
if (TextSecurePreferences.isPushRegistered(getActivity())) {
|
||||
preference.setChecked(true);
|
||||
preference.setSummary(TextSecurePreferences.getLocalNumber(getActivity()));
|
||||
} else {
|
||||
preference.setChecked(false);
|
||||
preference.setSummary(R.string.preferences__free_private_messages_and_calls);
|
||||
}
|
||||
|
||||
preference.setOnPreferenceChangeListener(new PushMessagingClickListener());
|
||||
}
|
||||
|
||||
private void initializeIdentitySelection() {
|
||||
ContactIdentityManager identity = ContactIdentityManager.getInstance(getActivity());
|
||||
|
||||
Preference preference = this.findPreference(TextSecurePreferences.IDENTITY_PREF);
|
||||
|
||||
if (identity.isSelfIdentityAutoDetected()) {
|
||||
this.getPreferenceScreen().removePreference(preference);
|
||||
} else {
|
||||
Uri contactUri = identity.getSelfIdentityUri();
|
||||
|
||||
if (contactUri != null) {
|
||||
String contactName = ContactAccessor.getInstance().getNameFromContact(getActivity(), contactUri);
|
||||
preference.setSummary(String.format(getString(R.string.ApplicationPreferencesActivity_currently_s),
|
||||
contactName));
|
||||
}
|
||||
|
||||
preference.setOnPreferenceClickListener(new IdentityPreferenceClickListener());
|
||||
}
|
||||
}
|
||||
|
||||
private @NonNull String getVersion(@Nullable Context context) {
|
||||
@@ -124,25 +87,6 @@ public class AdvancedPreferenceFragment extends CorrectedPreferenceFragment {
|
||||
}
|
||||
}
|
||||
|
||||
private class IdentityPreferenceClickListener implements Preference.OnPreferenceClickListener {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
Intent intent = new Intent(Intent.ACTION_PICK);
|
||||
intent.setType(ContactsContract.Contacts.CONTENT_TYPE);
|
||||
startActivityForResult(intent, PICK_IDENTITY_CONTACT);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private void handleIdentitySelection(Intent data) {
|
||||
Uri contactUri = data.getData();
|
||||
|
||||
if (contactUri != null) {
|
||||
TextSecurePreferences.setIdentityContactUri(getActivity(), contactUri.toString());
|
||||
initializeIdentitySelection();
|
||||
}
|
||||
}
|
||||
|
||||
private class SubmitDebugLogListener implements Preference.OnPreferenceClickListener {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
@@ -152,83 +96,132 @@ public class AdvancedPreferenceFragment extends CorrectedPreferenceFragment {
|
||||
}
|
||||
}
|
||||
|
||||
private class PushMessagingClickListener implements Preference.OnPreferenceChangeListener {
|
||||
private static final int SUCCESS = 0;
|
||||
private static final int NETWORK_ERROR = 1;
|
||||
|
||||
private class DisablePushMessagesTask extends ProgressDialogAsyncTask<Void, Void, Integer> {
|
||||
private final CheckBoxPreference checkBoxPreference;
|
||||
|
||||
public DisablePushMessagesTask(final CheckBoxPreference checkBoxPreference) {
|
||||
super(getActivity(), R.string.ApplicationPreferencesActivity_unregistering, R.string.ApplicationPreferencesActivity_unregistering_from_signal_messages_and_calls);
|
||||
this.checkBoxPreference = checkBoxPreference;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Integer result) {
|
||||
super.onPostExecute(result);
|
||||
switch (result) {
|
||||
case NETWORK_ERROR:
|
||||
Toast.makeText(getActivity(),
|
||||
R.string.ApplicationPreferencesActivity_error_connecting_to_server,
|
||||
Toast.LENGTH_LONG).show();
|
||||
break;
|
||||
case SUCCESS:
|
||||
TextSecurePreferences.setPushRegistered(getActivity(), false);
|
||||
initializePushMessagingToggle();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Integer doInBackground(Void... params) {
|
||||
try {
|
||||
Context context = getActivity();
|
||||
SignalServiceAccountManager accountManager = AccountManagerFactory.createManager(context);
|
||||
|
||||
try {
|
||||
accountManager.setGcmId(Optional.<String>absent());
|
||||
} catch (AuthorizationFailedException e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
|
||||
if (!TextSecurePreferences.isGcmDisabled(context)) {
|
||||
GoogleCloudMessaging.getInstance(context).unregister();
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
} catch (IOException ioe) {
|
||||
Log.w(TAG, ioe);
|
||||
return NETWORK_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
/***********************************************************************************************
|
||||
* Import/Export
|
||||
**********************************************************************************************/
|
||||
|
||||
private class BackupListener implements Preference.OnPreferenceClickListener {
|
||||
@Override
|
||||
public boolean onPreferenceChange(final Preference preference, Object newValue) {
|
||||
if (((CheckBoxPreference)preference).isChecked()) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
builder.setIconAttribute(R.attr.dialog_info_icon);
|
||||
builder.setTitle(R.string.ApplicationPreferencesActivity_disable_signal_messages_and_calls);
|
||||
builder.setMessage(R.string.ApplicationPreferencesActivity_disable_signal_messages_and_calls_by_unregistering);
|
||||
builder.setNegativeButton(android.R.string.cancel, null);
|
||||
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
new DisablePushMessagesTask((CheckBoxPreference)preference).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
});
|
||||
builder.show();
|
||||
} else {
|
||||
Intent nextIntent = new Intent(getActivity(), ApplicationPreferencesActivity.class);
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
Permissions.with(getActivity())
|
||||
.request(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
.ifNecessary()
|
||||
.withRationaleDialog(getActivity().getString(R.string.preferences_backup__ask_for_storage_permission), R.drawable.ic_folder_white_48dp)
|
||||
.onAllGranted(() -> {
|
||||
new AlertDialog.Builder(getActivity())
|
||||
.setTitle(R.string.preferences__backup)
|
||||
.setMessage(R.string.preferences_backup__export_explain)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setPositiveButton(R.string.preferences_backup__export_start_button, (dialogInterface, i) -> startImex(DcContext.DC_IMEX_EXPORT_BACKUP))
|
||||
.show();
|
||||
})
|
||||
.execute();
|
||||
|
||||
Intent intent = new Intent(getActivity(), RegistrationActivity.class);
|
||||
intent.putExtra(RegistrationActivity.RE_REGISTRATION_EXTRA, true);
|
||||
intent.putExtra("next_intent", nextIntent);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private class ManageKeysListener implements Preference.OnPreferenceClickListener {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
Permissions.with(getActivity())
|
||||
.request(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
.ifNecessary()
|
||||
.withRationaleDialog(getActivity().getString(R.string.preferences_managekeys__ask_for_storage_permission), R.drawable.ic_folder_white_48dp)
|
||||
.onAllGranted(() -> {
|
||||
new android.app.AlertDialog.Builder(getActivity())
|
||||
.setTitle(R.string.preferences_managekeys__menu_title)
|
||||
.setItems(new CharSequence[]{
|
||||
getActivity().getString(R.string.preferences_managekeys__export_secret_keys),
|
||||
getActivity().getString(R.string.preferences_managekeys__import_secret_keys)
|
||||
},
|
||||
(dialogInterface, i) -> {
|
||||
if (i==0) {
|
||||
new AlertDialog.Builder(getActivity())
|
||||
.setTitle(R.string.preferences_managekeys__export_secret_keys)
|
||||
.setMessage(getActivity().getString(R.string.preferences_managekeys__export_explain, dcContext.getImexDir().getAbsolutePath()))
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setPositiveButton(android.R.string.ok, (dialogInterface2, i2) -> startImex(DcContext.DC_IMEX_EXPORT_SELF_KEYS))
|
||||
.show();
|
||||
}
|
||||
else {
|
||||
new AlertDialog.Builder(getActivity())
|
||||
.setTitle(R.string.preferences_managekeys__import_secret_keys)
|
||||
.setMessage(getActivity().getString(R.string.preferences_managekeys__import_explain, dcContext.getImexDir().getAbsolutePath()))
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setPositiveButton(android.R.string.ok, (dialogInterface2, i2) -> startImex(DcContext.DC_IMEX_IMPORT_SELF_KEYS))
|
||||
.show();
|
||||
}
|
||||
}
|
||||
)
|
||||
.show();
|
||||
})
|
||||
.execute();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private ProgressDialog progressDialog = null;
|
||||
private int progressWhat = 0;
|
||||
private String imexDir = "";
|
||||
private void startImex(int what)
|
||||
{
|
||||
if( progressDialog!=null ) {
|
||||
progressDialog.dismiss();
|
||||
progressDialog = null;
|
||||
}
|
||||
progressWhat = what;
|
||||
progressDialog = new ProgressDialog(getActivity());
|
||||
progressDialog.setMessage(getActivity().getString(R.string.one_moment));
|
||||
progressDialog.setCanceledOnTouchOutside(false);
|
||||
progressDialog.setCancelable(false);
|
||||
progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getActivity().getString(android.R.string.cancel), (dialog, which) -> dcContext.stopOngoingProcess());
|
||||
progressDialog.show();
|
||||
|
||||
imexDir = dcContext.getImexDir().getAbsolutePath();
|
||||
dcContext.captureNextError();
|
||||
dcContext.imex(progressWhat, imexDir);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleEvent(int eventId, Object data1, Object data2) {
|
||||
if (eventId== DcContext.DC_EVENT_IMEX_PROGRESS) {
|
||||
long progress = (Long)data1;
|
||||
if (progress==0/*error/aborted*/) {
|
||||
dcContext.endCaptureNextError();
|
||||
progressDialog.dismiss();
|
||||
progressDialog = null;
|
||||
if (dcContext.hasCapturedError()) {
|
||||
new android.app.AlertDialog.Builder(getActivity())
|
||||
.setMessage(dcContext.getCapturedError())
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
else if (progress<1000/*progress in permille*/) {
|
||||
int percent = (int)progress / 10;
|
||||
progressDialog.setMessage(getResources().getString(R.string.one_moment)+String.format(" %d%%", percent));
|
||||
}
|
||||
else if (progress==1000/*done*/) {
|
||||
dcContext.endCaptureNextError();
|
||||
progressDialog.dismiss();
|
||||
progressDialog = null;
|
||||
String msg = "";
|
||||
if (progressWhat==DcContext.DC_IMEX_EXPORT_BACKUP) {
|
||||
msg = getActivity().getString(R.string.preferences_backup__backup_written_to_x, imexDir);
|
||||
}
|
||||
else if (progressWhat==DcContext.DC_IMEX_EXPORT_SELF_KEYS) {
|
||||
msg = getActivity().getString(R.string.preferences_managekeys__secret_keys_exported_to_x, imexDir);
|
||||
}
|
||||
else if (progressWhat==DcContext.DC_IMEX_IMPORT_SELF_KEYS) {
|
||||
msg = getActivity().getString(R.string.preferences_managekeys__secret_keys_imported_from_x, imexDir);
|
||||
}
|
||||
new android.app.AlertDialog.Builder(getActivity())
|
||||
.setMessage(msg)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user