drop ContactSync feature
This commit is contained in:
@@ -30,6 +30,8 @@ import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Build;
|
||||
import android.os.Build.VERSION;
|
||||
import android.os.Build.VERSION_CODES;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -37,7 +39,6 @@ import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.sufficientlysecure.keychain.keysync.KeyserverSyncManager;
|
||||
import org.sufficientlysecure.keychain.network.TlsCertificatePinning;
|
||||
import org.sufficientlysecure.keychain.provider.TemporaryFileProvider;
|
||||
import org.sufficientlysecure.keychain.service.ContactSyncAdapterService;
|
||||
import org.sufficientlysecure.keychain.util.PRNGFixes;
|
||||
import org.sufficientlysecure.keychain.util.Preferences;
|
||||
import timber.log.Timber;
|
||||
@@ -85,15 +86,9 @@ public class KeychainApplication extends Application {
|
||||
}
|
||||
*/
|
||||
|
||||
// Add OpenKeychain account to Android to link contacts with keys and keyserver sync
|
||||
createAccountIfNecessary(this);
|
||||
|
||||
Preferences preferences = Preferences.getPreferences(this);
|
||||
if (preferences.isAppExecutedFirstTime()) {
|
||||
preferences.setAppExecutedFirstTime(false);
|
||||
|
||||
ContactSyncAdapterService.enableContactsSync(this);
|
||||
|
||||
preferences.setPrefVersionToCurrentVersion();
|
||||
}
|
||||
|
||||
@@ -115,33 +110,6 @@ public class KeychainApplication extends Application {
|
||||
TemporaryFileProvider.scheduleCleanupImmediately(getApplicationContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the OpenKeychain contact/keyserver sync account if it exists or was successfully
|
||||
* created, null otherwise
|
||||
*/
|
||||
public static @Nullable Account createAccountIfNecessary(Context context) {
|
||||
try {
|
||||
AccountManager manager = AccountManager.get(context);
|
||||
Account[] accounts = manager.getAccountsByType(Constants.ACCOUNT_TYPE);
|
||||
|
||||
Account account = new Account(Constants.ACCOUNT_NAME, Constants.ACCOUNT_TYPE);
|
||||
if (accounts.length == 0) {
|
||||
if (!manager.addAccountExplicitly(account, null, null)) {
|
||||
Timber.d("error when adding account via addAccountExplicitly");
|
||||
return null;
|
||||
} else {
|
||||
return account;
|
||||
}
|
||||
} else {
|
||||
return accounts[0];
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
Timber.e(e, "SecurityException when adding the account");
|
||||
Toast.makeText(context, R.string.reinstall_openkeychain, Toast.LENGTH_LONG).show();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static HashMap<String,Bitmap> qrCodeCache = new HashMap<>();
|
||||
|
||||
@Override
|
||||
|
||||
@@ -43,7 +43,6 @@ import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
import org.sufficientlysecure.keychain.service.CertifyActionsParcel;
|
||||
import org.sufficientlysecure.keychain.service.CertifyActionsParcel.CertifyAction;
|
||||
import org.sufficientlysecure.keychain.service.ContactSyncAdapterService;
|
||||
import org.sufficientlysecure.keychain.service.UploadKeyringParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
|
||||
@@ -254,9 +253,6 @@ public class CertifyOperation extends BaseReadWriteOperation<CertifyActionsParce
|
||||
uploadOk, uploadError);
|
||||
}
|
||||
|
||||
// since only verified keys are synced to contacts, we need to initiate a sync now
|
||||
ContactSyncAdapterService.requestContactsSync();
|
||||
|
||||
log.add(LogType.MSG_CRT_SUCCESS, 0);
|
||||
if (uploadError != 0) {
|
||||
return new CertifyResult(CertifyResult.RESULT_WARNINGS, log, certifyOk, certifyError, uploadOk,
|
||||
|
||||
@@ -30,7 +30,6 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult.Operat
|
||||
import org.sufficientlysecure.keychain.operations.results.UpdateTrustResult;
|
||||
import org.sufficientlysecure.keychain.pgp.Progressable;
|
||||
import org.sufficientlysecure.keychain.daos.KeyWritableRepository;
|
||||
import org.sufficientlysecure.keychain.service.ContactSyncAdapterService;
|
||||
import org.sufficientlysecure.keychain.service.DeleteKeyringParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||
@@ -101,9 +100,6 @@ public class DeleteOperation extends BaseReadWriteOperation<DeleteKeyringParcel>
|
||||
|
||||
int result = DeleteResult.RESULT_OK;
|
||||
if (success > 0) {
|
||||
// make sure new data is synced into contacts
|
||||
ContactSyncAdapterService.requestContactsSync();
|
||||
|
||||
log.add(LogType.MSG_DEL_OK, 0, success);
|
||||
}
|
||||
if (fail > 0) {
|
||||
|
||||
@@ -38,7 +38,6 @@ import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpKeyOperation;
|
||||
import org.sufficientlysecure.keychain.pgp.Progressable;
|
||||
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
|
||||
import org.sufficientlysecure.keychain.service.ContactSyncAdapterService;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
||||
import org.sufficientlysecure.keychain.service.UploadKeyringParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
@@ -182,9 +181,6 @@ public class EditKeyOperation extends BaseReadWriteOperation<SaveKeyringParcel>
|
||||
|
||||
updateProgress(R.string.progress_done, 100, 100);
|
||||
|
||||
// make sure new data is synced into contacts
|
||||
ContactSyncAdapterService.requestContactsSync();
|
||||
|
||||
log.add(LogType.MSG_ED_SUCCESS, 0);
|
||||
return new EditKeyResult(EditKeyResult.RESULT_OK, log, ring.getMasterKeyId());
|
||||
|
||||
|
||||
@@ -32,9 +32,9 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.daos.KeyMetadataDao;
|
||||
import org.sufficientlysecure.keychain.daos.KeyWritableRepository;
|
||||
@@ -55,7 +55,6 @@ import org.sufficientlysecure.keychain.pgp.CanonicalizedKeyRing;
|
||||
import org.sufficientlysecure.keychain.pgp.Progressable;
|
||||
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
import org.sufficientlysecure.keychain.service.ContactSyncAdapterService;
|
||||
import org.sufficientlysecure.keychain.service.ImportKeyringParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
|
||||
@@ -134,9 +133,6 @@ public class ImportOperation extends BaseReadWriteOperation<ImportKeyringParcel>
|
||||
}
|
||||
|
||||
/**
|
||||
* Since the introduction of multithreaded import, we expect calling functions to handle the
|
||||
* contact-to-key sync i.e ContactSyncAdapterService.requestContactsSync()
|
||||
*
|
||||
* @param entries keys to import
|
||||
* @param numTotalKeys number of keys to import
|
||||
* @param hkpKeyserver contains uri of keyserver to import from, if it is an import from cloud
|
||||
@@ -274,11 +270,6 @@ public class ImportOperation extends BaseReadWriteOperation<ImportKeyringParcel>
|
||||
}
|
||||
}
|
||||
|
||||
// Special: make sure new data is synced into contacts
|
||||
// disabling sync right now since it reduces speed while multi-threading
|
||||
// so, we expect calling functions to take care of it. KeychainService handles this
|
||||
// ContactSyncAdapterService.requestContactsSync();
|
||||
|
||||
// convert to long array
|
||||
long[] importedMasterKeyIdsArray = new long[importedMasterKeyIds.size()];
|
||||
for (int i = 0; i < importedMasterKeyIds.size(); ++i) {
|
||||
@@ -476,10 +467,6 @@ public class ImportOperation extends BaseReadWriteOperation<ImportKeyringParcel>
|
||||
|
||||
result = multiThreadedKeyImport(keyList, keyServer, proxy, skipSave, forceReinsert);
|
||||
}
|
||||
|
||||
if (!skipSave) {
|
||||
ContactSyncAdapterService.requestContactsSync();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,177 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Schürmann & Breitmoser GbR
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.keychain.service;
|
||||
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.AbstractThreadedSyncAdapter;
|
||||
import android.content.ContentProviderClient;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SyncResult;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.provider.ContactsContract;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.KeychainApplication;
|
||||
import org.sufficientlysecure.keychain.NotificationChannelManager;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.ui.SettingsActivity;
|
||||
import org.sufficientlysecure.keychain.util.ContactHelper;
|
||||
import timber.log.Timber;
|
||||
|
||||
|
||||
public class ContactSyncAdapterService extends Service {
|
||||
|
||||
private static final int NOTIFICATION_ID_SYNC_SETTINGS = 13;
|
||||
|
||||
private class ContactSyncAdapter extends AbstractThreadedSyncAdapter {
|
||||
|
||||
// private final AtomicBoolean importDone = new AtomicBoolean(false);
|
||||
|
||||
public ContactSyncAdapter() {
|
||||
super(ContactSyncAdapterService.this, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider,
|
||||
final SyncResult syncResult) {
|
||||
Timber.d("Performing a contact sync!");
|
||||
|
||||
new ContactHelper(ContactSyncAdapterService.this).writeKeysToContacts();
|
||||
|
||||
// importKeys();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSecurityException(Account account, Bundle extras, String authority, SyncResult syncResult) {
|
||||
super.onSecurityException(account, extras, authority, syncResult);
|
||||
|
||||
// deactivate sync
|
||||
ContentResolver.setSyncAutomatically(account, authority, false);
|
||||
|
||||
NotificationChannelManager.getInstance(getContext()).createNotificationChannelsIfNecessary();
|
||||
|
||||
// show notification linking to sync settings
|
||||
Intent resultIntent = new Intent(ContactSyncAdapterService.this, SettingsActivity.class);
|
||||
resultIntent.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT,
|
||||
SettingsActivity.SyncPrefsFragment.class.getName());
|
||||
PendingIntent resultPendingIntent =
|
||||
PendingIntent.getActivity(
|
||||
ContactSyncAdapterService.this,
|
||||
0,
|
||||
resultIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
);
|
||||
NotificationCompat.Builder mBuilder =
|
||||
new NotificationCompat.Builder(ContactSyncAdapterService.this, NotificationChannelManager.PERMISSION_REQUESTS)
|
||||
.setAutoCancel(true)
|
||||
.setSmallIcon(R.drawable.ic_stat_notify_24dp)
|
||||
.setColor(getResources().getColor(R.color.primary))
|
||||
.setContentTitle(getString(R.string.sync_notification_permission_required_title))
|
||||
.setContentText(getString(R.string.sync_notification_permission_required_text))
|
||||
.setContentIntent(resultPendingIntent);
|
||||
NotificationManagerCompat.from(ContactSyncAdapterService.this)
|
||||
.notify(NOTIFICATION_ID_SYNC_SETTINGS, mBuilder.build());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return new ContactSyncAdapter().getSyncAdapterBinder();
|
||||
}
|
||||
|
||||
public static void requestContactsSync() {
|
||||
// if user has disabled automatic sync, do nothing
|
||||
boolean isSyncEnabled = ContentResolver.getSyncAutomatically(new Account
|
||||
(Constants.ACCOUNT_NAME, Constants.ACCOUNT_TYPE), ContactsContract.AUTHORITY);
|
||||
|
||||
if (!isSyncEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
Bundle extras = new Bundle();
|
||||
// no need to wait, do it immediately
|
||||
extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
|
||||
extras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
|
||||
ContentResolver.requestSync(
|
||||
new Account(Constants.ACCOUNT_NAME, Constants.ACCOUNT_TYPE),
|
||||
ContactsContract.AUTHORITY,
|
||||
extras);
|
||||
}
|
||||
|
||||
public static void enableContactsSync(Context context) {
|
||||
Account account = KeychainApplication.createAccountIfNecessary(context);
|
||||
if (account == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 1);
|
||||
ContentResolver.setSyncAutomatically(account, ContactsContract.AUTHORITY, true);
|
||||
}
|
||||
|
||||
// TODO: Import is currently disabled, until we implement proper origin management
|
||||
// private static void importKeys() {
|
||||
// importDone.set(false);
|
||||
// KeychainApplication.setupAccountAsNeeded(ContactSyncAdapterService.this);
|
||||
// EmailKeyHelper.importContacts(getContext(), new Messenger(new Handler(Looper.getMainLooper(),
|
||||
// new Handler.Callback() {
|
||||
// @Override
|
||||
// public boolean handleMessage(Message msg) {
|
||||
// Bundle data = msg.getInputData();
|
||||
// switch (msg.arg1) {
|
||||
// case KeychainIntentServiceHandler.MESSAGE_OKAY:
|
||||
// Log.d(Constants.TAG, "Syncing... Done.");
|
||||
// synchronized (importDone) {
|
||||
// importDone.set(true);
|
||||
// importDone.notifyAll();
|
||||
// }
|
||||
// return true;
|
||||
// case KeychainIntentServiceHandler.MESSAGE_UPDATE_PROGRESS:
|
||||
// if (data.containsKey(KeychainIntentServiceHandler.DATA_PROGRESS) &&
|
||||
// data.containsKey(KeychainIntentServiceHandler.DATA_PROGRESS_MAX)) {
|
||||
// Log.d(Constants.TAG, "Syncing... Progress: " +
|
||||
// data.getInt(KeychainIntentServiceHandler.DATA_PROGRESS) + "/" +
|
||||
// data.getInt(KeychainIntentServiceHandler.DATA_PROGRESS_MAX));
|
||||
// return false;
|
||||
// }
|
||||
// default:
|
||||
// Log.d(Constants.TAG, "Syncing... " + msg.toString());
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// })));
|
||||
// synchronized (importDone) {
|
||||
// try {
|
||||
// if (!importDone.get()) importDone.wait();
|
||||
// } catch (InterruptedException e) {
|
||||
// Log.w(Constants.TAG, e);
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Schürmann & Breitmoser GbR
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.keychain.service;
|
||||
|
||||
import android.accounts.AbstractAccountAuthenticator;
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountAuthenticatorResponse;
|
||||
import android.accounts.NetworkErrorException;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Message;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import timber.log.Timber;
|
||||
|
||||
|
||||
/**
|
||||
* This service actually does nothing, it's sole task is to show a Toast if the use tries to create an account.
|
||||
*/
|
||||
public class DummyAccountService extends Service {
|
||||
|
||||
private class Toaster {
|
||||
private static final String TOAST_MESSAGE = "toast_message";
|
||||
private Context context;
|
||||
private Handler handler = new Handler(new Handler.Callback() {
|
||||
@Override
|
||||
public boolean handleMessage(Message msg) {
|
||||
Toast.makeText(context, msg.getData().getString(TOAST_MESSAGE), Toast.LENGTH_LONG).show();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
private Toaster(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public void toast(int resourceId) {
|
||||
toast(context.getString(resourceId));
|
||||
}
|
||||
|
||||
public void toast(String message) {
|
||||
Message msg = new Message();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(TOAST_MESSAGE, message);
|
||||
msg.setData(bundle);
|
||||
handler.sendMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
private class Authenticator extends AbstractAccountAuthenticator {
|
||||
|
||||
public Authenticator() {
|
||||
super(DummyAccountService.this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
|
||||
Timber.d("DummyAccountService.editProperties");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType,
|
||||
String[] requiredFeatures, Bundle options) throws NetworkErrorException {
|
||||
response.onResult(new Bundle());
|
||||
toaster.toast(R.string.account_no_manual_account_creation);
|
||||
Timber.d("DummyAccountService.addAccount");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options)
|
||||
throws NetworkErrorException {
|
||||
Timber.d("DummyAccountService.confirmCredentials");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType,
|
||||
Bundle options) throws NetworkErrorException {
|
||||
Timber.d("DummyAccountService.getAuthToken");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthTokenLabel(String authTokenType) {
|
||||
Timber.d("DummyAccountService.getAuthTokenLabel");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType,
|
||||
Bundle options) throws NetworkErrorException {
|
||||
Timber.d("DummyAccountService.updateCredentials");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account, String[] features)
|
||||
throws NetworkErrorException {
|
||||
Timber.d("DummyAccountService.hasFeatures");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Toaster toaster;
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
toaster = new Toaster(this);
|
||||
return new Authenticator().getIBinder();
|
||||
}
|
||||
}
|
||||
@@ -23,16 +23,9 @@ import java.security.KeyStoreException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import android.Manifest;
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.preference.EditTextPreference;
|
||||
import android.preference.ListPreference;
|
||||
@@ -40,17 +33,13 @@ import android.preference.Preference;
|
||||
import android.preference.PreferenceFragment;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.preference.SwitchPreference;
|
||||
import android.provider.ContactsContract;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.KeychainApplication;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.compatibility.AppCompatPreferenceActivity;
|
||||
import org.sufficientlysecure.keychain.keyimport.HkpKeyserverAddress;
|
||||
@@ -402,11 +391,8 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
|
||||
|
||||
// Load the preferences from an XML resource
|
||||
addPreferencesFromResource(R.xml.sync_preferences);
|
||||
|
||||
findPreference(Constants.Pref.SYNC_KEYSERVER).setOnPreferenceChangeListener(
|
||||
(preference, newValue) -> {
|
||||
return true;
|
||||
});
|
||||
(preference, newValue) -> true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -414,130 +400,6 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
|
||||
super.onStop();
|
||||
KeyserverSyncManager.updateKeyserverSyncScheduleAsync(getActivity(), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
// this needs to be done in onResume since the user can change sync values from Android
|
||||
// settings and we need to reflect that change when the user navigates back
|
||||
final Account account = KeychainApplication.createAccountIfNecessary(getActivity());
|
||||
// for contacts sync
|
||||
initializeSyncCheckBox(
|
||||
(SwitchPreference) findPreference(Constants.Pref.SYNC_CONTACTS),
|
||||
account,
|
||||
ContactsContract.AUTHORITY
|
||||
);
|
||||
}
|
||||
|
||||
private void initializeSyncCheckBox(final SwitchPreference syncCheckBox,
|
||||
final Account account,
|
||||
final String authority) {
|
||||
// account is null if it could not be created for some reason
|
||||
boolean syncEnabled =
|
||||
account != null
|
||||
&& ContentResolver.getSyncAutomatically(account, authority)
|
||||
&& checkContactsPermission(authority);
|
||||
syncCheckBox.setChecked(syncEnabled);
|
||||
setSummary(syncCheckBox, authority, syncEnabled);
|
||||
|
||||
syncCheckBox.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
@TargetApi(Build.VERSION_CODES.M)
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
boolean syncEnabled = (Boolean) newValue;
|
||||
if (syncEnabled) {
|
||||
if (checkContactsPermission(authority)) {
|
||||
ContentResolver.setSyncAutomatically(account, authority, true);
|
||||
setSummary(syncCheckBox, authority, true);
|
||||
return true;
|
||||
} else {
|
||||
requestPermissions(
|
||||
new String[]{Manifest.permission.READ_CONTACTS},
|
||||
REQUEST_PERMISSION_READ_CONTACTS);
|
||||
// don't update preference
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (account == null) {
|
||||
// if account could not be created for some reason,
|
||||
// we can't have our sync
|
||||
return false;
|
||||
}
|
||||
// disable syncs
|
||||
ContentResolver.setSyncAutomatically(account, authority, false);
|
||||
// cancel any ongoing/pending syncs
|
||||
ContentResolver.cancelSync(account, authority);
|
||||
setSummary(syncCheckBox, authority, false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean checkContactsPermission(String authority) {
|
||||
if (!ContactsContract.AUTHORITY.equals(authority)) {
|
||||
// provides convenience of not using separate checks for keyserver and contact sync
|
||||
// in initializeSyncCheckBox
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_CONTACTS)
|
||||
== PackageManager.PERMISSION_GRANTED) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode,
|
||||
@NonNull String[] permissions,
|
||||
@NonNull int[] grantResults) {
|
||||
|
||||
if (requestCode != REQUEST_PERMISSION_READ_CONTACTS) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
return;
|
||||
}
|
||||
|
||||
boolean permissionWasGranted = grantResults.length > 0
|
||||
&& grantResults[0] == PackageManager.PERMISSION_GRANTED;
|
||||
|
||||
if (permissionWasGranted) {
|
||||
// permission granted -> enable contact linking
|
||||
AccountManager manager = AccountManager.get(getActivity());
|
||||
final Account account = manager.getAccountsByType(Constants.ACCOUNT_TYPE)[0];
|
||||
SwitchPreference pref = (SwitchPreference) findPreference(Constants.Pref.SYNC_CONTACTS);
|
||||
ContentResolver.setSyncAutomatically(account, ContactsContract.AUTHORITY, true);
|
||||
setSummary(pref, ContactsContract.AUTHORITY, true);
|
||||
pref.setChecked(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void setSummary(SwitchPreference syncCheckBox, String authority,
|
||||
boolean checked) {
|
||||
switch (authority) {
|
||||
case Constants.PROVIDER_AUTHORITY: {
|
||||
if (checked) {
|
||||
syncCheckBox.setSummary(R.string.label_sync_settings_keyserver_summary_on);
|
||||
} else {
|
||||
syncCheckBox.setSummary(R.string.label_sync_settings_keyserver_summary_off);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ContactsContract.AUTHORITY: {
|
||||
if (checked) {
|
||||
syncCheckBox.setSummary(R.string.label_sync_settings_contacts_summary_on);
|
||||
} else {
|
||||
syncCheckBox.setSummary(R.string.label_sync_settings_contacts_summary_off);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user