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.rhkb.cn/news/408476.html

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

相关文章

vscode修改选中文字颜色及当前tab颜色

VSCode-》首选项-》设置->-》搜color&#xff0c;找到&#xff1a;Workbench&#xff1a;Color Customizations&#xff0c;点击&#xff1a;在 settings.json 中编辑 加上 选中的文字内容的 配置 "workbench.colorCustomizations": {//设置用户选中代码段的颜色&…

前端——盒子模型

一个盒子的特点组成 外边距就是两个元素之前的距离 padding就是填充区的大小 从上开始 顺时针进行设置&#xff0c;没有则对称 也可以单独对某个方向进行设定&#xff0c;比如&#xff1a;padding-top border 边框区 符合属性 border-style 边框样式 border-color 边框颜色…

Flink常见数据源(source)使用教程(DataStream API)

前言 一个 Flink 程序,其实就是对 DataStream 的各种转换。具体来说,代码基本上都由以下几部分构成,如下图所示: 获取执行环境(execution environment)读取数据源(source)定义基于数据的转换操作(transformations)定义计算结果的输出位置(sink)触发程序执行(exec…

Ps:首选项 - 常规

Ps菜单&#xff1a;编辑/首选项 Edit/Preferences 快捷键&#xff1a;Ctrl K Photoshop 首选项中的“常规” General选项卡主要用于调整 Photoshop 的整体工作行为和用户体验。这些设置让用户可以根据个人习惯和工作流程定制软件的响应方式和界面布局&#xff0c;从而提高工作…

读软件开发安全之道:概念、设计与实施08密码学(下)

1. 对称加密 1.1. symmetric encryption 1.2. 使用各方共享的密钥来隐藏数据 1.2.1. 对称加密在本质上依赖共享密钥 1.3. 所有加密都是通过对明文进行转换&#xff0c;把明文消息&#xff08;或者原始消息&#xff09;变成无法识别的形式&#xff08;也称为密文&#xff09…

Linux 下命令行参数和环境变量

Linux 下命令行参数和环境变量 命令行参数为什么要有命令行参数谁可以做到结论 环境变量一些现象查看环境变量添加环境变量添加内存级环境变量永久有效 其他环境变量HOMEPWDSHELLHISTSIZE 自定义环境变量定义取消 本地变量整体理解环境变量环境变量的组织方式Linux 代码获取环境…

32 增加系统调用(1)

系统调用在 数据手册中的描述 这是在 GDT 中的描述符 这个系统调用 segment selector 指向的时 内核的代码段。因为系统调用需要的权限比较高。 offset 指的时 在内核代码中的具体的函数的地址。

深入浅出消息队列----【Broker 集群】

深入浅出消息队列----【Broker 集群】 单 master多 master多 master 多 slave 异步复制多 master 多 slave 同步复制Dledger 本文仅是文章笔记&#xff0c;整理了原文章中重要的知识点、记录了个人的看法 文章来源&#xff1a;编程导航-鱼皮【yes哥深入浅出消息队列专栏】 Brok…

ssrf攻击fastcgi复现

文章目录 环境搭建使用网页查看开始攻击 环境搭建 在/usr/local/nginx/html下新建一个php文件 phpinfo.php 1.php <?php highlight_file(__FILE__); $url $_GET[url]; $curl curl_init($url); curl_setopt($curl, CURLOPT_HEADER, 0); $responseText curl_exec($curl)…

Neo4J下载安装

Windows 版本 1、 下载链接安装JDK 下载链接 https://download.oracle.com/java/22/latest/jdk-22_windows-x64_bin.msi 下载完毕后默认安装即可 2、 下载Neo4J 进入Neo4j Deployment Center - Graph Database & Analytics下载页面&#xff0c;选择社区版&#xff0c;…

QT Quick QML 实例之定制 TableView

QT Quick QML 实例之定制 TableView 一、演示二、C关键步骤1. beginInsertRows()&#xff08;用户插入行&#xff09;2. roleNames() &#xff08;表格中列映射&#xff09;3. data() &#xff08;用户获取数据&#xff09;4. headerData() &#xff08;表头&#xff09;5. fla…

依靠 VPN 生存——探索 VPN 后利用技术

执行摘要 在这篇博文中,Akamai 研究人员强调了被忽视的 VPN 后利用威胁;也就是说,我们讨论了威胁行为者在入侵 VPN 服务器后可以用来进一步升级入侵的技术。 我们的发现包括影响 Ivanti Connect Secure 和 FortiGate VPN 的几个漏洞。 除了漏洞之外,我们还详细介绍了一组…

ETAS工具链自动化实战指南<二>

----自动化不仅是一种技术&#xff0c;更是一种思维方式&#xff0c;它将帮助我们在快节奏的工作环境中保持领先&#xff01; 目录 往期推荐 RTA-A2L工具概览 RTA-A2L的输出文件 常用命令行参数 场景1&#xff1a;通过 MCSD 文件来生成 .a2l 文件并更新地址 命令用法 命…

比Maven快2~10倍的编译工具mvnd简介与实战

概述 maven-mvnd&#xff0c;可简称&#xff08;或缩写&#xff09;mvnd&#xff0c;the Maven Daemon。Apache Maven团队借鉴Gradle和Takari后开发的更快的构建工具。mvnd内嵌Maven&#xff0c;开发者可无缝从Maven迁移到mvnd。 参考资料&#xff1a;GitHub。 mvnd中会启动…

【数据结构篇】~二叉树(堆)

【数据结构篇】~二叉树&#xff08;堆&#xff09; 二叉树1.树2.树的组成3.二叉树4.堆1.向上调整算法2.向下调整算法3.堆排序 4.topk问题源码 二叉树 1.树 树的概念与结构​ 树是一种非线性的数据结构&#xff0c;它是由 n&#xff08;n>0&#xff09; 个有限结点组成一个…

BUG——GT911上电后中断一直触发

版型&#xff1a;正点原子 I.MX6UL MINI板 屏幕&#xff1a;7寸 1024*600 ATK-MD0700R V1.4 我的建议是买7寸屏幕就不要Mini板&#xff0c;因为Mini板太小装不下7寸屏幕&#xff0c;你需要一个更大的板子 简介&#xff1a; 算是作为一个后来者对这一现象的补充。解决方案就…

linux memory cgroup的memory.move_charge_at_immigrate含义

1.内核文档 上面的例子说明&#xff1a; 最开始某个进程是在cgroup A中&#xff0c;后面要迁移到cgroup B中&#xff0c;那么进程的内存计数是否要完全迁入B中&#xff0c;就是通过memory.move_charge_at_immigrate控制&#xff0c;如果目标cgroup也就是B设置了1到该字段中&am…

DBeaver安装使用

文章目录 简介支持的数据库支持的系统 下载安装DBeaver使用修改Maven下载jar地址窗口->首选项连接->驱动->Maven配置仓库地址 选择需要连接的数据库进行连接 简介 DBeaver 是一个通用的数据库管理工具和 SQL 客户端&#xff0c;支持 MySQL, PostgreSQL, Oracle, DB2,…

进存销系统

摘 要 伴随着我国全面推动信息化的趋势&#xff0c;我国的很多行业都在朝着互联网的方向进发。商品销售行业也有很多挑战。这次论文介绍的进存销系统就是为了能够解决当前传统商品进存销存在的问题&#xff0c;使得商品进存销能够更加有效率。电商智能化管理必不可少的帮手有进…

【VIsion Master】机器视觉软件二次开发(C#版本)学习笔记

0.前言 最近接手新项目&#xff0c;用海康威视旗下的HIK ROBOT Vision Master机器视觉软件做二次开发相关的项目&#xff0c;写一篇博客记录一下学习过程。 参考视频&#xff1a;https://www.bilibili.com/video/BV1tq4y1j7RP?p1 其他参考资料&#xff1a;软件自带的开发文档…