From 8e207414ef4c2037411e593bac2990b199bf3835 Mon Sep 17 00:00:00 2001 From: tibbi Date: Sun, 11 Feb 2018 13:10:21 +0100 Subject: [PATCH] add a new source for storing contacts locally, without sharing with other apps --- .../activities/EditContactActivity.kt | 2 +- .../contacts/extensions/Activity.kt | 6 +- .../contacts/helpers/Constants.kt | 1 + .../contacts/helpers/ContactsHelper.kt | 203 +++++++++--------- 4 files changed, 111 insertions(+), 101 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/EditContactActivity.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/EditContactActivity.kt index ecf3c3ce..3b8b0092 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/EditContactActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/EditContactActivity.kt @@ -287,7 +287,7 @@ class EditContactActivity : ContactActivity() { contact_source.text = getPublicContactSource(contact!!.source) contact_source.setOnClickListener { showContactSourcePicker(contact!!.source) { - contact!!.source = it + contact!!.source = if (it == getString(R.string.phone_storage_hidden)) SMT_PRIVATE else it contact_source.text = getPublicContactSource(it) } } diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Activity.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Activity.kt index a7e390a9..02a87f7b 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Activity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Activity.kt @@ -2,7 +2,6 @@ package com.simplemobiletools.contacts.extensions import android.content.Intent import android.net.Uri -import com.simplemobiletools.commons.R import com.simplemobiletools.commons.activities.BaseSimpleActivity import com.simplemobiletools.commons.dialogs.RadioGroupDialog import com.simplemobiletools.commons.extensions.getFilePublicUri @@ -11,6 +10,7 @@ import com.simplemobiletools.commons.extensions.toast import com.simplemobiletools.commons.helpers.PERMISSION_CALL_PHONE import com.simplemobiletools.commons.models.RadioItem import com.simplemobiletools.contacts.BuildConfig +import com.simplemobiletools.contacts.R import com.simplemobiletools.contacts.activities.SimpleActivity import com.simplemobiletools.contacts.helpers.ContactsHelper import com.simplemobiletools.contacts.helpers.VcfExporter @@ -56,7 +56,7 @@ fun SimpleActivity.showContactSourcePicker(currentSource: String, callback: (new sources.forEachIndexed { index, account -> var publicAccount = account if (account == config.localAccountName) { - publicAccount = getString(com.simplemobiletools.contacts.R.string.phone_storage) + publicAccount = getString(R.string.phone_storage) } items.add(RadioItem(index, publicAccount)) @@ -73,7 +73,7 @@ fun SimpleActivity.showContactSourcePicker(currentSource: String, callback: (new } } -fun SimpleActivity.getPublicContactSource(source: String) = if (source == config.localAccountName) getString(com.simplemobiletools.contacts.R.string.phone_storage) else source +fun SimpleActivity.getPublicContactSource(source: String) = if (source == config.localAccountName) getString(R.string.phone_storage) else source fun BaseSimpleActivity.shareContacts(contacts: ArrayList) { val file = getTempFile() diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Constants.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Constants.kt index fa0e6a8c..c8dbce1b 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Constants.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Constants.kt @@ -14,6 +14,7 @@ const val LOCAL_ACCOUNT_TYPE = "local_account_type" const val ON_CONTACT_CLICK = "on_contact_click" const val CONTACT_ID = "contact_id" +const val SMT_PRIVATE = "smt_private" // contact photo changes const val PHOTO_ADDED = 1 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 e4903577..d5d8de29 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/ContactsHelper.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/ContactsHelper.kt @@ -227,7 +227,7 @@ class ContactsHelper(val activity: BaseSimpleActivity) { } fun getContactSources(callback: (ArrayList) -> Unit) { - val sources = HashSet() + val sources = LinkedHashSet() Thread { val uri = ContactsContract.RawContacts.CONTENT_URI val projection = arrayOf(ContactsContract.RawContacts.ACCOUNT_NAME, ContactsContract.RawContacts.ACCOUNT_TYPE) @@ -247,6 +247,7 @@ class ContactsHelper(val activity: BaseSimpleActivity) { cursor?.close() } + sources.add(ContactSource(activity.getString(R.string.phone_storage_hidden), SMT_PRIVATE)) callback(ArrayList(sources)) }.start() } @@ -451,109 +452,117 @@ class ContactsHelper(val activity: BaseSimpleActivity) { } fun insertContact(contact: Contact): Boolean { - return try { - val operations = ArrayList() - ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI).apply { - withValue(ContactsContract.RawContacts.ACCOUNT_NAME, contact.source) - withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, getContactSourceType(contact.source)) - operations.add(build()) - } - - // names - ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).apply { - withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) - withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) - withValue(CommonDataKinds.StructuredName.GIVEN_NAME, contact.firstName) - withValue(CommonDataKinds.StructuredName.MIDDLE_NAME, contact.middleName) - withValue(CommonDataKinds.StructuredName.FAMILY_NAME, contact.surname) - operations.add(build()) - } - - // phone numbers - contact.phoneNumbers.forEach { - ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).apply { - withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) - withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.Phone.CONTENT_ITEM_TYPE) - withValue(CommonDataKinds.Phone.NUMBER, it.value) - withValue(CommonDataKinds.Phone.TYPE, it.type) - operations.add(build()) - } - } - - // emails - contact.emails.forEach { - ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).apply { - withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) - withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.Email.CONTENT_ITEM_TYPE) - withValue(CommonDataKinds.Email.DATA, it.value) - withValue(CommonDataKinds.Email.TYPE, it.type) - operations.add(build()) - } - } - - // events - contact.events.forEach { - ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).apply { - withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) - withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.Event.CONTENT_ITEM_TYPE) - withValue(CommonDataKinds.Event.START_DATE, it.value) - withValue(CommonDataKinds.Event.TYPE, it.type) - operations.add(build()) - } - } - - // photo (inspired by https://gist.github.com/slightfoot/5985900) - var fullSizePhotoData: ByteArray? = null - var scaledSizePhotoData: ByteArray? - if (contact.photoUri.isNotEmpty()) { - val photoUri = Uri.parse(contact.photoUri) - val bitmap = MediaStore.Images.Media.getBitmap(activity.contentResolver, photoUri) - - val thumbnailSize = getThumbnailSize() - val scaledPhoto = Bitmap.createScaledBitmap(bitmap, thumbnailSize, thumbnailSize, false) - scaledSizePhotoData = bitmapToByteArray(scaledPhoto) - - fullSizePhotoData = bitmapToByteArray(bitmap) - scaledPhoto.recycle() - bitmap.recycle() - - ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).apply { - withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) - withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.Photo.CONTENT_ITEM_TYPE) - withValue(CommonDataKinds.Photo.PHOTO, scaledSizePhotoData) - operations.add(build()) - } - } - - val results: Array + return if (contact.source == SMT_PRIVATE) { + insertLocalContact(contact) + } else { try { - results = activity.contentResolver.applyBatch(ContactsContract.AUTHORITY, operations) - } finally { - scaledSizePhotoData = null - } + val operations = ArrayList() + ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI).apply { + withValue(ContactsContract.RawContacts.ACCOUNT_NAME, contact.source) + withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, getContactSourceType(contact.source)) + operations.add(build()) + } - // fullsize photo - val rawId = ContentUris.parseId(results[0].uri) - if (contact.photoUri.isNotEmpty() && fullSizePhotoData != null) { - addFullSizePhoto(rawId, fullSizePhotoData) - } + // names + ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).apply { + withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) + withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) + withValue(CommonDataKinds.StructuredName.GIVEN_NAME, contact.firstName) + withValue(CommonDataKinds.StructuredName.MIDDLE_NAME, contact.middleName) + withValue(CommonDataKinds.StructuredName.FAMILY_NAME, contact.surname) + operations.add(build()) + } - // favorite - val userId = getRealContactId(rawId) - if (userId != 0 && contact.starred == 1) { - val uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, userId.toString()) - val contentValues = ContentValues(1) - contentValues.put(ContactsContract.Contacts.STARRED, contact.starred) - activity.contentResolver.update(uri, contentValues, null, null) - } + // phone numbers + contact.phoneNumbers.forEach { + ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).apply { + withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) + withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.Phone.CONTENT_ITEM_TYPE) + withValue(CommonDataKinds.Phone.NUMBER, it.value) + withValue(CommonDataKinds.Phone.TYPE, it.type) + operations.add(build()) + } + } - true - } catch (e: Exception) { - activity.showErrorToast(e) - false + // emails + contact.emails.forEach { + ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).apply { + withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) + withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.Email.CONTENT_ITEM_TYPE) + withValue(CommonDataKinds.Email.DATA, it.value) + withValue(CommonDataKinds.Email.TYPE, it.type) + operations.add(build()) + } + } + + // events + contact.events.forEach { + ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).apply { + withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) + withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.Event.CONTENT_ITEM_TYPE) + withValue(CommonDataKinds.Event.START_DATE, it.value) + withValue(CommonDataKinds.Event.TYPE, it.type) + operations.add(build()) + } + } + + // photo (inspired by https://gist.github.com/slightfoot/5985900) + var fullSizePhotoData: ByteArray? = null + var scaledSizePhotoData: ByteArray? + if (contact.photoUri.isNotEmpty()) { + val photoUri = Uri.parse(contact.photoUri) + val bitmap = MediaStore.Images.Media.getBitmap(activity.contentResolver, photoUri) + + val thumbnailSize = getThumbnailSize() + val scaledPhoto = Bitmap.createScaledBitmap(bitmap, thumbnailSize, thumbnailSize, false) + scaledSizePhotoData = bitmapToByteArray(scaledPhoto) + + fullSizePhotoData = bitmapToByteArray(bitmap) + scaledPhoto.recycle() + bitmap.recycle() + + ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).apply { + withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) + withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.Photo.CONTENT_ITEM_TYPE) + withValue(CommonDataKinds.Photo.PHOTO, scaledSizePhotoData) + operations.add(build()) + } + } + + val results: Array + try { + results = activity.contentResolver.applyBatch(ContactsContract.AUTHORITY, operations) + } finally { + scaledSizePhotoData = null + } + + // fullsize photo + val rawId = ContentUris.parseId(results[0].uri) + if (contact.photoUri.isNotEmpty() && fullSizePhotoData != null) { + addFullSizePhoto(rawId, fullSizePhotoData) + } + + // favorite + val userId = getRealContactId(rawId) + if (userId != 0 && contact.starred == 1) { + val uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, userId.toString()) + val contentValues = ContentValues(1) + contentValues.put(ContactsContract.Contacts.STARRED, contact.starred) + activity.contentResolver.update(uri, contentValues, null, null) + } + + true + } catch (e: Exception) { + activity.showErrorToast(e) + false + } } } + private fun insertLocalContact(contact: Contact): Boolean { + return true + } + private fun addFullSizePhoto(contactId: Long, fullSizePhotoData: ByteArray) { val baseUri = ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, contactId) val displayPhotoUri = Uri.withAppendedPath(baseUri, ContactsContract.RawContacts.DisplayPhoto.CONTENT_DIRECTORY)