Skip to content

Commit 0b9b1b7

Browse files
committed
properly handle displaying local private photos
1 parent 192658c commit 0b9b1b7

File tree

11 files changed

+107
-47
lines changed

11 files changed

+107
-47
lines changed

app/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ ext {
4545
}
4646

4747
dependencies {
48-
implementation 'com.simplemobiletools:commons:3.11.3'
48+
implementation 'com.simplemobiletools:commons:3.11.5'
4949
implementation 'joda-time:joda-time:2.9.9'
5050
implementation 'com.facebook.stetho:stetho:1.5.0'
5151
implementation 'com.google.code.gson:gson:2.8.2'

app/src/main/kotlin/com/simplemobiletools/contacts/activities/ContactActivity.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.simplemobiletools.contacts.activities
22

3+
import android.graphics.Bitmap
34
import android.graphics.drawable.Drawable
45
import android.provider.ContactsContract
56
import android.widget.ImageView
@@ -41,16 +42,17 @@ abstract class ContactActivity : SimpleActivity() {
4142
photoView.setPadding(padding, padding, padding, padding)
4243
photoView.setImageBitmap(placeholder)
4344
currentContactPhotoPath = ""
45+
contact!!.photo = null
4446
}
4547

46-
fun updateContactPhoto(path: String, photoView: ImageView) {
48+
fun updateContactPhoto(path: String, photoView: ImageView, bitmap: Bitmap? = null) {
4749
currentContactPhotoPath = path
4850
val options = RequestOptions()
4951
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
5052
.centerCrop()
5153

5254
Glide.with(this)
53-
.load(path)
55+
.load(bitmap ?: path)
5456
.transition(DrawableTransitionOptions.withCrossFade())
5557
.apply(options)
5658
.listener(object : RequestListener<Drawable> {

app/src/main/kotlin/com/simplemobiletools/contacts/activities/EditContactActivity.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,10 @@ class EditContactActivity : ContactActivity() {
146146

147147
contact_photo.background = ColorDrawable(config.primaryColor)
148148

149-
if (contact!!.photoUri.isEmpty()) {
149+
if (contact!!.photoUri.isEmpty() && contact!!.photo == null) {
150150
showPhotoPlaceholder(contact_photo)
151151
} else {
152-
updateContactPhoto(contact!!.photoUri, contact_photo)
152+
updateContactPhoto(contact!!.photoUri, contact_photo, contact!!.photo)
153153
}
154154

155155
val textColor = config.textColor
@@ -283,7 +283,7 @@ class EditContactActivity : ContactActivity() {
283283
private fun setupNewContact() {
284284
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE)
285285
supportActionBar?.title = resources.getString(R.string.new_contact)
286-
contact = Contact(0, "", "", "", "", ArrayList(), ArrayList(), ArrayList(), config.lastUsedContactSource, 0, 0, "")
286+
contact = Contact(0, "", "", "", "", ArrayList(), ArrayList(), ArrayList(), config.lastUsedContactSource, 0, 0, "", null)
287287
contact_source.text = getPublicContactSource(contact!!.source)
288288
contact_source.setOnClickListener {
289289
showContactSourcePicker(contact!!.source) {
@@ -577,7 +577,7 @@ class EditContactActivity : ContactActivity() {
577577
RadioItem(CHOOSE_PHOTO, getString(R.string.choose_photo))
578578
)
579579

580-
if (currentContactPhotoPath.isNotEmpty()) {
580+
if (currentContactPhotoPath.isNotEmpty() || contact!!.photo != null) {
581581
items.add(RadioItem(REMOVE_PHOTO, getString(R.string.remove_photo)))
582582
}
583583

app/src/main/kotlin/com/simplemobiletools/contacts/activities/ViewContactActivity.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,10 @@ class ViewContactActivity : ContactActivity() {
9898

9999
contact_photo.background = ColorDrawable(config.primaryColor)
100100

101-
if (contact!!.photoUri.isEmpty()) {
101+
if (contact!!.photoUri.isEmpty() && contact!!.photo == null) {
102102
showPhotoPlaceholder(contact_photo)
103103
} else {
104-
updateContactPhoto(contact!!.photoUri, contact_photo)
104+
updateContactPhoto(contact!!.photoUri, contact_photo, contact!!.photo)
105105
}
106106

107107
val textColor = config.textColor

app/src/main/kotlin/com/simplemobiletools/contacts/adapters/ContactsAdapter.kt

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -199,16 +199,26 @@ class ContactsAdapter(activity: SimpleActivity, var contactItems: MutableList<Co
199199
contact_tmb.beVisibleIf(showContactThumbnails)
200200

201201
if (showContactThumbnails) {
202-
if (contact.photoUri.isNotEmpty()) {
203-
val options = RequestOptions()
204-
.signature(ObjectKey(contact.photoUri))
205-
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
206-
.error(contactDrawable)
207-
.centerCrop()
208-
209-
Glide.with(activity).load(contact.photoUri).transition(DrawableTransitionOptions.withCrossFade()).apply(options).into(contact_tmb)
210-
} else {
211-
contact_tmb.setImageDrawable(contactDrawable)
202+
when {
203+
contact.photoUri.isNotEmpty() -> {
204+
val options = RequestOptions()
205+
.signature(ObjectKey(contact.photoUri))
206+
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
207+
.error(contactDrawable)
208+
.centerCrop()
209+
210+
Glide.with(activity).load(contact.photoUri).transition(DrawableTransitionOptions.withCrossFade()).apply(options).into(contact_tmb)
211+
}
212+
contact.photo != null -> {
213+
val options = RequestOptions()
214+
.signature(ObjectKey(contact.photo!!))
215+
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
216+
.error(contactDrawable)
217+
.centerCrop()
218+
219+
Glide.with(activity).load(contact.photo).transition(DrawableTransitionOptions.withCrossFade()).apply(options).into(contact_tmb)
220+
}
221+
else -> contact_tmb.setImageDrawable(contactDrawable)
212222
}
213223
}
214224
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.simplemobiletools.contacts.extensions
2+
3+
import android.graphics.Bitmap
4+
import java.io.ByteArrayOutputStream
5+
6+
fun Bitmap.getByteArray(): ByteArray {
7+
var baos: ByteArrayOutputStream? = null
8+
try {
9+
baos = ByteArrayOutputStream()
10+
compress(Bitmap.CompressFormat.JPEG, 80, baos)
11+
return baos.toByteArray()
12+
} finally {
13+
baos?.close()
14+
}
15+
}

app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Context.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,3 +128,18 @@ fun Context.getCachePhoto(): File {
128128
}
129129

130130
fun Context.getCachePhotoUri(file: File = getCachePhoto()) = FileProvider.getUriForFile(this, "${BuildConfig.APPLICATION_ID}.provider", file)
131+
132+
fun Context.getPhotoThumbnailSize(): Int {
133+
val uri = ContactsContract.DisplayPhoto.CONTENT_MAX_DIMENSIONS_URI
134+
val projection = arrayOf(ContactsContract.DisplayPhoto.THUMBNAIL_MAX_DIM)
135+
var cursor: Cursor? = null
136+
try {
137+
cursor = contentResolver.query(uri, projection, null, null, null)
138+
if (cursor?.moveToFirst() == true) {
139+
return cursor.getIntValue(ContactsContract.DisplayPhoto.THUMBNAIL_MAX_DIM)
140+
}
141+
} finally {
142+
cursor?.close()
143+
}
144+
return 0
145+
}

app/src/main/kotlin/com/simplemobiletools/contacts/helpers/ContactsHelper.kt

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import com.simplemobiletools.commons.helpers.SORT_DESCENDING
2323
import com.simplemobiletools.contacts.R
2424
import com.simplemobiletools.contacts.extensions.config
2525
import com.simplemobiletools.contacts.extensions.dbHelper
26+
import com.simplemobiletools.contacts.extensions.getByteArray
27+
import com.simplemobiletools.contacts.extensions.getPhotoThumbnailSize
2628
import com.simplemobiletools.contacts.models.*
2729
import java.io.ByteArrayOutputStream
2830
import java.util.*
@@ -54,7 +56,7 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
5456
val starred = cursor.getIntValue(CommonDataKinds.StructuredName.STARRED)
5557
val contactId = cursor.getIntValue(ContactsContract.Data.CONTACT_ID)
5658
val thumbnailUri = cursor.getStringValue(CommonDataKinds.StructuredName.PHOTO_THUMBNAIL_URI) ?: ""
57-
val contact = Contact(id, firstName, middleName, surname, photoUri, number, emails, events, accountName, starred, contactId, thumbnailUri)
59+
val contact = Contact(id, firstName, middleName, surname, photoUri, number, emails, events, accountName, starred, contactId, thumbnailUri, null)
5860
contacts.put(id, contact)
5961
} while (cursor.moveToNext())
6062
}
@@ -224,7 +226,7 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
224226
val starred = cursor.getIntValue(CommonDataKinds.StructuredName.STARRED)
225227
val contactId = cursor.getIntValue(ContactsContract.Data.CONTACT_ID)
226228
val thumbnailUri = cursor.getStringValue(CommonDataKinds.StructuredName.PHOTO_THUMBNAIL_URI) ?: ""
227-
return Contact(id, firstName, middleName, surname, photoUri, number, emails, events, accountName, starred, contactId, thumbnailUri)
229+
return Contact(id, firstName, middleName, surname, photoUri, number, emails, events, accountName, starred, contactId, thumbnailUri, null)
228230
}
229231
} finally {
230232
cursor?.close()
@@ -429,12 +431,12 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
429431
val photoUri = Uri.parse(contact.photoUri)
430432
val bitmap = MediaStore.Images.Media.getBitmap(activity.contentResolver, photoUri)
431433

432-
val thumbnailSize = getThumbnailSize()
434+
val thumbnailSize = activity.getPhotoThumbnailSize()
433435
val scaledPhoto = Bitmap.createScaledBitmap(bitmap, thumbnailSize, thumbnailSize, false)
434-
val scaledSizePhotoData = bitmapToByteArray(scaledPhoto)
436+
val scaledSizePhotoData = scaledPhoto.getByteArray()
435437
scaledPhoto.recycle()
436438

437-
val fullSizePhotoData = bitmapToByteArray(bitmap)
439+
val fullSizePhotoData = bitmap.getByteArray()
438440
bitmap.recycle()
439441

440442
ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).apply {
@@ -522,11 +524,11 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
522524
val photoUri = Uri.parse(contact.photoUri)
523525
val bitmap = MediaStore.Images.Media.getBitmap(activity.contentResolver, photoUri)
524526

525-
val thumbnailSize = getThumbnailSize()
527+
val thumbnailSize = activity.getPhotoThumbnailSize()
526528
val scaledPhoto = Bitmap.createScaledBitmap(bitmap, thumbnailSize, thumbnailSize, false)
527-
scaledSizePhotoData = bitmapToByteArray(scaledPhoto)
529+
scaledSizePhotoData = scaledPhoto.getByteArray()
528530

529-
fullSizePhotoData = bitmapToByteArray(bitmap)
531+
fullSizePhotoData = bitmap.getByteArray()
530532
scaledPhoto.recycle()
531533
bitmap.recycle()
532534

@@ -677,19 +679,4 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
677679
activity.showErrorToast(e)
678680
}
679681
}
680-
681-
private fun getThumbnailSize(): Int {
682-
val uri = ContactsContract.DisplayPhoto.CONTENT_MAX_DIMENSIONS_URI
683-
val projection = arrayOf(ContactsContract.DisplayPhoto.THUMBNAIL_MAX_DIM)
684-
var cursor: Cursor? = null
685-
try {
686-
cursor = activity.contentResolver.query(uri, projection, null, null, null)
687-
if (cursor?.moveToFirst() == true) {
688-
return cursor.getIntValue(ContactsContract.DisplayPhoto.THUMBNAIL_MAX_DIM)
689-
}
690-
} finally {
691-
cursor?.close()
692-
}
693-
return 0
694-
}
695682
}

app/src/main/kotlin/com/simplemobiletools/contacts/helpers/DBHelper.kt

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,23 @@ import android.content.ContentValues
44
import android.content.Context
55
import android.database.sqlite.SQLiteDatabase
66
import android.database.sqlite.SQLiteOpenHelper
7+
import android.graphics.Bitmap
8+
import android.graphics.BitmapFactory
9+
import android.net.Uri
10+
import android.provider.MediaStore
711
import android.text.TextUtils
812
import com.google.gson.Gson
913
import com.google.gson.reflect.TypeToken
14+
import com.simplemobiletools.commons.extensions.getBlobValue
1015
import com.simplemobiletools.commons.extensions.getIntValue
1116
import com.simplemobiletools.commons.extensions.getStringValue
17+
import com.simplemobiletools.contacts.extensions.getByteArray
18+
import com.simplemobiletools.contacts.extensions.getPhotoThumbnailSize
1219
import com.simplemobiletools.contacts.models.Contact
1320
import com.simplemobiletools.contacts.models.Email
1421
import com.simplemobiletools.contacts.models.Event
1522
import com.simplemobiletools.contacts.models.PhoneNumber
1623

17-
1824
class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(context, DB_NAME, null, DB_VERSION) {
1925
private val CONTACTS_TABLE_NAME = "contacts"
2026
private val COL_ID = "id"
@@ -86,9 +92,26 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont
8692
put(COL_EMAILS, Gson().toJson(contact.emails))
8793
put(COL_EVENTS, Gson().toJson(contact.events))
8894
put(COL_STARRED, contact.starred)
95+
96+
if (contact.photoUri.isNotEmpty()) {
97+
put(COL_PHOTO, getPhotoByteArray(contact.photoUri))
98+
} else if (contact.photo == null) {
99+
putNull(COL_PHOTO)
100+
}
89101
}
90102
}
91103

104+
private fun getPhotoByteArray(uri: String): ByteArray {
105+
val photoUri = Uri.parse(uri)
106+
val bitmap = MediaStore.Images.Media.getBitmap(context.contentResolver, photoUri)
107+
108+
val thumbnailSize = context.getPhotoThumbnailSize()
109+
val scaledPhoto = Bitmap.createScaledBitmap(bitmap, thumbnailSize, thumbnailSize, false)
110+
val scaledSizePhotoData = scaledPhoto.getByteArray()
111+
scaledPhoto.recycle()
112+
return scaledSizePhotoData
113+
}
114+
92115
fun toggleFavorites(ids: Array<String>, addToFavorites: Boolean) {
93116
val contactValues = ContentValues()
94117
contactValues.put(COL_STARRED, if (addToFavorites) 1 else 0)
@@ -100,7 +123,7 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont
100123

101124
fun getContacts(selection: String? = null, selectionArgs: Array<String>? = null): ArrayList<Contact> {
102125
val contacts = ArrayList<Contact>()
103-
val projection = arrayOf(COL_ID, COL_FIRST_NAME, COL_MIDDLE_NAME, COL_SURNAME, COL_PHONE_NUMBERS, COL_EMAILS, COL_EVENTS, COL_STARRED)
126+
val projection = arrayOf(COL_ID, COL_FIRST_NAME, COL_MIDDLE_NAME, COL_SURNAME, COL_PHONE_NUMBERS, COL_EMAILS, COL_EVENTS, COL_STARRED, COL_PHOTO)
104127
val cursor = mDb.query(CONTACTS_TABLE_NAME, projection, selection, selectionArgs, null, null, null)
105128
cursor.use {
106129
while (cursor.moveToNext()) {
@@ -121,8 +144,15 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont
121144
val eventsToken = object : TypeToken<List<Event>>() {}.type
122145
val events = Gson().fromJson<ArrayList<Event>>(eventsJson, eventsToken) ?: ArrayList(1)
123146

147+
val photoByteArray = cursor.getBlobValue(COL_PHOTO) ?: null
148+
val photo = if (photoByteArray?.isNotEmpty() == true) {
149+
BitmapFactory.decodeByteArray(photoByteArray, 0, photoByteArray.size)
150+
} else {
151+
null
152+
}
153+
124154
val starred = cursor.getIntValue(COL_STARRED)
125-
val contact = Contact(id, firstName, middleName, surname, "", phoneNumbers, emails, events, SMT_PRIVATE, starred, id, "")
155+
val contact = Contact(id, firstName, middleName, surname, "", phoneNumbers, emails, events, SMT_PRIVATE, starred, id, "", photo)
126156
contacts.add(contact)
127157
}
128158
}

app/src/main/kotlin/com/simplemobiletools/contacts/helpers/VcfImporter.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ class VcfImporter(val activity: SimpleActivity) {
199199
}
200200

201201
private fun saveContact(source: String) {
202-
val contact = Contact(0, curFirstName, curMiddleName, curSurname, curPhotoUri, curPhoneNumbers, curEmails, curEvents, source, 0, 0, "")
202+
val contact = Contact(0, curFirstName, curMiddleName, curSurname, curPhotoUri, curPhoneNumbers, curEmails, curEvents, source, 0, 0, "", null)
203203
if (ContactsHelper(activity).insertContact(contact)) {
204204
contactsImported++
205205
}

0 commit comments

Comments
 (0)