@@ -6,6 +6,7 @@ import android.content.ContentResolver
66import android.content.ContentValues
77import android.content.Context
88import android.database.Cursor
9+ import android.database.sqlite.SQLiteException
910import android.graphics.Bitmap
1011import android.graphics.BitmapFactory
1112import android.net.Uri
@@ -262,16 +263,21 @@ fun Context.getMMSSender(msgId: Long): String {
262263}
263264
264265fun Context.getConversations (threadId : Long? = null, privateContacts : ArrayList <SimpleContact > = ArrayList ()): ArrayList <Conversation > {
266+ val archiveAvailable = config.isArchiveAvailable
267+
265268 val uri = Uri .parse(" ${Threads .CONTENT_URI } ?simple=true" )
266- val projection = arrayOf (
269+ val projection = mutableListOf (
267270 Threads ._ID ,
268271 Threads .SNIPPET ,
269272 Threads .DATE ,
270273 Threads .READ ,
271274 Threads .RECIPIENT_IDS ,
272- Threads .ARCHIVED
273275 )
274276
277+ if (archiveAvailable) {
278+ projection + = Threads .ARCHIVED
279+ }
280+
275281 var selection = " ${Threads .MESSAGE_COUNT } > ?"
276282 var selectionArgs = arrayOf(" 0" )
277283 if (threadId != null ) {
@@ -284,39 +290,68 @@ fun Context.getConversations(threadId: Long? = null, privateContacts: ArrayList<
284290 val conversations = ArrayList <Conversation >()
285291 val simpleContactHelper = SimpleContactsHelper (this )
286292 val blockedNumbers = getBlockedNumbers()
287- queryCursor(uri, projection, selection, selectionArgs, sortOrder, true ) { cursor ->
288- val id = cursor.getLongValue(Threads ._ID )
289- var snippet = cursor.getStringValue(Threads .SNIPPET ) ? : " "
290- if (snippet.isEmpty()) {
291- snippet = getThreadSnippet(id)
292- }
293+ try {
294+ queryCursorUnsafe(uri, projection.toTypedArray(), selection, selectionArgs, sortOrder) { cursor ->
295+ val id = cursor.getLongValue(Threads ._ID )
296+ var snippet = cursor.getStringValue(Threads .SNIPPET ) ? : " "
297+ if (snippet.isEmpty()) {
298+ snippet = getThreadSnippet(id)
299+ }
293300
294- var date = cursor.getLongValue(Threads .DATE )
295- if (date.toString().length > 10 ) {
296- date / = 1000
297- }
301+ var date = cursor.getLongValue(Threads .DATE )
302+ if (date.toString().length > 10 ) {
303+ date / = 1000
304+ }
298305
299- val rawIds = cursor.getStringValue(Threads .RECIPIENT_IDS )
300- val recipientIds = rawIds.split(" " ).filter { it.areDigitsOnly() }.map { it.toInt() }.toMutableList()
301- val phoneNumbers = getThreadPhoneNumbers(recipientIds)
302- if (phoneNumbers.isEmpty() || phoneNumbers.any { isNumberBlocked(it, blockedNumbers) }) {
303- return @queryCursor
304- }
306+ val rawIds = cursor.getStringValue(Threads .RECIPIENT_IDS )
307+ val recipientIds = rawIds.split(" " ).filter { it.areDigitsOnly() }.map { it.toInt() }.toMutableList()
308+ val phoneNumbers = getThreadPhoneNumbers(recipientIds)
309+ if (phoneNumbers.isEmpty() || phoneNumbers.any { isNumberBlocked(it, blockedNumbers) }) {
310+ return @queryCursorUnsafe
311+ }
305312
306- val names = getThreadContactNames(phoneNumbers, privateContacts)
307- val title = TextUtils .join(" , " , names.toTypedArray())
308- val photoUri = if (phoneNumbers.size == 1 ) simpleContactHelper.getPhotoUriFromPhoneNumber(phoneNumbers.first()) else " "
309- val isGroupConversation = phoneNumbers.size > 1
310- val read = cursor.getIntValue(Threads .READ ) == 1
311- val archived = cursor.getIntValue(Threads .ARCHIVED ) == 1
312- val conversation = Conversation (id, snippet, date.toInt(), read, title, photoUri, isGroupConversation, phoneNumbers.first(), isArchived = archived)
313- conversations.add(conversation)
313+ val names = getThreadContactNames(phoneNumbers, privateContacts)
314+ val title = TextUtils .join(" , " , names.toTypedArray())
315+ val photoUri = if (phoneNumbers.size == 1 ) simpleContactHelper.getPhotoUriFromPhoneNumber(phoneNumbers.first()) else " "
316+ val isGroupConversation = phoneNumbers.size > 1
317+ val read = cursor.getIntValue(Threads .READ ) == 1
318+ val archived = if (archiveAvailable) cursor.getIntValue(Threads .ARCHIVED ) == 1 else false
319+ val conversation = Conversation (id, snippet, date.toInt(), read, title, photoUri, isGroupConversation, phoneNumbers.first(), isArchived = archived)
320+ conversations.add(conversation)
321+ }
322+ } catch (sqliteException: SQLiteException ) {
323+ if (sqliteException.message?.contains(" no such column: archived" ) == true && archiveAvailable) {
324+ config.isArchiveAvailable = false
325+ return getConversations(threadId, privateContacts)
326+ } else {
327+ showErrorToast(sqliteException)
328+ }
329+ } catch (e: Exception ) {
330+ showErrorToast(e)
314331 }
315332
316333 conversations.sortByDescending { it.date }
317334 return conversations
318335}
319336
337+ private fun Context.queryCursorUnsafe (
338+ uri : Uri ,
339+ projection : Array <String >,
340+ selection : String? = null,
341+ selectionArgs : Array <String >? = null,
342+ sortOrder : String? = null,
343+ callback : (cursor: Cursor ) -> Unit
344+ ) {
345+ val cursor = contentResolver.query(uri, projection, selection, selectionArgs, sortOrder)
346+ cursor?.use {
347+ if (cursor.moveToFirst()) {
348+ do {
349+ callback(cursor)
350+ } while (cursor.moveToNext())
351+ }
352+ }
353+ }
354+
320355fun Context.getConversationIds (): List <Long > {
321356 val uri = Uri .parse(" ${Threads .CONTENT_URI } ?simple=true" )
322357 val projection = arrayOf(Threads ._ID )
@@ -713,7 +748,16 @@ fun Context.updateConversationArchivedStatus(threadId: Long, archived: Boolean)
713748 }
714749 val selection = " ${Threads ._ID } = ?"
715750 val selectionArgs = arrayOf(threadId.toString())
716- contentResolver.update(uri, values, selection, selectionArgs)
751+ try {
752+ contentResolver.update(uri, values, selection, selectionArgs)
753+ } catch (sqliteException: SQLiteException ) {
754+ if (sqliteException.message?.contains(" no such column: archived" ) == true && config.isArchiveAvailable) {
755+ config.isArchiveAvailable = false
756+ return
757+ } else {
758+ throw sqliteException
759+ }
760+ }
717761 if (archived) {
718762 conversationsDB.moveToArchive(threadId)
719763 } else {
0 commit comments