From c5bcbce28fa45d8d1e5714d111f3cc24a2c99d0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 23 Nov 2015 09:06:12 +0100 Subject: Show notification when READ_CONTACTS permission is denied in sync service, hide linked contact card if permission is denied --- OpenKeychain/src/main/AndroidManifest.xml | 18 ++++--- .../keychain/operations/CertifyOperation.java | 6 +-- .../keychain/operations/DeleteOperation.java | 2 +- .../keychain/operations/EditKeyOperation.java | 2 +- .../keychain/operations/ImportOperation.java | 6 +-- .../service/ContactSyncAdapterService.java | 57 +++++++++++++++++++--- .../keychain/ui/SettingsActivity.java | 12 ++--- .../keychain/ui/ViewKeyActivity.java | 4 +- .../keychain/ui/ViewKeyFragment.java | 31 ++++++++---- .../keychain/util/ContactHelper.java | 55 ++++++++++++++++++--- OpenKeychain/src/main/res/values/strings.xml | 2 + .../src/main/res/xml/cloud_search_preferences.xml | 21 ++++++++ .../src/main/res/xml/cloud_search_prefs.xml | 21 -------- .../main/res/xml/custom_pgp_contacts_structure.xml | 6 --- .../main/res/xml/keyserver_sync_adapter_desc.xml | 8 --- .../src/main/res/xml/proxy_preferences.xml | 34 +++++++++++++ OpenKeychain/src/main/res/xml/proxy_prefs.xml | 34 ------------- .../src/main/res/xml/sync_adapter_contacts.xml | 8 +++ .../res/xml/sync_adapter_contacts_structure.xml | 6 +++ .../src/main/res/xml/sync_adapter_desc.xml | 8 --- .../src/main/res/xml/sync_adapter_keys.xml | 8 +++ 21 files changed, 225 insertions(+), 124 deletions(-) create mode 100644 OpenKeychain/src/main/res/xml/cloud_search_preferences.xml delete mode 100644 OpenKeychain/src/main/res/xml/cloud_search_prefs.xml delete mode 100644 OpenKeychain/src/main/res/xml/custom_pgp_contacts_structure.xml delete mode 100644 OpenKeychain/src/main/res/xml/keyserver_sync_adapter_desc.xml create mode 100644 OpenKeychain/src/main/res/xml/proxy_preferences.xml delete mode 100644 OpenKeychain/src/main/res/xml/proxy_prefs.xml create mode 100644 OpenKeychain/src/main/res/xml/sync_adapter_contacts.xml create mode 100644 OpenKeychain/src/main/res/xml/sync_adapter_contacts_structure.xml delete mode 100644 OpenKeychain/src/main/res/xml/sync_adapter_desc.xml create mode 100644 OpenKeychain/src/main/res/xml/sync_adapter_keys.xml (limited to 'OpenKeychain/src') diff --git a/OpenKeychain/src/main/AndroidManifest.xml b/OpenKeychain/src/main/AndroidManifest.xml index 79b8dbb27..337ad73e0 100644 --- a/OpenKeychain/src/main/AndroidManifest.xml +++ b/OpenKeychain/src/main/AndroidManifest.xml @@ -56,14 +56,20 @@ - + - - + + + + diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java index 7d11fa1f1..4ad75fde1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java @@ -18,14 +18,12 @@ package org.sufficientlysecure.keychain.operations; -import java.net.Proxy; import java.util.ArrayList; import java.util.concurrent.atomic.AtomicBoolean; import android.content.Context; import android.support.annotation.NonNull; -import org.sufficientlysecure.keychain.keyimport.HkpKeyserver; import org.sufficientlysecure.keychain.operations.results.CertifyResult; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog; @@ -51,8 +49,6 @@ import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.NfcSignOperationsBuilder; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.util.Passphrase; -import org.sufficientlysecure.keychain.util.Preferences; -import org.sufficientlysecure.keychain.util.orbot.OrbotHelper; /** * An operation which implements a high level user id certification operation. @@ -256,7 +252,7 @@ public class CertifyOperation extends BaseOperation { } // since only verified keys are synced to contacts, we need to initiate a sync now - ContactSyncAdapterService.requestSync(); + ContactSyncAdapterService.requestContactsSync(); log.add(LogType.MSG_CRT_SUCCESS, 0); if (uploadError != 0) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/DeleteOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/DeleteOperation.java index 56bd3b786..8227fea02 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/DeleteOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/DeleteOperation.java @@ -102,7 +102,7 @@ public class DeleteOperation extends BaseOperation { int result = DeleteResult.RESULT_OK; if (success > 0) { // make sure new data is synced into contacts - ContactSyncAdapterService.requestSync(); + ContactSyncAdapterService.requestContactsSync(); log.add(LogType.MSG_DEL_OK, 0, success); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java index 3b2c484be..51485a35d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java @@ -195,7 +195,7 @@ public class EditKeyOperation extends BaseOperation { updateProgress(R.string.progress_done, 100, 100); // make sure new data is synced into contacts - ContactSyncAdapterService.requestSync(); + ContactSyncAdapterService.requestContactsSync(); log.add(LogType.MSG_ED_SUCCESS, 0); return new EditKeyResult(EditKeyResult.RESULT_OK, log, ring.getMasterKeyId()); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportOperation.java index 19a05790f..70288123f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportOperation.java @@ -124,7 +124,7 @@ public class ImportOperation extends BaseOperation { /** * Since the introduction of multithreaded import, we expect calling functions to handle the - * contact-to-key sync i.e ContactSyncAdapterService.requestSync() + * contact-to-key sync i.e ContactSyncAdapterService.requestContactsSync() * * @param entries keys to import * @param num number of keys to import @@ -325,7 +325,7 @@ public class ImportOperation extends BaseOperation { // 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.requestSync(); + // ContactSyncAdapterService.requestContactsSync(); // convert to long array long[] importedMasterKeyIdsArray = new long[importedMasterKeyIds.size()]; @@ -405,7 +405,7 @@ public class ImportOperation extends BaseOperation { result = multiThreadedKeyImport(keyList.iterator(), keyList.size(), keyServer, proxy); } - ContactSyncAdapterService.requestSync(); + ContactSyncAdapterService.requestContactsSync(); return result; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java index b36d23775..64f06fd15 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Dominik Schürmann + * Copyright (C) 2014-2015 Dominik Schürmann * * 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 @@ -18,6 +18,9 @@ package org.sufficientlysecure.keychain.service; import android.accounts.Account; +import android.app.Activity; +import android.app.NotificationManager; +import android.app.PendingIntent; import android.app.Service; import android.content.AbstractThreadedSyncAdapter; import android.content.ContentProviderClient; @@ -26,14 +29,20 @@ 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 android.support.v4.app.NotificationCompat; import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.ui.SettingsActivity; import org.sufficientlysecure.keychain.util.ContactHelper; import org.sufficientlysecure.keychain.util.Log; 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); @@ -46,7 +55,44 @@ public class ContactSyncAdapterService extends Service { public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, final SyncResult syncResult) { Log.d(Constants.TAG, "Performing a contact sync!"); - // TODO: Import is currently disabled for 2.8, until we implement proper origin management + + ContactHelper.writeKeysToContacts(ContactSyncAdapterService.this); + + 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); + + // 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) + .setSmallIcon(R.drawable.ic_stat_notify_24dp) + .setContentTitle(getString(R.string.sync_notification_permission_required_title)) + .setContentText(getString(R.string.sync_notification_permission_required_text)) + .setContentIntent(resultPendingIntent); + NotificationManager mNotifyMgr = + (NotificationManager) ContactSyncAdapterService.this.getSystemService(Activity.NOTIFICATION_SERVICE); + mNotifyMgr.notify(NOTIFICATION_ID_SYNC_SETTINGS, mBuilder.build()); + } + } + + private static void importKeys() { + // TODO: Import is currently disabled, until we implement proper origin management // importDone.set(false); // KeychainApplication.setupAccountAsNeeded(ContactSyncAdapterService.this); // EmailKeyHelper.importContacts(getContext(), new Messenger(new Handler(Looper.getMainLooper(), @@ -84,14 +130,13 @@ public class ContactSyncAdapterService extends Service { // return; // } // } - ContactHelper.writeKeysToContacts(ContactSyncAdapterService.this); - } } - public static void requestSync() { + public static void requestContactsSync() { Bundle extras = new Bundle(); - // no need to wait for internet connection! + // 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, diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java index 17398911c..9e962fa0d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java @@ -133,7 +133,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity { super.onCreate(savedInstanceState); // Load the preferences from an XML resource - addPreferencesFromResource(R.xml.cloud_search_prefs); + addPreferencesFromResource(R.xml.cloud_search_preferences); mKeyServerPreference = (PreferenceScreen) findPreference(Constants.Pref.KEY_SERVERS); mKeyServerPreference.setSummary(keyserverSummary(getActivity())); @@ -238,11 +238,11 @@ public class SettingsActivity extends AppCompatPreferenceActivity { if (mFragment != null) { Preferences.setPreferenceManagerFileAndMode(mFragment.getPreferenceManager()); // Load the preferences from an XML resource - mFragment.addPreferencesFromResource(R.xml.proxy_prefs); + mFragment.addPreferencesFromResource(R.xml.proxy_preferences); } else { Preferences.setPreferenceManagerFileAndMode(mActivity.getPreferenceManager()); // Load the preferences from an XML resource - mActivity.addPreferencesFromResource(R.xml.proxy_prefs); + mActivity.addPreferencesFromResource(R.xml.proxy_preferences); } mUseTor = (SwitchPreference) automaticallyFindPreference(Constants.Pref.USE_TOR_PROXY); @@ -509,9 +509,9 @@ public class SettingsActivity extends AppCompatPreferenceActivity { // 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_KEYSERVER); - ContentResolver.setSyncAutomatically(account, Constants.PROVIDER_AUTHORITY, true); - setSummary(pref, Constants.PROVIDER_AUTHORITY, true); + SwitchPreference pref = (SwitchPreference) findPreference(Constants.Pref.SYNC_CONTACTS); + ContentResolver.setSyncAutomatically(account, ContactsContract.AUTHORITY, true); + setSummary(pref, ContactsContract.AUTHORITY, true); pref.setChecked(true); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java index c333ee0ef..e1b796f38 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -855,8 +855,8 @@ public class ViewKeyActivity extends BaseNfcActivity implements AsyncTask photoTask = new AsyncTask() { protected Bitmap doInBackground(Long... mMasterKeyId) { - return ContactHelper.loadPhotoByMasterKeyId(getContentResolver(), - mMasterKeyId[0], true); + return ContactHelper.loadPhotoByMasterKeyId(ViewKeyActivity.this, + getContentResolver(), mMasterKeyId[0], true); } protected void onPostExecute(Bitmap photo) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java index 7be695de0..dda2a680a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java @@ -22,10 +22,12 @@ package org.sufficientlysecure.keychain.ui; import java.io.IOException; import java.util.List; +import android.Manifest; import android.annotation.TargetApi; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; import android.database.Cursor; import android.graphics.Bitmap; import android.net.Uri; @@ -35,6 +37,7 @@ import android.os.Bundle; import android.os.Handler; import android.provider.ContactsContract; import android.support.v4.app.LoaderManager; +import android.support.v4.content.ContextCompat; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.support.v7.widget.CardView; @@ -241,9 +244,9 @@ public class ViewKeyFragment extends LoaderFragment implements Bitmap picture; if (mIsSecret) { - picture = ContactHelper.loadMainProfilePhoto(resolver, false); + picture = ContactHelper.loadMainProfilePhoto(getActivity(), resolver, false); } else { - picture = ContactHelper.loadPhotoByContactId(resolver, contactId, false); + picture = ContactHelper.loadPhotoByContactId(getActivity(), resolver, contactId, false); } if (picture != null) mSystemContactPicture.setImageBitmap(picture); @@ -419,13 +422,7 @@ public class ViewKeyFragment extends LoaderFragment implements getLoaderManager().initLoader(LOADER_ID_LINKED_IDS, null, this); } - - Bundle linkedContactData = new Bundle(); - linkedContactData.putLong(LOADER_EXTRA_LINKED_CONTACT_MASTER_KEY_ID, masterKeyId); - linkedContactData.putBoolean(LOADER_EXTRA_LINKED_CONTACT_IS_SECRET, mIsSecret); - - // initialises loader for contact query so we can listen to any updates - getLoaderManager().initLoader(LOADER_ID_LINKED_CONTACT, linkedContactData, this); + initLinkedContactLoader(masterKeyId, mIsSecret); break; } @@ -465,6 +462,22 @@ public class ViewKeyFragment extends LoaderFragment implements } } + private void initLinkedContactLoader(long masterKeyId, boolean isSecret) { + if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_CONTACTS) + == PackageManager.PERMISSION_DENIED) { + Log.w(Constants.TAG, "loading linked system contact not possible READ_CONTACTS permission denied!"); + hideLinkedSystemContact(); + return; + } + + Bundle linkedContactData = new Bundle(); + linkedContactData.putLong(LOADER_EXTRA_LINKED_CONTACT_MASTER_KEY_ID, masterKeyId); + linkedContactData.putBoolean(LOADER_EXTRA_LINKED_CONTACT_IS_SECRET, isSecret); + + // initialises loader for contact query so we can listen to any updates + getLoaderManager().initLoader(LOADER_ID_LINKED_CONTACT, linkedContactData, this); + } + /** * This is called when the last Cursor provided to onLoadFinished() above is about to be closed. * We need to make sure we are no longer using it. diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java index 77aa1a055..1abe56055 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java @@ -17,17 +17,21 @@ package org.sufficientlysecure.keychain.util; +import android.Manifest; import android.accounts.Account; import android.accounts.AccountManager; import android.content.ContentProviderOperation; import android.content.ContentResolver; import android.content.ContentUris; import android.content.Context; +import android.content.pm.PackageManager; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; +import android.os.Build; import android.provider.ContactsContract; +import android.support.v4.content.ContextCompat; import android.util.Patterns; import org.sufficientlysecure.keychain.Constants; @@ -51,6 +55,11 @@ public class ContactHelper { private static final Map photoCache = new HashMap<>(); public static List getPossibleUserEmails(Context context) { + if (!isContactsPermissionGranted(context)) { + Log.w(Constants.TAG, "getting emails not possible READ_CONTACTS permission denied!"); + return new ArrayList<>(); + } + Set accountMails = getAccountEmails(context); accountMails.addAll(getMainProfileContactEmails(context)); @@ -69,6 +78,11 @@ public class ContactHelper { } public static List getPossibleUserNames(Context context) { + if (!isContactsPermissionGranted(context)) { + Log.w(Constants.TAG, "getting names not possible READ_CONTACTS permission denied!"); + return new ArrayList<>(); + } + Set accountMails = getAccountEmails(context); Set names = getContactNamesFromEmails(context, accountMails); names.addAll(getMainProfileContactName(context)); @@ -242,7 +256,7 @@ public class ContactHelper { * @param highRes true for large image if present, false for thumbnail * @return bitmap of loaded photo */ - public static Bitmap loadMainProfilePhoto(ContentResolver contentResolver, boolean highRes) { + public static Bitmap loadMainProfilePhoto(Context context, ContentResolver contentResolver, boolean highRes) { try { long mainProfileContactId = getMainProfileContactId(contentResolver); @@ -300,6 +314,7 @@ public class ContactHelper { } public static Uri dataUriFromContactUri(Context context, Uri contactUri) { + Cursor contactMasterKey = context.getContentResolver().query(contactUri, new String[]{ContactsContract.Data.DATA2}, null, null, null); if (contactMasterKey != null) { @@ -373,32 +388,43 @@ public class ContactHelper { return contactName; } - public static Bitmap getCachedPhotoByMasterKeyId(ContentResolver contentResolver, long masterKeyId) { + public static Bitmap getCachedPhotoByMasterKeyId(Context context, ContentResolver contentResolver, + long masterKeyId) { if (masterKeyId == -1) { return null; } if (!photoCache.containsKey(masterKeyId)) { - photoCache.put(masterKeyId, loadPhotoByMasterKeyId(contentResolver, masterKeyId, false)); + photoCache.put(masterKeyId, loadPhotoByMasterKeyId(context, contentResolver, masterKeyId, false)); } return photoCache.get(masterKeyId); } - public static Bitmap loadPhotoByMasterKeyId(ContentResolver contentResolver, long masterKeyId, - boolean highRes) { + public static Bitmap loadPhotoByMasterKeyId(Context context, ContentResolver contentResolver, + long masterKeyId, boolean highRes) { + if (!isContactsPermissionGranted(context)) { + Log.w(Constants.TAG, "loading photo not possible READ_CONTACTS permission denied!"); + return null; + } + if (masterKeyId == -1) { return null; } try { long contactId = findContactId(contentResolver, masterKeyId); - return loadPhotoByContactId(contentResolver, contactId, highRes); + return loadPhotoByContactId(context, contentResolver, contactId, highRes); } catch (Throwable ignored) { return null; } } - public static Bitmap loadPhotoByContactId(ContentResolver contentResolver, long contactId, - boolean highRes) { + public static Bitmap loadPhotoByContactId(Context context, ContentResolver contentResolver, + long contactId, boolean highRes) { + if (!isContactsPermissionGranted(context)) { + Log.w(Constants.TAG, "loading photo not possible READ_CONTACTS permission denied!"); + return null; + } + if (contactId == -1) { return null; } @@ -452,6 +478,19 @@ public class ContactHelper { writeKeysToNormalContacts(context, resolver); } + private static boolean isContactsPermissionGranted(Context context) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + return true; + } + + if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS) + == PackageManager.PERMISSION_GRANTED) { + return true; + } + + return false; + } + private static void writeKeysToNormalContacts(Context context, ContentResolver resolver) { // delete raw contacts flagged for deletion by user so they can be reinserted deleteFlaggedNormalRawContacts(resolver); diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index 12917f515..38a619ad7 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -1505,6 +1505,8 @@ "You can not create OpenKeychain accounts manually." "Privacy" "OpenKeychain does not synchronize your contacts with the Internet. It only links contacts to keys based on names and email addresses. It does this offline on your device." + "Linking keys needs contacts access!" + "Touch to configure linking to contacts" diff --git a/OpenKeychain/src/main/res/xml/cloud_search_preferences.xml b/OpenKeychain/src/main/res/xml/cloud_search_preferences.xml new file mode 100644 index 000000000..85d6a6bca --- /dev/null +++ b/OpenKeychain/src/main/res/xml/cloud_search_preferences.xml @@ -0,0 +1,21 @@ + + + + + + + + + \ No newline at end of file diff --git a/OpenKeychain/src/main/res/xml/cloud_search_prefs.xml b/OpenKeychain/src/main/res/xml/cloud_search_prefs.xml deleted file mode 100644 index 85d6a6bca..000000000 --- a/OpenKeychain/src/main/res/xml/cloud_search_prefs.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/OpenKeychain/src/main/res/xml/custom_pgp_contacts_structure.xml b/OpenKeychain/src/main/res/xml/custom_pgp_contacts_structure.xml deleted file mode 100644 index 39dd8bc91..000000000 --- a/OpenKeychain/src/main/res/xml/custom_pgp_contacts_structure.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/OpenKeychain/src/main/res/xml/keyserver_sync_adapter_desc.xml b/OpenKeychain/src/main/res/xml/keyserver_sync_adapter_desc.xml deleted file mode 100644 index 3923fae59..000000000 --- a/OpenKeychain/src/main/res/xml/keyserver_sync_adapter_desc.xml +++ /dev/null @@ -1,8 +0,0 @@ - - \ No newline at end of file diff --git a/OpenKeychain/src/main/res/xml/proxy_preferences.xml b/OpenKeychain/src/main/res/xml/proxy_preferences.xml new file mode 100644 index 000000000..fbb83eb12 --- /dev/null +++ b/OpenKeychain/src/main/res/xml/proxy_preferences.xml @@ -0,0 +1,34 @@ + + + + + + + + diff --git a/OpenKeychain/src/main/res/xml/proxy_prefs.xml b/OpenKeychain/src/main/res/xml/proxy_prefs.xml deleted file mode 100644 index fbb83eb12..000000000 --- a/OpenKeychain/src/main/res/xml/proxy_prefs.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - diff --git a/OpenKeychain/src/main/res/xml/sync_adapter_contacts.xml b/OpenKeychain/src/main/res/xml/sync_adapter_contacts.xml new file mode 100644 index 000000000..a134fdebe --- /dev/null +++ b/OpenKeychain/src/main/res/xml/sync_adapter_contacts.xml @@ -0,0 +1,8 @@ + + \ No newline at end of file diff --git a/OpenKeychain/src/main/res/xml/sync_adapter_contacts_structure.xml b/OpenKeychain/src/main/res/xml/sync_adapter_contacts_structure.xml new file mode 100644 index 000000000..39dd8bc91 --- /dev/null +++ b/OpenKeychain/src/main/res/xml/sync_adapter_contacts_structure.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/OpenKeychain/src/main/res/xml/sync_adapter_desc.xml b/OpenKeychain/src/main/res/xml/sync_adapter_desc.xml deleted file mode 100644 index a134fdebe..000000000 --- a/OpenKeychain/src/main/res/xml/sync_adapter_desc.xml +++ /dev/null @@ -1,8 +0,0 @@ - - \ No newline at end of file diff --git a/OpenKeychain/src/main/res/xml/sync_adapter_keys.xml b/OpenKeychain/src/main/res/xml/sync_adapter_keys.xml new file mode 100644 index 000000000..3923fae59 --- /dev/null +++ b/OpenKeychain/src/main/res/xml/sync_adapter_keys.xml @@ -0,0 +1,8 @@ + + \ No newline at end of file -- cgit v1.2.3