Android中获取设备里面的音频文件

前言

本文用来记录如何获取手机设备中存储的音频文件,之后可以通过各种播放器进行播放。


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)
        }
    }

}
相关推荐
robotx1 小时前
安卓线程相关
android
消失的旧时光-19431 小时前
Android 面试高频:JSON 文件、大数据存储与断电安全(从原理到工程实践)
android·面试·json
dalancon2 小时前
VSYNC 信号流程分析 (Android 14)
android
dalancon2 小时前
VSYNC 信号完整流程2
android
dalancon3 小时前
SurfaceFlinger 上帧后 releaseBuffer 完整流程分析
android
用户69371750013844 小时前
不卷AI速度,我卷自己的从容——北京程序员手记
android·前端·人工智能
程序员Android4 小时前
Android 刷新一帧流程trace拆解
android
墨狂之逸才5 小时前
解决 Android/Gradle 编译报错:Comparison method violates its general contract!
android
阿明的小蝴蝶5 小时前
记一次Gradle环境的编译问题与解决
android·前端·gradle
汪海游龙6 小时前
开源项目 Trending AI 招募 Google Play 内测人员(12 名)
android·github