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

}
相关推荐
Coffeeee8 分钟前
ios零基础的Android开发能否靠AI让老板省一笔人工费呢
android·ios·ai编程
Joey_friends14 分钟前
指纹authenticate流程图
android·java·c++
郑州光合科技余经理28 分钟前
家政O2O平台解析:从0搭建上门预约小程序解决方案
android·java·开发语言·前端·小程序·架构·php
yueqc12 小时前
Android 渲染(三):掉帧监控
android·渲染·apm·掉帧
Mico182 小时前
MySQL 8.0.35 基于GTID 主从复制安装增强半同步复制
android·mysql·adb
Kapaseker3 小时前
你是不是还没用过 select?实战 Kotlin select
android·kotlin
__Witheart__3 小时前
适用于Android内核boot.img生成流程
android·rockchip
木易 士心3 小时前
Jetpack Compose 深度解析:初始组合与重组的底层奥秘
android
GitLqr12 小时前
Flutter 无障碍开发实战:玩转 Semantics 解决视障用户使用痛点
android·flutter·dart
雨白16 小时前
掌握 NestedScrolling 嵌套滑动:手写仿知乎折叠主页
android