2022 May 02.
2022 Apr. 30.
2022 Feb. 13.
2022 Jan. 30.
2021 Jul. 06.
2021 Jul. 04.
参考ページ 共有ストレージからメディア ファイルにアクセスする | Android デベロッパー | Android Developers
ContentResolverを利用して外部ストレージの共有領域のメディアファイル(audio video image)を読み込む
外部ストレージにユーザーが作成した任意のディレクトリ内に保存されたメディアファイルを読み込み可能
ContentResolverでのメディアファイル取得
ContentResolverはMediaStoreの持っているContentProviderにアクセスし、結果を取得する。
ContentProviderがデータベースサーバー、ContentResolverがクライアントに相当する。
projectionにセットする値(Audioの場合)
ID:MediaStore.Audio.Media._ID (URIそのものの取得に必要)
ファイル名:MediaStore.Audio.Media.DISPLAY_NAME
ファイルサイズ:MediaStore.Audio.Media.SIZE
ファイルパス:"_data"
URIそのものの取得には、下記サンプルのようにContentUris.withAppendedId()にIDを入れる。
val resolver = applicationContext.contentResolver val query = resolver.query(....) query?.use { cursor -> val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media._ID) cursor.moveToFirst() val id = cursor.getLong(idColumn) val contentUri = ContentUris.withAppendedId(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, id) } query?.close()
確認端末
android 7
android 11
ContentResolver#queryのcolumn projectionに _data を使っているが動作した。
MediaStore.Audio.Media.DATAは"Deprecated in API level 29"だが _data は利用できる模様。
コンパイル環境
compileSdkVersion 31
minSdkVersion 24
targetSdkVersion 31
パーミッション
READ_EXTERNAL_STORAGEを要する
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="...."> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <application
外部ストレージの音声ファイル情報をLogcatに表示するkotlinコード
MainActivity.kt
// 事前に permission.READ_EXTERNAL_STORAGE を取得しておくこと fun readExMedia() { val collection = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { MediaStore.Audio.Media.getContentUri( MediaStore.VOLUME_EXTERNAL ) } else { MediaStore.Audio.Media.EXTERNAL_CONTENT_URI } val columns = arrayOf( MediaStore.Audio.Media._ID, MediaStore.Audio.Media.DISPLAY_NAME, MediaStore.Audio.Media.SIZE, "_data" ) val resolver = applicationContext.contentResolver val query = resolver.query( // オーディオファイルの集合を取得 collection, //データの種類 columns, //取得する項目 nullは全部 null, //フィルター条件 nullはフィルタリング無し null, //フィルター用のパラメータ null //並べ替え ) Log.d( "MyApp" , Arrays.toString( query?.getColumnNames() ) ) //項目名の一覧を出力 val numCount = query?.count Log.d("MyApp", "Num raws : $numCount") // オーディオファイル数 query?.use { cursor -> val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media._ID) val displayNameColumn = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DISPLAY_NAME) val sizeColumn = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.SIZE) val pathColumn = cursor.getColumnIndexOrThrow("_data") cursor.move(getRandomNum(numCount!!)) // オーディオファイルをランダムに1つ指定 // 指定したオーディオファイルの各カラムのデータを取得する val id = cursor.getLong(idColumn) val displayName = cursor.getString(displayNameColumn) val mediaSize = cursor.getInt(sizeColumn) val contentUri: Uri = ContentUris.withAppendedId( MediaStore.Video.Media.EXTERNAL_CONTENT_URI, id) val PathOfUri = cursor.getString(pathColumn) // URI等を表示 Log.d( "MyApp", "id: $id, name: $displayName, ${mediaSize}Byte, uri: $contentUri" ) // パスを表示 Log.d("MyApp", "Selected " + PathOfUri!!) } query?.close() } // 0以上、maxNum未満の範囲でランダムな数を1つ返す fun getRandomNum(maxNum: Int): Int { val random = Random() return random.nextInt(maxNum) } }