Android车载蓝牙音乐实例(附Demo源码):实现手机播放音乐后车机应用显示音乐名称,歌手,专辑名。且可控制上一曲下一曲,暂停播放功能

一、功能需求

功能需求是在Android10以上设备上实现蓝牙音乐功能,细分为两个功能点:

1、手机和车载设备实现蓝牙连接 (本Demo文只做监听蓝牙连接状态,需手动到设置中连接蓝牙)

2、连接蓝牙成功后手机播放音乐时车载设备也能播放音乐,并且在车机应用上显示音乐名称,歌手,专辑名。可在车机应用中点击播放,暂停,上一曲,下一曲控制手机端的音乐播放。

二、实现效果图

Demo地址:BluetoothMediaDemo: 实现Android10以上设备蓝牙音乐功能,Demo主要实现两步: 1、监听蓝牙连接状态 2、手机播放音乐时车载设备播放手机的音乐,并且在车机应用上显示音乐名称,歌手,专辑名。可在车机应用中点击播放,暂停,上一曲,下一曲控制手机端的音乐播放 (gitee.com)

三、代码详解

3.1、实现原理:

     安卓系统通过媒体浏览器服务已经为大家提供了一套完整的音乐控制解决方案,并进行了封装。所以音乐类应用通过媒体浏览器服务可以轻松实现音乐控制等功能

     蓝牙音乐应用根据当前系统的安卓版本通过构建相应的 ComponentName来初始化媒体浏览器服务的客户端也即是 MediaBrowser 来连接媒体浏览器服务的服务端 MediaBrowserService,连接成功后应用获取到 MediaController 来控制音乐。

     因为ComponentName指明了bind哪个服务,从而可以正确找到蓝牙服务中对应于媒体浏览器的服务。根据蓝牙服务的清单文件AndroidManifest.xml指定,应用构建相应的ComponentName,构建此变量需要提供包名package和类名class。

3.2、代码分析:

1、按照以上实现原理,首先我们需要连接媒体浏览器服务:

