properly handle displaying local private photos
This commit is contained in:
parent
192658c0d3
commit
0b9b1b7f1a
|
@ -45,7 +45,7 @@ ext {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.simplemobiletools:commons:3.11.3'
|
||||
implementation 'com.simplemobiletools:commons:3.11.5'
|
||||
implementation 'joda-time:joda-time:2.9.9'
|
||||
implementation 'com.facebook.stetho:stetho:1.5.0'
|
||||
implementation 'com.google.code.gson:gson:2.8.2'
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.simplemobiletools.contacts.activities
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.provider.ContactsContract
|
||||
import android.widget.ImageView
|
||||
|
@ -41,16 +42,17 @@ abstract class ContactActivity : SimpleActivity() {
|
|||
photoView.setPadding(padding, padding, padding, padding)
|
||||
photoView.setImageBitmap(placeholder)
|
||||
currentContactPhotoPath = ""
|
||||
contact!!.photo = null
|
||||
}
|
||||
|
||||
fun updateContactPhoto(path: String, photoView: ImageView) {
|
||||
fun updateContactPhoto(path: String, photoView: ImageView, bitmap: Bitmap? = null) {
|
||||
currentContactPhotoPath = path
|
||||
val options = RequestOptions()
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||
.centerCrop()
|
||||
|
||||
Glide.with(this)
|
||||
.load(path)
|
||||
.load(bitmap ?: path)
|
||||
.transition(DrawableTransitionOptions.withCrossFade())
|
||||
.apply(options)
|
||||
.listener(object : RequestListener<Drawable> {
|
||||
|
|
|
@ -146,10 +146,10 @@ class EditContactActivity : ContactActivity() {
|
|||
|
||||
contact_photo.background = ColorDrawable(config.primaryColor)
|
||||
|
||||
if (contact!!.photoUri.isEmpty()) {
|
||||
if (contact!!.photoUri.isEmpty() && contact!!.photo == null) {
|
||||
showPhotoPlaceholder(contact_photo)
|
||||
} else {
|
||||
updateContactPhoto(contact!!.photoUri, contact_photo)
|
||||
updateContactPhoto(contact!!.photoUri, contact_photo, contact!!.photo)
|
||||
}
|
||||
|
||||
val textColor = config.textColor
|
||||
|
@ -283,7 +283,7 @@ class EditContactActivity : ContactActivity() {
|
|||
private fun setupNewContact() {
|
||||
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE)
|
||||
supportActionBar?.title = resources.getString(R.string.new_contact)
|
||||
contact = Contact(0, "", "", "", "", ArrayList(), ArrayList(), ArrayList(), config.lastUsedContactSource, 0, 0, "")
|
||||
contact = Contact(0, "", "", "", "", ArrayList(), ArrayList(), ArrayList(), config.lastUsedContactSource, 0, 0, "", null)
|
||||
contact_source.text = getPublicContactSource(contact!!.source)
|
||||
contact_source.setOnClickListener {
|
||||
showContactSourcePicker(contact!!.source) {
|
||||
|
@ -577,7 +577,7 @@ class EditContactActivity : ContactActivity() {
|
|||
RadioItem(CHOOSE_PHOTO, getString(R.string.choose_photo))
|
||||
)
|
||||
|
||||
if (currentContactPhotoPath.isNotEmpty()) {
|
||||
if (currentContactPhotoPath.isNotEmpty() || contact!!.photo != null) {
|
||||
items.add(RadioItem(REMOVE_PHOTO, getString(R.string.remove_photo)))
|
||||
}
|
||||
|
||||
|
|
|
@ -98,10 +98,10 @@ class ViewContactActivity : ContactActivity() {
|
|||
|
||||
contact_photo.background = ColorDrawable(config.primaryColor)
|
||||
|
||||
if (contact!!.photoUri.isEmpty()) {
|
||||
if (contact!!.photoUri.isEmpty() && contact!!.photo == null) {
|
||||
showPhotoPlaceholder(contact_photo)
|
||||
} else {
|
||||
updateContactPhoto(contact!!.photoUri, contact_photo)
|
||||
updateContactPhoto(contact!!.photoUri, contact_photo, contact!!.photo)
|
||||
}
|
||||
|
||||
val textColor = config.textColor
|
||||
|
|
|
@ -199,16 +199,26 @@ class ContactsAdapter(activity: SimpleActivity, var contactItems: MutableList<Co
|
|||
contact_tmb.beVisibleIf(showContactThumbnails)
|
||||
|
||||
if (showContactThumbnails) {
|
||||
if (contact.photoUri.isNotEmpty()) {
|
||||
val options = RequestOptions()
|
||||
.signature(ObjectKey(contact.photoUri))
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||
.error(contactDrawable)
|
||||
.centerCrop()
|
||||
when {
|
||||
contact.photoUri.isNotEmpty() -> {
|
||||
val options = RequestOptions()
|
||||
.signature(ObjectKey(contact.photoUri))
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||
.error(contactDrawable)
|
||||
.centerCrop()
|
||||
|
||||
Glide.with(activity).load(contact.photoUri).transition(DrawableTransitionOptions.withCrossFade()).apply(options).into(contact_tmb)
|
||||
} else {
|
||||
contact_tmb.setImageDrawable(contactDrawable)
|
||||
Glide.with(activity).load(contact.photoUri).transition(DrawableTransitionOptions.withCrossFade()).apply(options).into(contact_tmb)
|
||||
}
|
||||
contact.photo != null -> {
|
||||
val options = RequestOptions()
|
||||
.signature(ObjectKey(contact.photo!!))
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||
.error(contactDrawable)
|
||||
.centerCrop()
|
||||
|
||||
Glide.with(activity).load(contact.photo).transition(DrawableTransitionOptions.withCrossFade()).apply(options).into(contact_tmb)
|
||||
}
|
||||
else -> contact_tmb.setImageDrawable(contactDrawable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
package com.simplemobiletools.contacts.extensions
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import java.io.ByteArrayOutputStream
|
||||
|
||||
fun Bitmap.getByteArray(): ByteArray {
|
||||
var baos: ByteArrayOutputStream? = null
|
||||
try {
|
||||
baos = ByteArrayOutputStream()
|
||||
compress(Bitmap.CompressFormat.JPEG, 80, baos)
|
||||
return baos.toByteArray()
|
||||
} finally {
|
||||
baos?.close()
|
||||
}
|
||||
}
|
|
@ -128,3 +128,18 @@ fun Context.getCachePhoto(): File {
|
|||
}
|
||||
|
||||
fun Context.getCachePhotoUri(file: File = getCachePhoto()) = FileProvider.getUriForFile(this, "${BuildConfig.APPLICATION_ID}.provider", file)
|
||||
|
||||
fun Context.getPhotoThumbnailSize(): Int {
|
||||
val uri = ContactsContract.DisplayPhoto.CONTENT_MAX_DIMENSIONS_URI
|
||||
val projection = arrayOf(ContactsContract.DisplayPhoto.THUMBNAIL_MAX_DIM)
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = contentResolver.query(uri, projection, null, null, null)
|
||||
if (cursor?.moveToFirst() == true) {
|
||||
return cursor.getIntValue(ContactsContract.DisplayPhoto.THUMBNAIL_MAX_DIM)
|
||||
}
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@ 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.models.*
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.util.*
|
||||
|
@ -54,7 +56,7 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
|
|||
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 contact = Contact(id, firstName, middleName, surname, photoUri, number, emails, events, accountName, starred, contactId, thumbnailUri)
|
||||
val contact = Contact(id, firstName, middleName, surname, photoUri, number, emails, events, accountName, starred, contactId, thumbnailUri, null)
|
||||
contacts.put(id, contact)
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
|
@ -224,7 +226,7 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
|
|||
val starred = cursor.getIntValue(CommonDataKinds.StructuredName.STARRED)
|
||||
val contactId = cursor.getIntValue(ContactsContract.Data.CONTACT_ID)
|
||||
val thumbnailUri = cursor.getStringValue(CommonDataKinds.StructuredName.PHOTO_THUMBNAIL_URI) ?: ""
|
||||
return Contact(id, firstName, middleName, surname, photoUri, number, emails, events, accountName, starred, contactId, thumbnailUri)
|
||||
return Contact(id, firstName, middleName, surname, photoUri, number, emails, events, accountName, starred, contactId, thumbnailUri, null)
|
||||
}
|
||||
} finally {
|
||||
cursor?.close()
|
||||
|
@ -429,12 +431,12 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
|
|||
val photoUri = Uri.parse(contact.photoUri)
|
||||
val bitmap = MediaStore.Images.Media.getBitmap(activity.contentResolver, photoUri)
|
||||
|
||||
val thumbnailSize = getThumbnailSize()
|
||||
val thumbnailSize = activity.getPhotoThumbnailSize()
|
||||
val scaledPhoto = Bitmap.createScaledBitmap(bitmap, thumbnailSize, thumbnailSize, false)
|
||||
val scaledSizePhotoData = bitmapToByteArray(scaledPhoto)
|
||||
val scaledSizePhotoData = scaledPhoto.getByteArray()
|
||||
scaledPhoto.recycle()
|
||||
|
||||
val fullSizePhotoData = bitmapToByteArray(bitmap)
|
||||
val fullSizePhotoData = bitmap.getByteArray()
|
||||
bitmap.recycle()
|
||||
|
||||
ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).apply {
|
||||
|
@ -522,11 +524,11 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
|
|||
val photoUri = Uri.parse(contact.photoUri)
|
||||
val bitmap = MediaStore.Images.Media.getBitmap(activity.contentResolver, photoUri)
|
||||
|
||||
val thumbnailSize = getThumbnailSize()
|
||||
val thumbnailSize = activity.getPhotoThumbnailSize()
|
||||
val scaledPhoto = Bitmap.createScaledBitmap(bitmap, thumbnailSize, thumbnailSize, false)
|
||||
scaledSizePhotoData = bitmapToByteArray(scaledPhoto)
|
||||
scaledSizePhotoData = scaledPhoto.getByteArray()
|
||||
|
||||
fullSizePhotoData = bitmapToByteArray(bitmap)
|
||||
fullSizePhotoData = bitmap.getByteArray()
|
||||
scaledPhoto.recycle()
|
||||
bitmap.recycle()
|
||||
|
||||
|
@ -677,19 +679,4 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
|
|||
activity.showErrorToast(e)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getThumbnailSize(): Int {
|
||||
val uri = ContactsContract.DisplayPhoto.CONTENT_MAX_DIMENSIONS_URI
|
||||
val projection = arrayOf(ContactsContract.DisplayPhoto.THUMBNAIL_MAX_DIM)
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = activity.contentResolver.query(uri, projection, null, null, null)
|
||||
if (cursor?.moveToFirst() == true) {
|
||||
return cursor.getIntValue(ContactsContract.DisplayPhoto.THUMBNAIL_MAX_DIM)
|
||||
}
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,17 +4,23 @@ import android.content.ContentValues
|
|||
import android.content.Context
|
||||
import android.database.sqlite.SQLiteDatabase
|
||||
import android.database.sqlite.SQLiteOpenHelper
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.net.Uri
|
||||
import android.provider.MediaStore
|
||||
import android.text.TextUtils
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.simplemobiletools.commons.extensions.getBlobValue
|
||||
import com.simplemobiletools.commons.extensions.getIntValue
|
||||
import com.simplemobiletools.commons.extensions.getStringValue
|
||||
import com.simplemobiletools.contacts.extensions.getByteArray
|
||||
import com.simplemobiletools.contacts.extensions.getPhotoThumbnailSize
|
||||
import com.simplemobiletools.contacts.models.Contact
|
||||
import com.simplemobiletools.contacts.models.Email
|
||||
import com.simplemobiletools.contacts.models.Event
|
||||
import com.simplemobiletools.contacts.models.PhoneNumber
|
||||
|
||||
|
||||
class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(context, DB_NAME, null, DB_VERSION) {
|
||||
private val CONTACTS_TABLE_NAME = "contacts"
|
||||
private val COL_ID = "id"
|
||||
|
@ -86,9 +92,26 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont
|
|||
put(COL_EMAILS, Gson().toJson(contact.emails))
|
||||
put(COL_EVENTS, Gson().toJson(contact.events))
|
||||
put(COL_STARRED, contact.starred)
|
||||
|
||||
if (contact.photoUri.isNotEmpty()) {
|
||||
put(COL_PHOTO, getPhotoByteArray(contact.photoUri))
|
||||
} else if (contact.photo == null) {
|
||||
putNull(COL_PHOTO)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getPhotoByteArray(uri: String): ByteArray {
|
||||
val photoUri = Uri.parse(uri)
|
||||
val bitmap = MediaStore.Images.Media.getBitmap(context.contentResolver, photoUri)
|
||||
|
||||
val thumbnailSize = context.getPhotoThumbnailSize()
|
||||
val scaledPhoto = Bitmap.createScaledBitmap(bitmap, thumbnailSize, thumbnailSize, false)
|
||||
val scaledSizePhotoData = scaledPhoto.getByteArray()
|
||||
scaledPhoto.recycle()
|
||||
return scaledSizePhotoData
|
||||
}
|
||||
|
||||
fun toggleFavorites(ids: Array<String>, addToFavorites: Boolean) {
|
||||
val contactValues = ContentValues()
|
||||
contactValues.put(COL_STARRED, if (addToFavorites) 1 else 0)
|
||||
|
@ -100,7 +123,7 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont
|
|||
|
||||
fun getContacts(selection: String? = null, selectionArgs: Array<String>? = null): ArrayList<Contact> {
|
||||
val contacts = ArrayList<Contact>()
|
||||
val projection = arrayOf(COL_ID, COL_FIRST_NAME, COL_MIDDLE_NAME, COL_SURNAME, COL_PHONE_NUMBERS, COL_EMAILS, COL_EVENTS, COL_STARRED)
|
||||
val projection = arrayOf(COL_ID, COL_FIRST_NAME, COL_MIDDLE_NAME, COL_SURNAME, COL_PHONE_NUMBERS, COL_EMAILS, COL_EVENTS, COL_STARRED, COL_PHOTO)
|
||||
val cursor = mDb.query(CONTACTS_TABLE_NAME, projection, selection, selectionArgs, null, null, null)
|
||||
cursor.use {
|
||||
while (cursor.moveToNext()) {
|
||||
|
@ -121,8 +144,15 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont
|
|||
val eventsToken = object : TypeToken<List<Event>>() {}.type
|
||||
val events = Gson().fromJson<ArrayList<Event>>(eventsJson, eventsToken) ?: ArrayList(1)
|
||||
|
||||
val photoByteArray = cursor.getBlobValue(COL_PHOTO) ?: null
|
||||
val photo = if (photoByteArray?.isNotEmpty() == true) {
|
||||
BitmapFactory.decodeByteArray(photoByteArray, 0, photoByteArray.size)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
val starred = cursor.getIntValue(COL_STARRED)
|
||||
val contact = Contact(id, firstName, middleName, surname, "", phoneNumbers, emails, events, SMT_PRIVATE, starred, id, "")
|
||||
val contact = Contact(id, firstName, middleName, surname, "", phoneNumbers, emails, events, SMT_PRIVATE, starred, id, "", photo)
|
||||
contacts.add(contact)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -199,7 +199,7 @@ class VcfImporter(val activity: SimpleActivity) {
|
|||
}
|
||||
|
||||
private fun saveContact(source: String) {
|
||||
val contact = Contact(0, curFirstName, curMiddleName, curSurname, curPhotoUri, curPhoneNumbers, curEmails, curEvents, source, 0, 0, "")
|
||||
val contact = Contact(0, curFirstName, curMiddleName, curSurname, curPhotoUri, curPhoneNumbers, curEmails, curEvents, source, 0, 0, "", null)
|
||||
if (ContactsHelper(activity).insertContact(contact)) {
|
||||
contactsImported++
|
||||
}
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
package com.simplemobiletools.contacts.models
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import com.simplemobiletools.commons.helpers.SORT_BY_FIRST_NAME
|
||||
import com.simplemobiletools.commons.helpers.SORT_BY_MIDDLE_NAME
|
||||
import com.simplemobiletools.commons.helpers.SORT_DESCENDING
|
||||
|
||||
data class Contact(val id: Int, var firstName: String, var middleName: String, var surname: String, var photoUri: String,
|
||||
var phoneNumbers: ArrayList<PhoneNumber>, var emails: ArrayList<Email>, var events: ArrayList<Event>, var source: String,
|
||||
var starred: Int, val contactId: Int, val thumbnailUri: String) : Comparable<Contact> {
|
||||
var starred: Int, val contactId: Int, val thumbnailUri: String, var photo: Bitmap?) : Comparable<Contact> {
|
||||
companion object {
|
||||
var sorting = 0
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue