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

news2024/9/26 1:25:06

一、功能需求

功能需求是在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.创建MediaBrowser
        mMediaBrowser = new MediaBrowser(this, componentName, connectionCallback, null);
        //3.连接MediaBrowser
        mMediaBrowser.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,第二个参数为token
            mMediaController = 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() {
        @Override
        public 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();//专辑名称
              
            }
        }

        @Override
        public 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.coloradmin.cn/o/2067414.html

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

相关文章

【python报错已解决】“IndexError: list index out of range”

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 引言 你是否在处理Python列表时遇到了“IndexError: list index out of range”的错误&#xff1f;这个错误可能会让你的程序中…

51单片机最快能生成多高频率的方波?

前言 在嵌入式系统开发中&#xff0c;51 单片机作为一种非常非常非常经典&#xff0c;贯穿上下几十年的微控制器&#xff0c;被广泛应用于各种电子项目中。其中&#xff0c;生成特定频率的方波信号是一项常见的需求。 那么&#xff0c;51 单片机究竟能以多快的速度生成方波呢&…

STM32——GPS模块(GY-NEO-6M)

1连接 1-1 使用 USB-TTL 工具&#xff0c;安装好驱动&#xff0c;可以在”设备管理器看到对应COM”按照如下链接测试模块&#xff1a; USB-TTL GPS 模块 3.3V--------------------------------->VCC GND------------------------------>GND RXD--------------------…

应用程自定义协议与序列化反序列化

本篇将主要介绍在应用层中自定义的协议&#xff0c;自定义协议的同时还需要将我们的数据继续序列化和反序列化&#xff0c;所以本篇的重点为序列化、反序列化的原因以及如何自定义协议&#xff0c;接着探讨了关于为什么 tcp 协议可以支持全双工协议。还根据用户自定义协议结合 …

⼆⼿⻋交易系统前景分析

二手车交易系统开发小程序在当前市场中具有显著的优势和潜力。以下是对二手车交易系统小程序功能的综合分析&#xff1a; 车辆信息展示&#xff1a;小程序应提供详细的车辆信息展示&#xff0c;包括车辆的图片、品牌、型号、年份、里程数、价格等关键信息&#xff0c;方便用户…

Python爬虫—常用的网络爬虫工具推荐

以下列举几个常用的网络爬虫工具 1. 八爪鱼&#xff08;Bazhuayu&#xff09; 简介&#xff1a; 八爪鱼是一款面向非技术用户的桌面端爬虫软件&#xff0c;以其可视化操作和强大的模板库而受到青睐。它支持从各种网站上抓取数据&#xff0c;包括文本、图片、文档等&#xff…

特殊类设计和类型转换

前言 这一篇博客我们讲特殊类设计和类型转换 1. 特殊类设计 1.1 请设计一个类&#xff0c;不能被拷贝 这个比较简单 第一种方法就是将赋值和拷贝构造只定义不声明然后设置为私有就可以了 第二种方法就是直接令它为delete 1.2 请设计一个类&#xff0c;只能在堆上创建对象 …

自学成才:通过自学成为软件开发者——之入行成为软件开发者

一些优秀的程序员&#xff0c;可能以前从事的是其他职业&#xff0c;他们大都发现工作中的很多固定化的流程内容&#xff0c;如果可以实现自动化&#xff0c;不仅效率能够得到提高和保证&#xff0c;提高自己的生成力&#xff0c;同时自己也会从中释放出来&#xff0c;有更多的…

Go使用MongoDB应用指南

Go使用MongoDB应用指南 MongoDB 是一种高性能、开源、文档型的 NoSQL 数据库&#xff0c;广泛应用于 Web 应用、大数据以及云计算领域。Go 语言则以其快速、开发效率高、代码可维护性强著称。本指南将详细介绍如何在 Go 语言中使用 MongoDB 进行数据库操作&#xff0c;包括连接…

鸿蒙HarmonyOS开发知识:命令行工具Command Line Tools

该命令行工具集合了HarmonyOS应用开发所用到的系列工具&#xff0c;包括代码检查codelinter、三方库的包管理ohpm、命令行解析hstack、编译构建hvigorw。 命令行工具获取 请前往下载中心获取并下载命令行工具Command Line Tools。 配置环境变量 Windows 将解压后command-l…

英语四六级有多重要你不知道

卷出天际 IT业内卷严重大家都知道 因此也就打击了很多想入行的新人 到底什么是核心竞争力 放在十年前 稍微会Spring, CRUD 就能达到入门的台阶 那也是培训机构最繁荣的一段时期 而今顶峰已经过去 IT业从含金量上 已经大不如前 在野蛮发展期 如果不太挑的话 大专也是…

云轴科技ZStack AIOS平台智塔亮相FDS金融领袖峰会

人工智能&#xff08;AI&#xff09;正以前所未有的速度渗透到金融系统&#xff0c;推动着金融服务的创新和变革。这种深度融合不仅可以提高金融服务的效率和准确性&#xff0c;未来还可催生全新的金融产品和服务模式。尤其是生成式人工智能&#xff08;GenAI&#xff09;的出现…

算法的学习笔记—复杂链表的复制(牛客JZ35)

&#x1f600;前言 在许多实际应用中&#xff0c;我们会遇到复杂链表的复制问题。复杂链表不同于一般的单链表&#xff0c;不仅每个节点有指向下一个节点的指针&#xff0c;还有一个特殊的指针 random&#xff0c;可以指向链表中的任意节点或 null。如何高效地复制这样一个复杂…

CACTER直播预告:聚焦EDLP邮件数据防泄露实战重点

在信息高速流通的今天&#xff0c;邮件作为商务沟通的桥梁&#xff0c;不仅承载着日常沟通&#xff0c;更是企业机密和知识产权的重要载体。然而&#xff0c;邮件系统的开放性也使其成为网络攻击的主要目标。数据泄露不仅会导致商业损失&#xff0c;还可能对企业声誉造成不可逆…

【请安全下载】黑神话:悟空 单机游戏 它是如何保证安全的 怎样防破解的?安全措施:D加密,反外挂,代码加密,资源保护

单机 《黑神话&#xff1a;悟空》是一款单机游戏&#xff0c;由游戏科学开发&#xff0c;并于2024年8月20日全球同步上线。游戏以其独特的暗黑国风、深度的故事背景以及精致的游戏画面&#xff0c;重塑了西游题材&#xff0c;为玩家呈现了一个前所未有的悟空传奇。 黑神话&…

[Linux]在Ubuntu中安装samba并且正确配置(详细)

一、我们为什么需要samba服务 samba是一种实现windows和linux包括macos文件共享的套件。它能让我们像访问自己的磁盘一样去访问别的系统的文件。可以看得出来这种一种快速并且高效的文件传输协议。看到这里&#xff0c;大家可能会有些疑问。向linux传输文件&#xff0c;我们可以…

常用网络测试工具以及解决tcp协议带来得问题

一、解决粘包问题 1.1、tcp的特点 面向字节流特点&#xff0c;会造成可能数据与数据发送到一块&#xff0c;成为粘包&#xff0c;数据之间不区分 1.2、拆包 因为缓冲区的大小&#xff0c;一次性发送的数据会进行拆分&#xff08;大小不符合的时候&#xff09; 就和水一样一…

vue3使用i18n实现国际化

安装vue-i18n npm install vue-i18n创建一个ts文件用于存储各种翻译 globalLang.ts的内容如下&#xff1a; export default {"cn": {},"en": {},"de": {},"es": {},"fr": {},"id": {},"it": {},&quo…

HDMI画面发白

这个问题困扰我很久了&#xff0c;今天在抖音上看到了解决方案! https://v.douyin.com/Ceie2g2s/ 量化范围&#xff1a;有限范围改成全范围。

Tomcat安装部署

简介 Tomcat 是由 Apache 开发的一个 Servlet 容器&#xff0c;实现了对 Servlet 和 JSP 的支持&#xff0c;并提供了作为Web服务器的一些特有功能&#xff0c;如Tomcat管理和控制平台、安全域管理和Tomcat阀等。 简单来说&#xff0c;Tomcat是一个WEB应用程序的托管平台&…