【Android笔记】LocalFaraway简易安卓音乐播放器 | 及相关知识

298 阅读4分钟

一、基本音乐播放器

几年前写的,从csdn上迁移过来

1、代码库:MiaPlayer

2、其他结构知识:【Kotlin】FarawayPlayer

3、基本思路:

  • 通过ContentProvider方法
  • 查询MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
  • 根据MediaStore.Audio.Media.TITLE等对应参数取值
  • 高版本适配MediaStore.Audio.Media.DATA对应参数是这个:MediaStore.MediaColumns.RELATIVE_PATH

4、 盘一下各种关系:

  1. MediaStore.Audio.Media  |  Android Developers
  • 是个类 image.png
  • 从三个里继承了常量

image.png

  1. MediaStore.MediaColumns 是个接口

image.png

private var id: String? = null //歌曲id
    private var song: String? = null //歌曲名称
    private var singer: String? = null //歌手名称
    private var album: String? = null //专辑名称
    private var duration: String? = null //歌曲时长
    private var path: String? = null //歌曲路径

    private var albumUri: Uri ? = null ;//存储音乐封面的Uri地址
    private var thumb:Bitmap? = null ;//存储封面图片

一、权限配置

  1. 先在清单文件中加入<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>.安卓4.4后写需要权限
  2. 6.0 后的动态权限申请,传送门先不写,这个文章自己还没写好

二、Layout设计

  1. Relativelayout,上面有个RecycleView
  2. 下面有个信息栏RelativeLayout

image.png

三、获取本地数据

  1. 使用了内容提供器,ContentProvider共享数据的好处是统一了数据访问方式
  2. Cursor用法
//4.获取本地数据
    fun loadLocalMusicDate(){
        //加载本地存储中的音乐文件到mp3中
        //1,使用ContentResolver对象   获取contentprider 实现跨进程通信
        var resolver: ContentResolver =contentResolver//get方法 应该是有简写
        //2.获取本地音乐存储的Url地址  选择音乐Audio类
        var uri:Uri=MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
        //uri=content://media/external/audio/media 这是音频媒体表的uri
        /* MediaStore.Audio.Artists.Albums
         打印它的所有的列:发现了album_art,它缓存专辑封面。所以现在我们知道需要找album_art*/
        //3.开始查询 新建cursor对象
        val cursor: Cursor? = resolver.query(uri, null, null, null, null)
        //4.遍历地址
        var id:Long=0
        while(cursor!!.moveToNext()){
            var song=cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE))//获取字段
            var singer=cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST))//获取字段
            var album=cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM))//获取字段
            id++
            val sid = id.toString()//将其转为string类型 计数keyid字段 扫描ID
            //添加   获取该音乐所在专辑的id 真实ID
            //所有专辑都有自己的ID 所以肯定不会空
            var albumId = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Albums.ALBUM_ID));
            //得到播放路径
            var path = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA))
            //long型时间长度  代表毫秒数
            var duration = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.DURATION))

            var sdf = SimpleDateFormat("mm:ss")//转一下格式 java.txt包
            var time = sdf.format(Date(duration))
            //albumart文件夹专门用于存放专辑图片
            //组合找到当前前专辑所在Uri content://media/external/audio/albumart/4
            var albumUri:Uri ?=null
            print("查找前uri    "+albumUri+"   albumID"+albumId    )
            //I/System.out: 查找前uri    null   albumID81 发现这和id是不太一样的
            /*
            * id78  letter song 专辑79
            * id=89   起风了  专辑87
            * id=100  告白气球 专辑87*/
            albumUri= ContentUris.withAppendedId(Uri.parse("content://media/external/audio/albumart"), albumId)
            println("查找后uri"+albumUri)
            var thumb:Bitmap?=null//有些专辑没图片
            if (albumUri!=null)//找不到对应图片地址的bean传空值 在adapter设定若为空则 显示默认的
            {
                thumb=createThumbFromUir(resolver,albumUri)
            }else{
                var res = getResources();
                var bmp = BitmapFactory.decodeResource(res, R.drawable.icon_song);
                thumb=bmp
            }

            //将同一行中的数据封装入对象
            val bean = LocalMusicBean(sid, song, singer, album, time, path,albumUri,thumb)
            mDatas?.add(bean)//MutableList才有add方法
            println("获取数据成功:" + bean.toString())
        }
        cursor.close();
        //数据源变化 ,提示适配器更新 //将测试数据去掉
        adapterT?.notifyDataSetChanged();
    }
  1. 拿到专辑图片路径后,转为bitmap
//创建封面图片方法
    fun createThumbFromUir(res: ContentResolver, albumUri: Uri): Bitmap ?{
        var inF: InputStream? = null
        var bmp: Bitmap? = null
        try {
            inF = res.openInputStream(albumUri)
            val sBitmapOptions = BitmapFactory.Options()
            bmp = BitmapFactory.decodeStream(inF, null, sBitmapOptions)//流用stream直接图片用decodeResource
            inF!!.close()
        } catch (e: FileNotFoundException) {

        } catch (e: IOException) {
            e.printStackTrace()
        }

        return bmp
    }

二、 耳机控制

一、蓝牙与耳机断开/连接监听

二、音频抢占

三、Android耳机线控-播放/暂停/上一曲/下一曲

补充知识

一、android 媒体库数据更新解决办法总结

四、如何获取媒体库中所有音频文件信息,并在文件增删后及时更新媒体库_android中获取内存中的所有音频及其信息

五、android 多媒体播放 MediaSession 框架

六、MediaSession框架_mediasession 框架

八、Android 实现ListView的A-Z字母排序和过滤搜索功能,实现汉字转成拼音_xiaanming的博客-CSDN博客

九、Android之MediaStore使用的点点滴滴

十、MediaMetadataRetriever  |  Android Developers

  • Android低版本可用这个获取比特率,
  • 缺点是耗时太长

十一、query查询组写法可以参照这个: 访问共享存储空间中的媒体文件  |  Android 开发者  |  Android Developers

Exoplayer