現象
Fatal Exception: java.lang.ClassCastException: android.content.ContentResolver$CursorWrapperInner cannot be cast to java.io.Closeable
原因
Cursor が Closeable を継承するのは API 16 から。ContentResolver の返す Cursor が custom cursor にできない問題に気を取られすぎて、Closeable を継承してないのを忘れていた・・・
明示的に Cursor を Closeable にすると、ちゃんと Android Lint が怒ってくれる。use を使う場合は出てこない。悲しみが深い。
解決策
以下の拡張関数をcompatで書いて対応。関数名をuseにしていないのは書いてるときにimportする関数を間違える可能性が高いから。
import android.database.Cursor import android.os.Build import kotlin.io.use as ioUse inline fun <T : Cursor?, R> T.useCompat(block: (T) -> R): R { return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { ioUse(block) } else { var exception: Throwable? = null try { return block(this) } catch (expected: Throwable) { exception = expected throw expected } finally { when { this == null -> { } exception == null -> close() else -> try { close() } catch (ignored: Throwable) { } } } } }
理想的な解決策
minimum support API を28にする