📸

【Android】MediaStore の query でストレージから画像が取得できない

2021/03/03に公開

MediaStore#queryで、ストレージに保存されている画像を取得しようとしたところ、なぜかアプリで撮影・保存した画像しか取得出来なかったので、対処法を書いてみたいと思います。

READ_EXTERNAL_STORAGE パーミッションをチェックする

MediaStore#queryで画像を取得する前に、READ_EXTERNAL_STORAGEパーミッションのチェック・許可をしていなかったので、取得出来なかったようです。

Sample : 端末の画像一覧取得

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="...">
    // パーミッションを設定
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

MainActivity.kt

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    loadImages()
}

// requestPermissions の後に呼び出される
override fun onRequestPermissionsResult(
    requestCode: Int,
    permissions: Array<out String>,
    grantResults: IntArray
) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    if (requestCode != REQUEST_CODE_PERMISSION) return
    if (grantResults.isNotEmpty() && (grantResults.first() == PackageManager.PERMISSION_GRANTED)) {
        // 許可した後の処理
    }
}
    
private fun loadImages() {
    // READ_EXTERNAL_STORAGE パーミッションが許可されているかチェックする
    val isGranted = ContextCompat.checkSelfPermission(
        this,
        Manifest.permission.READ_EXTERNAL_STORAGE
    ) == PackageManager.PERMISSION_GRANTED

    // 許可されていない場合、パーミッションの許可を選択するダイアログを表示する
    if (!isGranted) {
        requestPermissions(
            arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),
            REQUEST_CODE_PERMISSION
        )
        return
    }

    val uris = mutableListOf<Uri>()
    // 外部ストレージを指定する
    val queryUri: Uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
    // queryで取得したいカラムを指定する
    val projection: Array<String> = arrayOf(MediaStore.Images.Media._ID)
    /**
     * 検索条件を指定する。
     * 条件は「"${MediaStore.Images.Media.DATE_TAKEN} >= ?"」のように記述する。
     * 全件取得のときはnullを指定する。
     */
    val selection: String? = null
    /**
     * selectionの「?」に代入する条件を指定する。
     * 全件取得のときはnullを指定する。
     */
    val selectionArgs: Array<String>? = null
    /**
     * ソート条件を指定する。
     * 条件は「"${MediaStore.Images.Media.DATE_ADDED} DESC"」のように記述する。
     * 条件を指定しない場合はnullを設定する。
     */
    val sortOrder: String? = null

    contentResolver.query(
        queryUri,
        projection,
        selection,
        selectionArgs,
        sortOrder
     ).use { cursor ->
        cursor ?: return@use
        // projectionで指定していないカラムを取得しようとすると、例外がスローされる。
        val columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID)
        while (cursor.moveToNext()) {
            val imageId = cursor.getLong(columnIndex)
            // メディアアイテムのURIを取得する
            val uri = Uri.withAppendedPath(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                imageId.toString()
            )
            uris.add(uri.toString())
        }
    }
}

Discussion