一、基本音乐播放器
几年前写的,从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、 盘一下各种关系:
- 是个类
- 从三个里继承了常量
- MediaStore.MediaColumns 是个接口
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 ;//存储封面图片
一、权限配置
- 先在清单文件中加入
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>.安卓4.4后写需要权限 - 6.0 后的动态权限申请,传送门先不写,这个文章自己还没写好
二、Layout设计
- Relativelayout,上面有个RecycleView
- 下面有个信息栏RelativeLayout
三、获取本地数据
//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();
}
- 拿到专辑图片路径后,转为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
}
二、 耳机控制
一、蓝牙与耳机断开/连接监听
- 样品工具库:kirikaTowa/AndroidUtils: Common tool library
- 分支:demo_bluetooth_headset
二、音频抢占
三、Android耳机线控-播放/暂停/上一曲/下一曲
补充知识
四、如何获取媒体库中所有音频文件信息,并在文件增删后及时更新媒体库_android中获取内存中的所有音频及其信息
五、android 多媒体播放 MediaSession 框架
六、MediaSession框架_mediasession 框架
八、Android 实现ListView的A-Z字母排序和过滤搜索功能,实现汉字转成拼音_xiaanming的博客-CSDN博客
十、MediaMetadataRetriever | Android Developers
- Android低版本可用这个获取比特率,
- 缺点是耗时太长
十一、query查询组写法可以参照这个: 访问共享存储空间中的媒体文件 | Android 开发者 | Android Developers
- MediaStore.Audio.Media
- MediaStore.MediaColumns | Android Developers
- bitrate API 30才有,
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.R),Android 11;