前言
本文用来记录如何获取手机设备中存储的音频文件,之后可以通过各种播放器进行播放。
audio介绍
用下面工具类来获取系统提供的ContentProvider中数据库里的音频文件,然后自由选择每条记录的所需的属性并存储在Bean类中,就可以通过实体类随意使用了。
kotlin
1.工具类:
//工具类,目前固定获取手机中音频文件中容量、歌曲名、歌手属性,后续考虑修改扩展性更强的工具类
object GetQueryAudioUtils {
suspend fun getQueryAudio(
context: Context
): List<AudioBean> = withContext(Dispatchers.IO) {
val resolver = context.contentResolver //获取contentResolver
val queryResult = mutableListOf<AudioBean>() //存放查询结果
val projection = arrayOf(
//查询的属性列表
MediaStore.Audio.Media._ID, //拼uri 必定存在的列 不会出现找不到的异常
MediaStore.Audio.Media.SIZE, //容量
MediaStore.Audio.Media.DISPLAY_NAME, //含扩展名的歌曲名
MediaStore.Audio.Media.ARTIST, //歌手
)
runCatching {
resolver.query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
//获取到路径 容量 歌曲名 歌手
projection,
null,
null,
null
)?.use { cursor -> //可以自动关流
//获取对应属性在表中具体第几列的序列号index
val idIndex = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media._ID) //防止意外抛出异常
val sizeIndex = cursor.getColumnIndex(MediaStore.Audio.Media.SIZE)
val nameIndex = cursor.getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME)
val artisIndex = cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST)
while (cursor.moveToNext()) {
//对查询后的结果进行包装实体类
val id = cursor.getLong(idIndex)
val size = if (sizeIndex != -1) cursor.getLong(sizeIndex) else 0
val songName = if (nameIndex != -1) cursor.getString(nameIndex)
?.substringBeforeLast('.') ?: "未知歌曲" else "未知歌曲"
val singer = if (artisIndex != -1) cursor.getString(artisIndex)
?: "未知歌手" else "未知歌手"
val uri =
ContentUris.withAppendedId(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id
) //将获取到的id拼接在contentProvider地址的后面
queryResult.add(AudioBean(uri, size, songName, singer))
}
}
queryResult
}.onFailure {
Log.e("GetQueryAudioUtils", "query audio failed", it)
}.getOrDefault(emptyList<AudioBean>())
}
}
2.使用:
//清单文件中添加权限
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" /> <!--api33及以上-->
<!-- 外部存储读取权限 -->
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" /><!--api29-32-->
//mainActivity
class MainActivity : BaseActivity() {
private lateinit var text: TextView
override fun setViewId(): Int = R.layout.activity_main
override fun initView() {
text = findViewById(R.id.text)
//动态获取权限
PremissionUtils.requestPermissions(this)
lifecycleScope.launch(Dispatchers.Main) {
val result: List<AudioBean> = GetQueryAudioUtils.getQueryAudio(this@MainActivity)
if (result.isNotEmpty())
text.text = result.toString()
}
}
}
//3.动态权限申请
object PremissionUtils {
var PERMISSIONS_STORAGE: Array<String?> = arrayOf<String?>(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
) //Android6.0以后操作系统的动态权限申请
/**
* 用于Android6.0以后的操作系统,动态申请存储的读写权限
* @param context
*/
fun requestPermissions(context: Activity) {
//用于Android6.0以后的操作系统,动态申请存储的读写权限
val permission =
ActivityCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE)
if (permission != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(context, PERMISSIONS_STORAGE, 1)
}
}
}