Add robustness when getting data from cursors.

Use androidx.core.database extension for better nullability check, and ignore uncomplete data.
This commit is contained in:
Benoit Marty 2021-12-01 16:09:12 +01:00
parent 2e52f429fb
commit 84f7eb29e0
6 changed files with 34 additions and 24 deletions

1
changelog.d/4605.bugfix Normal file
View file

@ -0,0 +1 @@
Add robustness when getting data from cursors

View file

@ -20,6 +20,8 @@ import android.content.ContentResolver
import android.content.Context
import android.content.Intent
import android.provider.ContactsContract
import androidx.core.database.getIntOrNull
import androidx.core.database.getStringOrNull
import im.vector.lib.multipicker.entity.MultiPickerContactType
import im.vector.lib.multipicker.utils.getColumnIndexOrNull
@ -54,9 +56,9 @@ class ContactPicker : Picker<MultiPickerContactType>() {
val nameColumn = cursor.getColumnIndexOrNull(ContactsContract.Contacts.DISPLAY_NAME) ?: return@use
val photoUriColumn = cursor.getColumnIndexOrNull(ContactsContract.Contacts.PHOTO_URI) ?: return@use
val contactId = cursor.getInt(idColumn)
var name = cursor.getString(nameColumn)
val photoUri = cursor.getString(photoUriColumn)
val contactId = cursor.getIntOrNull(idColumn) ?: return@use
var name = cursor.getStringOrNull(nameColumn) ?: return@use
val photoUri = cursor.getStringOrNull(photoUriColumn)
val phoneNumberList = mutableListOf<String>()
val emailList = mutableListOf<String>()
@ -78,8 +80,8 @@ class ContactPicker : Picker<MultiPickerContactType>() {
val data1ColumnIndex = innerCursor.getColumnIndexOrNull(ContactsContract.Data.DATA1) ?: return@inner
while (innerCursor.moveToNext()) {
val mimeType = innerCursor.getString(mimeTypeColumnIndex)
val contactData = innerCursor.getString(data1ColumnIndex)
val mimeType = innerCursor.getStringOrNull(mimeTypeColumnIndex)
val contactData = innerCursor.getStringOrNull(data1ColumnIndex) ?: continue
if (mimeType == ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) {
name = contactData
@ -121,7 +123,7 @@ class ContactPicker : Picker<MultiPickerContactType>() {
)?.use { cursor ->
return if (cursor.moveToFirst()) {
cursor.getColumnIndexOrNull(ContactsContract.RawContacts._ID)
?.let { cursor.getInt(it) }
?.let { cursor.getIntOrNull(it) }
} else null
}
}

View file

@ -19,6 +19,8 @@ package im.vector.lib.multipicker
import android.content.Context
import android.content.Intent
import android.provider.OpenableColumns
import androidx.core.database.getLongOrNull
import androidx.core.database.getStringOrNull
import im.vector.lib.multipicker.entity.MultiPickerBaseType
import im.vector.lib.multipicker.entity.MultiPickerFileType
import im.vector.lib.multipicker.utils.getColumnIndexOrNull
@ -53,8 +55,8 @@ class FilePicker : Picker<MultiPickerBaseType>() {
val nameColumn = cursor.getColumnIndexOrNull(OpenableColumns.DISPLAY_NAME) ?: return@use null
val sizeColumn = cursor.getColumnIndexOrNull(OpenableColumns.SIZE) ?: return@use null
if (cursor.moveToFirst()) {
val name = cursor.getString(nameColumn)
val size = cursor.getLong(sizeColumn)
val name = cursor.getStringOrNull(nameColumn)
val size = cursor.getLongOrNull(sizeColumn) ?: 0
MultiPickerFileType(
name,

View file

@ -20,6 +20,8 @@ import android.content.Context
import android.media.MediaMetadataRetriever
import android.net.Uri
import android.provider.MediaStore
import androidx.core.database.getLongOrNull
import androidx.core.database.getStringOrNull
import im.vector.lib.multipicker.entity.MultiPickerAudioType
import im.vector.lib.multipicker.entity.MultiPickerImageType
import im.vector.lib.multipicker.entity.MultiPickerVideoType
@ -41,8 +43,8 @@ internal fun Uri.toMultiPickerImageType(context: Context): MultiPickerImageType?
val sizeColumn = cursor.getColumnIndexOrNull(MediaStore.Images.Media.SIZE) ?: return@use null
if (cursor.moveToNext()) {
val name = cursor.getString(nameColumn)
val size = cursor.getLong(sizeColumn)
val name = cursor.getStringOrNull(nameColumn)
val size = cursor.getLongOrNull(sizeColumn) ?: 0
val bitmap = ImageUtils.getBitmap(context, this)
val orientation = ImageUtils.getOrientation(context, this)
@ -79,8 +81,8 @@ internal fun Uri.toMultiPickerVideoType(context: Context): MultiPickerVideoType?
val sizeColumn = cursor.getColumnIndexOrNull(MediaStore.Video.Media.SIZE) ?: return@use null
if (cursor.moveToNext()) {
val name = cursor.getString(nameColumn)
val size = cursor.getLong(sizeColumn)
val name = cursor.getStringOrNull(nameColumn)
val size = cursor.getLongOrNull(sizeColumn) ?: 0
var duration = 0L
var width = 0
var height = 0
@ -128,8 +130,8 @@ fun Uri.toMultiPickerAudioType(context: Context): MultiPickerAudioType? {
val sizeColumn = cursor.getColumnIndexOrNull(MediaStore.Audio.Media.SIZE) ?: return@use null
if (cursor.moveToNext()) {
val name = cursor.getString(nameColumn)
val size = cursor.getLong(sizeColumn)
val name = cursor.getStringOrNull(nameColumn)
val size = cursor.getLongOrNull(sizeColumn) ?: 0
var duration = 0L
context.contentResolver.openFileDescriptor(this, "r")?.use { pfd ->

View file

@ -20,6 +20,8 @@ import android.content.Context
import android.net.Uri
import android.provider.ContactsContract
import androidx.annotation.WorkerThread
import androidx.core.database.getLongOrNull
import androidx.core.database.getStringOrNull
import im.vector.lib.multipicker.utils.getColumnIndexOrNull
import timber.log.Timber
import javax.inject.Inject
@ -61,8 +63,8 @@ class ContactsDataSource @Inject constructor(
val displayNameColumnIndex = cursor.getColumnIndexOrNull(ContactsContract.Contacts.DISPLAY_NAME) ?: return@use
val photoUriColumnIndex = cursor.getColumnIndexOrNull(ContactsContract.Data.PHOTO_URI)
while (cursor.moveToNext()) {
val id = cursor.getLong(idColumnIndex)
val displayName = cursor.getString(displayNameColumnIndex)
val id = cursor.getLongOrNull(idColumnIndex) ?: continue
val displayName = cursor.getStringOrNull(displayNameColumnIndex) ?: continue
val mappedContactBuilder = MappedContactBuilder(
id = id,
@ -70,7 +72,7 @@ class ContactsDataSource @Inject constructor(
)
photoUriColumnIndex
?.let { cursor.getString(it) }
?.let { cursor.getStringOrNull(it) }
?.let { Uri.parse(it) }
?.let { mappedContactBuilder.photoURI = it }
@ -94,10 +96,10 @@ class ContactsDataSource @Inject constructor(
val phoneNumberColumnIndex = cursor.getColumnIndexOrNull(ContactsContract.CommonDataKinds.Phone.NUMBER) ?: return@use
while (cursor.moveToNext()) {
val mappedContactBuilder = cursor.getLong(idColumnIndex)
.let { map[it] }
val mappedContactBuilder = cursor.getLongOrNull(idColumnIndex)
?.let { map[it] }
?: continue
cursor.getString(phoneNumberColumnIndex)
cursor.getStringOrNull(phoneNumberColumnIndex)
?.let {
mappedContactBuilder.msisdns.add(
MappedMsisdn(
@ -128,10 +130,10 @@ class ContactsDataSource @Inject constructor(
while (cursor.moveToNext()) {
// This would allow you get several email addresses
// if the email addresses were stored in an array
val mappedContactBuilder = cursor.getLong(idColumnIndex)
.let { map[it] }
val mappedContactBuilder = cursor.getLongOrNull(idColumnIndex)
?.let { map[it] }
?: continue
cursor.getString(emailColumnIndex)
cursor.getStringOrNull(emailColumnIndex)
?.let {
mappedContactBuilder.emails.add(
MappedEmail(

View file

@ -19,6 +19,7 @@ package im.vector.app.core.intent
import android.content.Context
import android.net.Uri
import android.provider.OpenableColumns
import androidx.core.database.getStringOrNull
import im.vector.lib.multipicker.utils.getColumnIndexOrNull
fun getFilenameFromUri(context: Context?, uri: Uri): String? {
@ -27,7 +28,7 @@ fun getFilenameFromUri(context: Context?, uri: Uri): String? {
?.use { cursor ->
if (cursor.moveToFirst()) {
return cursor.getColumnIndexOrNull(OpenableColumns.DISPLAY_NAME)
?.let { cursor.getString(it) }
?.let { cursor.getStringOrNull(it) }
}
}
}