(1)、android-7(N版本) ~ android-9(P版本):

       String package = "com.android.bluetooth"

       String class = "com.android.bluetooth.a2dpsink.mbs.A2dpMediaBrowserService" 

 (2)、Android10以上的版本服务包名和文件名分别为:

       String package = "com.android.bluetooth"

       String class = "com.android.bluetooth.avrcpcontroller.BluetoothMediaBrowserService"

 private void connectMediaBrowser() {//1.绑定服务,Android10以上的版本服务名称为ComponentName componentName = new ComponentName("com.android.bluetooth", "com.android.bluetooth.avrcpcontroller.BluetoothMediaBrowserService");// 2.创建MediaBrowsermMediaBrowser = new MediaBrowser(this, componentName, connectionCallback, null);//3.连接MediaBrowsermMediaBrowser.connect();}
2、connectionCallback接口回调监听与流媒体服务是否连接成功,若连接成功则获取MediaController对象,通过MediaController 来控制音乐
private MediaBrowser.ConnectionCallback connectionCallback = new MediaBrowser.ConnectionCallback() {public void onConnected() {//如果服务端接受连接,就会调此方法表示连接成功,否则回调onConnectionFailed();Log.d(TAG, "onConnected: ");//获取配对令牌MediaSession.Token token = mMediaBrowser.getSessionToken();//通过token,获取MediaController,第一个参数是context,第二个参数为tokenmMediaController = new MediaController(mContext, token);Log.e(TAG, "mMediaController===" + mMediaController);//mediaController注册回调,callback就是媒体信息改变后,服务给客户端的回调mMediaController.registerCallback(mMediaCallBack);}public void onConnectionSuspended() {Log.d(TAG, "onConnectionSuspended: ");//与服务断开回调(可选)}public void onConnectionFailed() {Log.d(TAG, "onConnectionFailed: ");//连接失败回调(可选)}};
3、MediaController.Callback接口监听音乐信息和播放状态的变化,得到MediaMetadata 对象后通过MediaDescription 即可获取音乐名称,歌手,专辑名。PlaybackState获取播放状态,进度。

 详细接口解释可参考Android官方文档:MediaDescription  |  Android Developers (google.cn)

 

 private MediaController.Callback mMediaCallBack = new MediaController.Callback() {@Overridepublic void onMetadataChanged(@Nullable MediaMetadata metadata) {super.onMetadataChanged(metadata);if (metadata != null) {MediaDescription description = metadata.getDescription();String title=description.getTitle().toString();//音乐名称String singer=description.getSubtitle().toString();//歌手String album=description.getDescription().toString();//专辑名称}}@Overridepublic void onPlaybackStateChanged(@Nullable PlaybackState state) {super.onPlaybackStateChanged(state);//播放状态信息回调long position = state.getPosition();//获取当前播放进度int playState=state.getState(); //当前播放状态      }};
4、蓝牙音乐通过 MediaController.getTransportControls()提供的音乐控制接口下发相应的指令,指令经过媒体浏览器服务转送到蓝牙服务中,通过蓝牙技术传输到远端设备执行响应的动作,最终达到控制蓝牙音乐的目的。
mMediaController.getTransportControls().skipToPrevious();//上一曲
mMediaController.getTransportControls().skipToNext();//下一曲
mMediaController.getTransportControls().play()//播放
mMediaController.getTransportControls().pause();//暂停
5、注意我们需要在AndroidManifest文件中申请权限,如果是Android 10以上设备还需要动态申请权限
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

详细有关蓝牙协议的源码分析可参考文章:

Android 控制车载蓝牙播放音乐详解流程_Android_脚本之家 (jb51.net)

创造不易,转载请标明出处!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/52337.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python常用内置函数(二)

Python 常用内置函数及示例&#xff08;续&#xff09; 在前面的基础上&#xff0c;我们将继续介绍另外50个常用的Python内置函数&#xff0c;并给出每个函数的简短说明和示例。 1. callable() 功能: 检查对象是否可调用。示例:def func(): pass print(callable(func)) # 输…

leetcode 递归(回溯)——java实现

递归算法与DFS类似&#xff0c;也与二叉树的先序遍历类似 以下摘自 leetcode回溯算法入门级详解 回溯法 采用试错的思想&#xff0c;它尝试分步的去解决一个问题。在分步解决问题的过程中&#xff0c;当它通过尝试发现现有的分步答案不能得到有效的正确的解答的时候&#xff…

了解蜜罐网络技术:网络安全中的诱捕与防御

在网络安全领域&#xff0c;攻击者和防御者之间的斗争日趋激烈。为了更好地识别、分析和抵御网络攻击&#xff0c;安全专家开发了一种称为蜜罐网络技术&#xff08;Honeypot Network Technology&#xff09;的防御策略。蜜罐网络不仅能够吸引攻击者进入虚假的环境&#xff0c;从…

MySQL笔记01: MySQL入门_1.2 MySQL下载安装与配置

2.2 MySQL下载安装与配置 2.2.1 MySQL下载 MySQL中文官网&#xff1a;https://www.mysql.com/cn/ MySQL英文官网&#xff1a;https://www.mysql.com/ MySQL官网下载地址&#xff1a;https://www.mysql.com/downloads/ &#xff08;1&#xff09;点击“MySQL Community (GPL) Do…

TinaSDKV2.0 自定义系统开发

TinaSDKV2.0 自定义系统开发 什么是自定义系统&#xff1f; TinaSDK Kconfig界面配置 Tina Linux采用 Kconfig 机制对 SDK 和内核进行配置。 Kconfig 是一种固定格式的配置文件。Linux 编译环境中的 menuconfig 程序可以识别这种格式的配置文件&#xff0c;并提取出有效信息…

catvod、TVBox源的解析过程分析和Spider参数覆盖问题解决

文章目录 TVBox官网源内容的结构 Spider参数覆盖问题Spider参数覆盖问题的解决脚本附录&#xff1a;核心代码分析首页详情页面播放界面获取播放信息源内容配置类Jar包解析类Js解析类Spider TVBox官网 TVBox项目索引&#xff1a;https://github.com/o0HalfLife0o/TVBoxOSC/ 完…

LibreWolf使用记录

之前一直使用Firefox作为个人主力浏览器&#xff0c;工作上由于有些网页兼容问题&#xff0c;一直使用的是Chrome。自从看了Eric Murphy 关于浏览器的分类之后, 出于对隐私的考虑&#xff0c;还是决定把chrome换成Brave&#xff0c;同时考虑对Firefox进行harden或者使用LibreWo…

从力扣中等+困难题+表白HTML测试 -- 文心快码(Baidu Comate)

0 写在前面 &#xff08;通过如下链接/二维码进入官网注册&#xff0c;并在IDE使用三次及以上可以找我领计算机基础/ML/DL 面经/知识点一份~&#xff09; 官网地址&#xff1a;Baidu Comate Step1 打开文心快码&#xff08;Baidu Comate&#xff09;官网&#xff0c;点击「免…

[Python可视化]空气污染物浓度地图可视化

[Python可视化]空气污染物浓度地图可视化&#xff0c;果然是路边浓度最大 在本篇文章中&#xff0c;我将展示如何使用 Python 结合 OSMnx、NetworkX 和 GeoPandas 等库&#xff0c;计算给定路径的最短路线&#xff0c;并基于该路径穿过的网格单元计算总污染量。最终&#xff0c…

【ORACLE】listagg() 函数

在Oracle数据库中&#xff0c;LISTAGG 函数是一个非常有用的聚合函数&#xff0c;它能够将多个行的字符串值连接成一个单独的字符串。这个函数在处理需要将多行数据合并为一行数据的场景中特别有用&#xff0c;比如生成报表或者构建复杂的字符串输出。 基本语法 LISTAGG 函数…

k8s - Secret实践练习

参考文档&#xff1a;https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/ 这个和ConfigMap很相似&#xff0c;这里选两个做下测试&#xff0c;就不过多赘述了 简介 Secret 类似于 ConfigMap 但专门用于保存机密数据。 Secret 是一种包含少量敏感信息例如密码…

<数据集>鸟类识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;16287张 标注数量(xml文件个数)&#xff1a;16287 标注数量(txt文件个数)&#xff1a;16287 标注类别数&#xff1a;10 标注类别名称&#xff1a;[Chestnut Munia, Zebra Dove, Garden Sunbird, Collared Kingfish…

一篇文章入门Java虚拟机(JVM)

JVM全称是Java Virtual Machine&#xff0c;中文译名Java虚拟机。本质上是一个运行在计算机上的程序 一&#xff0c;JVM的功能 功能描述解释和运行对字节码文件中的指令&#xff0c;实时的解释成机器码&#xff0c;让计算机执行内存管理自动为对象、方法等分配内存&#xff1…

ChatGPT 3.5/4.0 新手使用手册

ChatGPT 3.5/4.0 新手使用手册 一、引言 ChatGPT 是由 OpenAI 开发的一种基于人工智能技术的聊天机器人&#xff0c;它能够自动生成自然语言的响应&#xff0c;与用户进行高质量的对话。ChatGPT 3.5 和 4.0 是该系列的最新版本&#xff0c;它们在自然语言处理、对话能力和知识…

海山数据库(He3DB)源码详解:CommitTransaction函数源码详解

文章目录 海山数据库(He3DB)源码详解&#xff1a;CommitTransaction函数1. 执行条件2. 执行过程2.1 获取当前节点状态&#xff1a;2.2 检查当前状态&#xff1a;2.3 预提交处理&#xff1a;2.4 提交处理&#xff1a;2.5 释放资源&#xff1a;2.6 提交事务&#xff1a; 作者介绍…

数据结构-线性表-了解循环链表

了解循环链表 循环链表是一种特殊的链表结构&#xff0c;其中最后一个节点的指针指向头节点&#xff0c;从而形成一个闭环。循环链表可以分为两种类型&#xff1a;单循环链表和双循环链表。 1. 单循环链表&#xff08;Singly Circular Linked List&#xff09; 定义&#xf…

Qt第十八章 XML和Json格式解析

文章目录 JSON格式解析Json生成案例 XML简介与HTML的区别格式XML解析流的方式DOM XML生成 JSON与XML的区别比较 JSON 格式 JSON是一个标记符的序列。这套标记符包含六个构造字符、字符串、数字和三个字面名 六个构造字符 开始和结束数组&#xff1a;[ ]开始和结束对象&#x…

基于HarmonyOS的宠物收养系统的设计与实现(一)

基于HarmonyOS的宠物收养系统的设计与实现&#xff08;一&#xff09; 本系统是简易的宠物收养系统&#xff0c;为了更加熟练地掌握HarmonyOS相关技术的使用。 项目创建 创建一个空项目取名为PetApp 首页实现&#xff08;组件导航使用&#xff09; 官方文档&#xff1a;组…

安卓中设置渐变字体和描边字体

1.CommonFontSpan abstract class CommonFontSpan : ReplacementSpan() {/** 测量的文本宽度 */private var mMeasureTextWidth 0foverride fun getSize(paint: Paint,text: CharSequence?,start: Int,end: Int,fontMetricsInt: FontMetricsInt?): Int {mMeasureTextWidth…

机器学习辅助复合材料预测,性能管理优化创新材料,这种王炸般的组合,还真是大开眼界!

在人工智能与复合材料技术融合的背景下&#xff0c;复合材料的研究和应用正迅速发展&#xff0c;创新解决方案层出不穷。从复合材料性能的精确预测到复杂材料结构的智能设计&#xff0c;从数据驱动的材料结构优化到多尺度分析&#xff0c;人工智能技术正以其强大的数据处理能力…