diff --git a/data/src/main/java/com/moez/QKSMS/mapper/CursorToMessageImpl.kt b/data/src/main/java/com/moez/QKSMS/mapper/CursorToMessageImpl.kt index cec8e3b7..0c0c4548 100644 --- a/data/src/main/java/com/moez/QKSMS/mapper/CursorToMessageImpl.kt +++ b/data/src/main/java/com/moez/QKSMS/mapper/CursorToMessageImpl.kt @@ -27,44 +27,45 @@ import com.moez.QKSMS.extensions.map import com.moez.QKSMS.manager.KeyManager import com.moez.QKSMS.manager.PermissionManager import com.moez.QKSMS.model.Message +import com.moez.QKSMS.util.Preferences +import com.moez.QKSMS.util.SqliteWrapper +import com.moez.QKSMS.util.tryOrNull import javax.inject.Inject class CursorToMessageImpl @Inject constructor( private val context: Context, private val cursorToPart: CursorToPart, private val keys: KeyManager, - private val permissionManager: PermissionManager + private val permissionManager: PermissionManager, + private val preferences: Preferences ) : CursorToMessage { - companion object { - val URI = Uri.parse("content://mms-sms/complete-conversations") - val PROJECTION = arrayOf( - MmsSms.TYPE_DISCRIMINATOR_COLUMN, - MmsSms._ID, - Mms.DATE, - Mms.DATE_SENT, - Mms.READ, - Mms.THREAD_ID, - Mms.LOCKED, - Mms.SUBSCRIPTION_ID, + private val uri = Uri.parse("content://mms-sms/complete-conversations") + private val projection = arrayOf( + MmsSms.TYPE_DISCRIMINATOR_COLUMN, + MmsSms._ID, + Mms.DATE, + Mms.DATE_SENT, + Mms.READ, + Mms.THREAD_ID, + Mms.LOCKED, - Sms.ADDRESS, - Sms.BODY, - Sms.SEEN, - Sms.TYPE, - Sms.STATUS, - Sms.ERROR_CODE, + Sms.ADDRESS, + Sms.BODY, + Sms.SEEN, + Sms.TYPE, + Sms.STATUS, + Sms.ERROR_CODE, - Mms.SUBJECT, - Mms.SUBJECT_CHARSET, - Mms.SEEN, - Mms.MESSAGE_TYPE, - Mms.MESSAGE_BOX, - Mms.DELIVERY_REPORT, - Mms.READ_REPORT, - MmsSms.PendingMessages.ERROR_TYPE, - Mms.STATUS) - } + Mms.SUBJECT, + Mms.SUBJECT_CHARSET, + Mms.SEEN, + Mms.MESSAGE_TYPE, + Mms.MESSAGE_BOX, + Mms.DELIVERY_REPORT, + Mms.READ_REPORT, + MmsSms.PendingMessages.ERROR_TYPE, + Mms.STATUS) override fun map(from: Pair): Message { val cursor = from.first @@ -124,8 +125,24 @@ class CursorToMessageImpl @Inject constructor( } override fun getMessagesCursor(): Cursor? { + + // Even if the device is running API 22, we can't assume we have access to the subId + // column. In this case, we need to check if we do, before trying to sync messages + if (!preferences.canUseSubId.isSet) { + val canUseSubId = tryOrNull { + SqliteWrapper.query(context, uri, arrayOf(Mms.SUBSCRIPTION_ID))?.use { true } + } + + preferences.canUseSubId.set(canUseSubId ?: false) + } + + val projection = when (preferences.canUseSubId.get()) { + true -> this.projection + false -> this.projection + } + return when (permissionManager.hasSms()) { - true -> context.contentResolver.query(URI, PROJECTION, null, null, "normalized_date desc") + true -> SqliteWrapper.query(context, uri, projection, sortOrder = "normalized_date desc") false -> null } } diff --git a/data/src/main/java/com/moez/QKSMS/util/Preferences.kt b/data/src/main/java/com/moez/QKSMS/util/Preferences.kt index d7fbd553..84be9307 100644 --- a/data/src/main/java/com/moez/QKSMS/util/Preferences.kt +++ b/data/src/main/java/com/moez/QKSMS/util/Preferences.kt @@ -48,7 +48,11 @@ class Preferences @Inject constructor(private val rxPrefs: RxSharedPreferences) const val SEND_DELAY_LONG = 3 } + // Internal val night = rxPrefs.getBoolean("night", false) + val canUseSubId = rxPrefs.getBoolean("canUseSubId", true) + + // User configurable val nightMode = rxPrefs.getInteger("nightModeSummary", NIGHT_MODE_OFF) val nightStart = rxPrefs.getString("nightStart", "18:00") val nightEnd = rxPrefs.getString("nightEnd", "6:00") diff --git a/data/src/main/java/com/moez/QKSMS/util/SqliteWrapper.kt b/data/src/main/java/com/moez/QKSMS/util/SqliteWrapper.kt new file mode 100644 index 00000000..2a2624f5 --- /dev/null +++ b/data/src/main/java/com/moez/QKSMS/util/SqliteWrapper.kt @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2017 Moez Bhatti + * + * This file is part of QKSMS. + * + * QKSMS is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * QKSMS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with QKSMS. If not, see . + */ +package com.moez.QKSMS.util + +import android.content.Context +import android.database.Cursor +import android.database.sqlite.SQLiteException +import android.net.Uri +import timber.log.Timber + +/** + * Utility class to make ContentResolver queries with Kotlin more concise + */ +object SqliteWrapper { + + fun query( + context: Context, + uri: Uri, + projection: Array? = null, + selection: String? = null, + selectionArgs: Array? = null, + sortOrder: String? = null + ): Cursor? { + return try { + context.contentResolver.query(uri, projection, selection, selectionArgs, sortOrder) + } catch (e: SQLiteException) { + Timber.e(e) + null + } + + } + +} \ No newline at end of file