文章目录
前言
Android开发中经常需要获取当前设备中的音频文件,用来播放等操作,于是写了一个工具类可以直接拿来使用,避免了每次手写,提高代码开发的效率。
工具类,可针对需求自行调节细节
kotlin
object MusicRepository {
/**
* @describe: 获取本地的音频数据
* @params:
* context:上下文
* externalScope:协程
* @return:
*/
suspend fun getLocalMusic(context: Context): List<Song> = withContext(
Dispatchers.IO){
val result = mutableListOf<Song>()
runCatching {
//定义要查询的字段
val projection = arrayOf(
MediaStore.Audio.Media._ID, // 唯一ID
MediaStore.Audio.Media.TITLE, // 标题
MediaStore.Audio.Media.ARTIST, // 歌手
MediaStore.Audio.Media.ALBUM, // 专辑
MediaStore.Audio.Media.DURATION, // 时长
MediaStore.Audio.Media.DATA, // 文件路径(Android 10+ 需注意分区存储)
MediaStore.Audio.Media.SIZE // 文件大小
)
//设置筛选条件:只保留音乐文件(排除掉铃声、通知等) 时长>10秒(过滤短音频)
val selection =
"${MediaStore.Audio.Media.IS_MUSIC} = 1 AND ${MediaStore.Audio.Media.DURATION} > 10000"
//排序:按标题升序
val sortOrder = "${MediaStore.Audio.Media.TITLE} ASC"
//查询媒体库
val cursor = context.contentResolver.query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, //查询的数据源URI:外部存储音频
projection,//需要返回的列
selection, //过滤的条件
null, //过滤条件的参数值
sortOrder //排序
)
//解析Cursor的查询结果
cursor?.use { //use{}可以自动关闭cursor避免内存泄漏
//获取列表中目标列名所对应的位置position
val idColumn = it.getColumnIndexOrThrow(MediaStore.Audio.Media._ID)
val titleColumn = it.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE)
val artistColumn = it.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST)
val albumColumn = it.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM)
val durationColumn = it.getColumnIndexOrThrow(MediaStore.Audio.Media.DURATION)
val pathColumn = it.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA)
val sizeColumn = it.getColumnIndexOrThrow(MediaStore.Audio.Media.SIZE)
while (it.moveToNext()) {
//跟据列号获取当前行中对应位置的具体数据(即行+列直接对应到具体位置)
val id = it.getLong(idColumn)
val title = it.getStringOrNull(titleColumn)
val artist = it.getStringOrNull(artistColumn)
val album = it.getStringOrNull(albumColumn)
val duration = it.getLongOrNull(durationColumn)
val path = it.getStringOrNull(pathColumn)
val size = it.getLongOrNull(sizeColumn)
//将获取到的数据存储起来
result.add(Song(id, title, if(artist == "<unknown>") "未知歌手" else artist, album, duration, path, size))
}
}
}.getOrNull()
return@withContext result.toList()
}
}
/**
* @describe: 歌曲的数据类
* @params:
* @return:
*/
data class Song(
val id: Long, // 媒体库唯一ID
val title: String?, // 音乐标题
val artist: String?, // 歌手名
val album: String?, // 专辑名
val duration: Long?, // 时长(毫秒)
val path: String?, // 音频文件路径
val size: Long? // 文件大小(字节)
)
activity中使用:
注意需要动态申请权限,Android13及以上权限为READ_MEDIA_AUDIO,以下为READ_EXTERNAL_STORAGE
kotlin
lifecycleScope.launch { //此处默认为主线程
data = MusicRepository.getLocalMusic(this@MainActivity)
data?.let {
musicTitle.text = it[0].title
musicSinger.text = it[0].artist
val intent = Intent(this@MainActivity, AudioService::class.java).apply {
putExtra("uri",it[0].path)
putExtra("title",it[0].title)
putExtra("artist",it[0].artist)
}
}
}