From 0e1009b499c1f9a55f21d0fc77fc5e509d3af2c8 Mon Sep 17 00:00:00 2001 From: tibbi Date: Mon, 15 Jan 2018 14:08:52 +0100 Subject: [PATCH] handle contact photo importing --- .../contacts/activities/ContactActivity.kt | 11 ---- .../contacts/extensions/Context.kt | 16 +++++ .../contacts/helpers/Constants.kt | 1 + .../contacts/helpers/ContactsHelper.kt | 2 +- .../contacts/helpers/VcfImporter.kt | 61 ++++++++++++++++++- 5 files changed, 77 insertions(+), 14 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/ContactActivity.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/ContactActivity.kt index ffd137d7..70ab342c 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/ContactActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/ContactActivity.kt @@ -737,17 +737,6 @@ class ContactActivity : SimpleActivity() { } } - private fun getCachePhotoUri(): Uri { - val imagesFolder = File(cacheDir, "my_cache") - if (!imagesFolder.exists()) { - imagesFolder.mkdirs() - } - - val file = File(imagesFolder, "Photo_${System.currentTimeMillis()}.jpg") - file.createNewFile() - return FileProvider.getUriForFile(this, "${BuildConfig.APPLICATION_ID}.provider", file) - } - private fun getPhoneNumberTextId(type: Int) = when (type) { CommonDataKinds.Phone.TYPE_MOBILE -> R.string.mobile CommonDataKinds.Phone.TYPE_HOME -> R.string.home 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 c738891a..c8e5c5bd 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Context.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Context.kt @@ -7,14 +7,17 @@ import android.database.Cursor import android.net.Uri import android.os.Build import android.provider.ContactsContract +import android.support.v4.content.FileProvider import com.simplemobiletools.commons.R import com.simplemobiletools.commons.extensions.getIntValue import com.simplemobiletools.commons.extensions.isLollipopPlus import com.simplemobiletools.commons.extensions.toast +import com.simplemobiletools.contacts.BuildConfig import com.simplemobiletools.contacts.activities.ContactActivity import com.simplemobiletools.contacts.helpers.CONTACT_ID import com.simplemobiletools.contacts.helpers.Config import com.simplemobiletools.contacts.models.Contact +import java.io.File val Context.config: Config get() = Config.newInstance(applicationContext) @@ -94,3 +97,16 @@ fun lookupContactUri(lookup: String, context: Context): Uri { val lookupUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookup) return ContactsContract.Contacts.lookupContact(context.contentResolver, lookupUri) } + +fun Context.getCachePhoto(): File { + val imagesFolder = File(cacheDir, "my_cache") + if (!imagesFolder.exists()) { + imagesFolder.mkdirs() + } + + val file = File(imagesFolder, "Photo_${System.currentTimeMillis()}.jpg") + file.createNewFile() + return file +} + +fun Context.getCachePhotoUri(file: File = getCachePhoto()) = FileProvider.getUriForFile(this, "${BuildConfig.APPLICATION_ID}.provider", file) 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 5559ff4d..3c4d4a3e 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Constants.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Constants.kt @@ -32,6 +32,7 @@ val BDAY = "BDAY:" val ANNIVERSARY = "ANNIVERSARY:" val PHOTO = "PHOTO" val EMAIL = "EMAIL" +val BASE64 = "BASE64" // phone number/email types val CELL = "CELL" 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 0875ca3a..e178eb24 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/ContactsHelper.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/ContactsHelper.kt @@ -483,9 +483,9 @@ class ContactsHelper(val activity: BaseSimpleActivity) { val thumbnailSize = getThumbnailSize() val scaledPhoto = Bitmap.createScaledBitmap(bitmap, thumbnailSize, thumbnailSize, false) scaledSizePhotoData = bitmapToByteArray(scaledPhoto) - scaledPhoto.recycle() fullSizePhotoData = bitmapToByteArray(bitmap) + scaledPhoto.recycle() bitmap.recycle() ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).apply { diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/VcfImporter.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/VcfImporter.kt index 069cdc70..2e5104d5 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/VcfImporter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/VcfImporter.kt @@ -1,15 +1,22 @@ package com.simplemobiletools.contacts.helpers +import android.graphics.Bitmap +import android.graphics.BitmapFactory import android.provider.ContactsContract.CommonDataKinds +import android.util.Base64 import android.widget.Toast import com.simplemobiletools.commons.extensions.showErrorToast import com.simplemobiletools.contacts.activities.SimpleActivity +import com.simplemobiletools.contacts.extensions.getCachePhoto +import com.simplemobiletools.contacts.extensions.getCachePhotoUri import com.simplemobiletools.contacts.helpers.VcfImporter.ImportResult.* import com.simplemobiletools.contacts.models.Contact import com.simplemobiletools.contacts.models.Email import com.simplemobiletools.contacts.models.Event import com.simplemobiletools.contacts.models.PhoneNumber import java.io.File +import java.io.FileOutputStream + class VcfImporter(val activity: SimpleActivity) { enum class ImportResult { @@ -19,10 +26,15 @@ class VcfImporter(val activity: SimpleActivity) { private var curFirstName = "" private var curMiddleName = "" private var curSurname = "" + private var curPhotoUri = "" private var curPhoneNumbers = ArrayList() private var curEmails = ArrayList() private var curEvents = ArrayList() + private var isGettingPhoto = false + private var currentPhotoString = StringBuilder() + private var currentPhotoCompressionFormat = Bitmap.CompressFormat.JPEG + private var contactsImported = 0 private var contactsFailed = 0 @@ -38,6 +50,10 @@ class VcfImporter(val activity: SimpleActivity) { while (true) { val line = it.readLine() ?: break if (line.trim().isEmpty()) { + if (isGettingPhoto) { + savePhoto() + isGettingPhoto = false + } continue } @@ -48,7 +64,9 @@ class VcfImporter(val activity: SimpleActivity) { line.startsWith(EMAIL) -> addEmail(line.substring(EMAIL.length)) line.startsWith(BDAY) -> addBirthday(line.substring(BDAY.length)) line.startsWith(ANNIVERSARY) -> addAnniversary(line.substring(ANNIVERSARY.length)) + line.startsWith(PHOTO) -> addPhoto(line.substring(PHOTO.length)) line == END_VCARD -> saveContact(targetContactSource) + isGettingPhoto -> currentPhotoString.append(line.trim()) } } } @@ -78,7 +96,7 @@ class VcfImporter(val activity: SimpleActivity) { if (rawType.contains('=')) { val types = rawType.split('=') if (types.any { it.contains(';') }) { - subType = types[1].split(';').first() + subType = types[1].split(';')[0] } rawType = types.last() } @@ -126,8 +144,42 @@ class VcfImporter(val activity: SimpleActivity) { curEvents.add(Event(anniversary, CommonDataKinds.Event.TYPE_ANNIVERSARY)) } + private fun addPhoto(photo: String) { + val photoParts = photo.trimStart(';').split(';') + if (photoParts.size == 2) { + val typeParts = photoParts[1].split(':') + currentPhotoCompressionFormat = getPhotoCompressionFormat(typeParts[0]) + val encoding = photoParts[0].split('=').last() + if (encoding == BASE64) { + isGettingPhoto = true + currentPhotoString.append(typeParts[1].trim()) + } + } + } + + private fun getPhotoCompressionFormat(type: String) = when (type.toLowerCase()) { + "png" -> Bitmap.CompressFormat.PNG + "webp" -> Bitmap.CompressFormat.WEBP + else -> Bitmap.CompressFormat.JPEG + } + + private fun savePhoto() { + val file = activity.getCachePhoto() + val imageAsBytes = Base64.decode(currentPhotoString.toString().toByteArray(), Base64.DEFAULT) + val bitmap = BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.size) + var fileOutputStream: FileOutputStream? = null + try { + fileOutputStream = FileOutputStream(file) + bitmap.compress(currentPhotoCompressionFormat, 100, fileOutputStream) + } finally { + fileOutputStream?.close() + } + + curPhotoUri = activity.getCachePhotoUri(file).toString() + } + private fun saveContact(source: String) { - val contact = Contact(0, curFirstName, curMiddleName, curSurname, "", curPhoneNumbers, curEmails, curEvents, source, 0, 0) + val contact = Contact(0, curFirstName, curMiddleName, curSurname, curPhotoUri, curPhoneNumbers, curEmails, curEvents, source, 0, 0) if (ContactsHelper(activity).insertContact(contact)) { contactsImported++ } @@ -137,8 +189,13 @@ class VcfImporter(val activity: SimpleActivity) { curFirstName = "" curMiddleName = "" curSurname = "" + curPhotoUri = "" curPhoneNumbers = ArrayList() curEmails = ArrayList() curEvents = ArrayList() + + isGettingPhoto = false + currentPhotoString = StringBuilder() + currentPhotoCompressionFormat = Bitmap.CompressFormat.JPEG } }