From e05f48b425e5069a4a1b6b6e19ecd1287e22a969 Mon Sep 17 00:00:00 2001 From: tibbi Date: Fri, 6 Apr 2018 18:51:21 +0200 Subject: [PATCH] fix #110, allow launching the app without granting Contacts permission --- .../contacts/activities/MainActivity.kt | 13 +- .../contacts/extensions/Context.kt | 5 + .../contacts/helpers/ContactsHelper.kt | 173 ++++++++++-------- 3 files changed, 104 insertions(+), 87 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/MainActivity.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/MainActivity.kt index f05fcdf5..c79686bf 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/MainActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/MainActivity.kt @@ -59,17 +59,12 @@ class MainActivity : SimpleActivity(), RefreshContactsListener { handlePermission(PERMISSION_READ_CONTACTS) { if (it) { handlePermission(PERMISSION_WRITE_CONTACTS) { - if (it) { - storeLocalAccountData() - initFragments() - } else { - toast(R.string.no_contacts_permission) - finish() - } + storeLocalAccountData() + initFragments() } } else { - toast(R.string.no_contacts_permission) - finish() + storeLocalAccountData() + initFragments() } } storeStateVariables() diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Context.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Context.kt index 8731909a..5c1befcc 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Context.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Context.kt @@ -9,7 +9,10 @@ import android.os.Build import android.provider.ContactsContract import android.support.v4.content.FileProvider import com.simplemobiletools.commons.extensions.getIntValue +import com.simplemobiletools.commons.extensions.hasPermission import com.simplemobiletools.commons.extensions.toast +import com.simplemobiletools.commons.helpers.PERMISSION_READ_CONTACTS +import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_CONTACTS import com.simplemobiletools.commons.helpers.isLollipopPlus import com.simplemobiletools.contacts.BuildConfig import com.simplemobiletools.contacts.R @@ -155,3 +158,5 @@ fun Context.getPhotoThumbnailSize(): Int { } return 0 } + +fun Context.hasContactPermissions() = hasPermission(PERMISSION_READ_CONTACTS) && hasPermission(PERMISSION_WRITE_CONTACTS) diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/ContactsHelper.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/ContactsHelper.kt index b2e02e13..3d3b73d3 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/ContactsHelper.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/ContactsHelper.kt @@ -20,87 +20,14 @@ import com.simplemobiletools.commons.helpers.SORT_BY_MIDDLE_NAME import com.simplemobiletools.commons.helpers.SORT_BY_SURNAME import com.simplemobiletools.commons.helpers.SORT_DESCENDING import com.simplemobiletools.contacts.R -import com.simplemobiletools.contacts.extensions.config -import com.simplemobiletools.contacts.extensions.dbHelper -import com.simplemobiletools.contacts.extensions.getByteArray -import com.simplemobiletools.contacts.extensions.getPhotoThumbnailSize +import com.simplemobiletools.contacts.extensions.* import com.simplemobiletools.contacts.models.* class ContactsHelper(val activity: BaseSimpleActivity) { fun getContacts(callback: (ArrayList) -> Unit) { val contacts = SparseArray() Thread { - val uri = ContactsContract.Data.CONTENT_URI - val projection = getContactProjection() - val selection = "${ContactsContract.Data.MIMETYPE} = ?" - val selectionArgs = arrayOf(CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) - val sortOrder = getSortString() - - var cursor: Cursor? = null - try { - cursor = activity.contentResolver.query(uri, projection, selection, selectionArgs, sortOrder) - if (cursor?.moveToFirst() == true) { - do { - val id = cursor.getIntValue(ContactsContract.Data.RAW_CONTACT_ID) - val firstName = cursor.getStringValue(CommonDataKinds.StructuredName.GIVEN_NAME) ?: "" - val middleName = cursor.getStringValue(CommonDataKinds.StructuredName.MIDDLE_NAME) ?: "" - val surname = cursor.getStringValue(CommonDataKinds.StructuredName.FAMILY_NAME) ?: "" - val photoUri = cursor.getStringValue(CommonDataKinds.StructuredName.PHOTO_URI) ?: "" - val number = ArrayList() // proper value is obtained below - val emails = ArrayList() - val addresses = ArrayList
() - val events = ArrayList() - val accountName = cursor.getStringValue(ContactsContract.RawContacts.ACCOUNT_NAME) ?: "" - val starred = cursor.getIntValue(CommonDataKinds.StructuredName.STARRED) - val contactId = cursor.getIntValue(ContactsContract.Data.CONTACT_ID) - val thumbnailUri = cursor.getStringValue(CommonDataKinds.StructuredName.PHOTO_THUMBNAIL_URI) ?: "" - val notes = "" - val groups = ArrayList() - val contact = Contact(id, firstName, middleName, surname, photoUri, number, emails, addresses, events, accountName, - starred, contactId, thumbnailUri, null, notes, groups) - contacts.put(id, contact) - } while (cursor.moveToNext()) - } - } catch (e: Exception) { - activity.showErrorToast(e) - } finally { - cursor?.close() - } - - val phoneNumbers = getPhoneNumbers() - var size = phoneNumbers.size() - for (i in 0 until size) { - val key = phoneNumbers.keyAt(i) - contacts[key]?.phoneNumbers = phoneNumbers.valueAt(i) - } - - val emails = getEmails() - size = emails.size() - for (i in 0 until size) { - val key = emails.keyAt(i) - contacts[key]?.emails = emails.valueAt(i) - } - - val addresses = getAddresses() - size = addresses.size() - for (i in 0 until size) { - val key = addresses.keyAt(i) - contacts[key]?.addresses = addresses.valueAt(i) - } - - val events = getEvents() - size = events.size() - for (i in 0 until size) { - val key = events.keyAt(i) - contacts[key]?.events = events.valueAt(i) - } - - val notes = getNotes() - size = notes.size() - for (i in 0 until size) { - val key = notes.keyAt(i) - contacts[key]?.notes = notes.valueAt(i) - } + getDeviceContacts(contacts) activity.dbHelper.getContacts(activity).forEach { contacts.put(it.id, it) @@ -113,7 +40,7 @@ class ContactsHelper(val activity: BaseSimpleActivity) { // groups are obtained with contactID, not rawID, so assign them to proper contacts like this val groups = getContactGroups(getStoredGroups()) - size = groups.size() + val size = groups.size() for (i in 0 until size) { val key = groups.keyAt(i) resultContacts.firstOrNull { it.contactId == key }?.groups = groups.valueAt(i) @@ -125,6 +52,84 @@ class ContactsHelper(val activity: BaseSimpleActivity) { }.start() } + private fun getDeviceContacts(contacts: SparseArray) { + if (!activity.hasContactPermissions()) { + return + } + + val uri = ContactsContract.Data.CONTENT_URI + val projection = getContactProjection() + val selection = "${ContactsContract.Data.MIMETYPE} = ?" + val selectionArgs = arrayOf(CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) + val sortOrder = getSortString() + + var cursor: Cursor? = null + try { + cursor = activity.contentResolver.query(uri, projection, selection, selectionArgs, sortOrder) + if (cursor?.moveToFirst() == true) { + do { + val id = cursor.getIntValue(ContactsContract.Data.RAW_CONTACT_ID) + val firstName = cursor.getStringValue(CommonDataKinds.StructuredName.GIVEN_NAME) ?: "" + val middleName = cursor.getStringValue(CommonDataKinds.StructuredName.MIDDLE_NAME) ?: "" + val surname = cursor.getStringValue(CommonDataKinds.StructuredName.FAMILY_NAME) ?: "" + val photoUri = cursor.getStringValue(CommonDataKinds.StructuredName.PHOTO_URI) ?: "" + val number = ArrayList() // proper value is obtained below + val emails = ArrayList() + val addresses = ArrayList
() + val events = ArrayList() + val accountName = cursor.getStringValue(ContactsContract.RawContacts.ACCOUNT_NAME) ?: "" + val starred = cursor.getIntValue(CommonDataKinds.StructuredName.STARRED) + val contactId = cursor.getIntValue(ContactsContract.Data.CONTACT_ID) + val thumbnailUri = cursor.getStringValue(CommonDataKinds.StructuredName.PHOTO_THUMBNAIL_URI) ?: "" + val notes = "" + val groups = ArrayList() + val contact = Contact(id, firstName, middleName, surname, photoUri, number, emails, addresses, events, accountName, + starred, contactId, thumbnailUri, null, notes, groups) + contacts.put(id, contact) + } while (cursor.moveToNext()) + } + } catch (e: Exception) { + activity.showErrorToast(e) + } finally { + cursor?.close() + } + + val phoneNumbers = getPhoneNumbers() + var size = phoneNumbers.size() + for (i in 0 until size) { + val key = phoneNumbers.keyAt(i) + contacts[key]?.phoneNumbers = phoneNumbers.valueAt(i) + } + + val emails = getEmails() + size = emails.size() + for (i in 0 until size) { + val key = emails.keyAt(i) + contacts[key]?.emails = emails.valueAt(i) + } + + val addresses = getAddresses() + size = addresses.size() + for (i in 0 until size) { + val key = addresses.keyAt(i) + contacts[key]?.addresses = addresses.valueAt(i) + } + + val events = getEvents() + size = events.size() + for (i in 0 until size) { + val key = events.keyAt(i) + contacts[key]?.events = events.valueAt(i) + } + + val notes = getNotes() + size = notes.size() + for (i in 0 until size) { + val key = notes.keyAt(i) + contacts[key]?.notes = notes.valueAt(i) + } + } + private fun getPhoneNumbers(contactId: Int? = null): SparseArray> { val phoneNumbers = SparseArray>() val uri = CommonDataKinds.Phone.CONTENT_URI @@ -317,6 +322,10 @@ class ContactsHelper(val activity: BaseSimpleActivity) { private fun getContactGroups(storedGroups: ArrayList, contactId: Int? = null): SparseArray> { val groups = SparseArray>() + if (!activity.hasContactPermissions()) { + return groups + } + val uri = ContactsContract.Data.CONTENT_URI val projection = arrayOf( ContactsContract.Data.CONTACT_ID, @@ -357,7 +366,17 @@ class ContactsHelper(val activity: BaseSimpleActivity) { } fun getStoredGroups(): ArrayList { + val groups = getDeviceStoredGroups() + groups.addAll(activity.dbHelper.getGroups()) + return groups + } + + fun getDeviceStoredGroups(): ArrayList { val groups = ArrayList() + if (!activity.hasContactPermissions()) { + return groups + } + val uri = ContactsContract.Groups.CONTENT_URI val projection = arrayOf( ContactsContract.Groups._ID, @@ -389,8 +408,6 @@ class ContactsHelper(val activity: BaseSimpleActivity) { } finally { cursor?.close() } - - groups.addAll(activity.dbHelper.getGroups()) return groups }