如下是我自己研究过程的总结,想知道结果的直接看最后即可。
==============================过程总结==========================================
在上篇博客中我写到,在远程控制音乐软件的实现中,我在4.4系统里遇到了问题。需要获取到当前播放的音乐软件的包名才能解决。就在进行了一定时间的查找,意外的发现android貌似没有提供这样的api。这一下我一下丢失了方向。甚至想到直接获取系统中所有的包名,直接搜索常用音乐软件来草草完成。
最后由于时间比较充裕,就多研究了一段时间,突然想到,这既然是系统的为了耳机来完成远程控制的动作,那么系统应该会注意到这个问题才对。果然,我使用耳机上的按钮来操作,则没有任何问题。所以我开始研究android的系统源码究竟是如何做到这一点的。耳机控制需要使用Intent的,在intent.java(以下代码均来源于android4.4源码)中可以找到如下字段:
public static final String ACTION_MEDIA_BUTTON = "android.intent.action.MEDIA_BUTTON";
这就是android自己用于耳机控制播放器的intent action字段了,我们可以利用它来找到相关代码,很容易我们找到了这个类MediaFocusControl类,其中包含方法dispatchMediaKeyEvent():
private void dispatchMediaKeyEvent(KeyEvent keyEvent, boolean needWakeLock) {
.................
Intent keyIntent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
....................
mRCStack.peek().mMediaIntent.send(mContext,
needWakeLock ? WAKELOCK_RELEASE_ON_FINISHED : 0 /*code*/,
keyIntent, this, mEventHandler);
....................
}
这里讲intent发送了出去,具体去了哪里我们不用操心,我们只要知道谁用了这个intent。这里的mRCStack是一个Stack类,其中包含着我们需要的RemoteControlStackEntry类对象。我们继续查看,这个对象是在哪被放入Stack中的,最后找到pushMediaButtonReceiver_syncAfRcs()方法,其中关键部分如下:
private boolean pushMediaButtonReceiver_syncAfRcs(PendingIntent mediaIntent,
ComponentName target, IBinder token) {
...........
if (!wasInsideStack) {
rcse = new RemoteControlStackEntry(this, mediaIntent, target, token);
}
mRCStack.push(rcse); //rcse被push进mRCStack
..........
}
由此,可以知道这个rcse就是我们需要的对象,而他是被直接new出来的,则这个构造函数的参数就变的很重要了。查看构造函数如下:
public RemoteControlStackEntry(MediaFocusControl controller, PendingIntent mediaIntent,
ComponentName eventReceiver, IBinder token)
可以发现,里面包含了一个重要的ComponentName对象,这个对象在android中就带表着一个应用程序,看来这就是我们要找的音乐播放软件了。那么他是如何被系统拿出来的呢?我们继续找。在刚刚的构造方法创建对象过程中,这个参数是使用target变量直接放入的。而这个target是pushMediaButtonReceiver_syncAfRcs方法的一个参数,那么继续根据这个线索向上找。发现这个参量是经过registerMediaButtonIntent()传入,但是仍然是方法的一个参数,那么继续找,发现找到了源头:
protected void restoreMediaButtonReceiver() {
................
String receiverName = Settings.System.getStringForUser(mContentResolver,
Settings.System.MEDIA_BUTTON_RECEIVER, UserHandle.USER_CURRENT);
ComponentName eventReceiver = ComponentName.unflattenFromString(receiverName);
................
registerMediaButtonIntent(pi, eventReceiver, null);
}
由此我们发现了ComponentName对象的创建过程,它使用了一个receiverName对象,这个是个String,他就是我们的目标了。这是用了system的一个方法来创建,进入发现他竟然是个hide的方法,无法作为api使用。后来分析了方法名才释然,这个适用于多用户的,android4.3以后准备加入用户系统,可惜还不完善所以不给我们用,这肯定是有一般方法的,很快找到了getString方法,其实他就是调用了getStringForUser而已,只是屏蔽了id的参数。但是还有一个小问题,其实Settings.System.MEDIA_BUTTON_RECEIVER字段也是个hide字段,是不可以当做api来用的,我想这就系统根本就是不想提供获取正在播放音乐的软件的方法,不过既然是个字段就没问题了,我们查看一下源码就能看到MEDIA_BUTTON_RECEIVER字段其实就代表着"media_button_receiver"而已。到这里我们已经可以实现功能了。方法如下,其实就简单的三句即可:
================================功能实现===========================================
String receiverName = Settings.System.getString(this.getContentResolver(),
"media_button_receiver");
ComponentName eventReceiver = ComponentName.unflattenFromString(receiverName);
String musicPlayerPkgName = eventReceiver.getPackageName();
我们即可得到我们所需要的包名。
相关推荐
【VB定时播放音乐软件与闹钟系统开发】 VB(Visual Basic)是Microsoft公司推出的一种面向对象的编程语言,尤其适合初学者和快速开发小型应用程序。在这个项目中,我们看到一个VB应用被用来创建一个定时播放音乐的...
在中断服务函数里,我们可以根据当前播放的音符改变PWM的占空比,并更新音乐播放的位置。此外,还要注意处理音乐的暂停、停止和重置等操作。 在Proteus仿真环境中,我们需要创建一个包含音乐播放硬件的电路模型。这...
音乐播放的关键在于控制单片机的定时器产生精确的时序脉冲,这些脉冲通过振荡器转换为音频信号,进而驱动扬声器播放音乐。 在描述中提到的“简谱翻译成频率”的小软件,其实是一个将音乐乐谱转换为对应频率值的工具...
显示正在播放的信息通常包括当前歌曲名、艺术家、专辑封面、播放进度等。这些信息可以从音频文件的元数据中提取,元数据通常包含在音频文件的头部。对于没有元数据的文件,可能需要用户手动输入。这些信息可以通过...
计算属性则用于根据其他数据生成衍生值,如歌词滚动可能就需要依赖当前播放时间的计算属性。 【事件处理】 Vue.js 提供了事件绑定机制,使得用户交互可以轻松处理。例如,点击歌曲列表项可以触发播放指定歌曲的事件...
- `while(1)` 循环确保程序持续运行,不断播放音乐。 - 在循环内,通过判断数组中的元素来决定播放什么音符。当遇到结束符(0x00)时,会延时1秒后重新开始播放;遇到休止符(0xff)时,会延时100毫秒后继续播放下...
- 类`WavePlayer`可能是这个项目的核心,它封装了播放音乐的功能。类通常包含私有成员变量来存储音频文件信息和播放状态,以及公共成员函数来实现播放、暂停、调整音量等操作。 2. **MFC库**: - MFC是微软提供的...
在IT行业中,音频处理是一个重要的领域,特别是在多媒体应用和音乐软件开发中。MP3是一种广泛使用的音频格式,它使用有损压缩技术,能在保持相对高质量的同时显著减小文件大小。当我们处理MP3文件时,有时需要获取其...
"仿云音乐黑胶唱片"是一个项目,旨在模仿云音乐的特色,同时具备播放音乐的基本功能,如播放、暂停、切换歌曲以及调整播放进度。在这个项目中,我们可以探讨几个关键的知识点: 1. **用户界面(UI)设计**: - **...
实验内容要求综合运用各种Android知识,如UI界面设计(如ListView)、数据存储(可能涉及到SQLite数据库存储音乐信息)、Activity(负责用户交互)和服务(Service,用于后台播放音乐)。音乐播放功能是通过Service...
8. **播放界面**:整个音乐软件的核心界面,通常包括当前播放歌曲的信息、进度条、快进/快退按钮等,设计时需考虑信息的清晰度和布局的合理性。 9. **混音调整按钮**:高级音乐软件通常包含混音功能,允许用户...
在解决iTOP-4412开发板搭配Ubuntu 12.0.4系统播放音乐没有声音的问题中,主要涉及到了几个关键的知识点,包括Linux声音系统的配置、pulseaudio服务的启动与配置,以及系统权限与模块管理。 首先,对于在Ubuntu系统...
至于压缩包子文件的文件名称“黄金眼图片浏览器 (4.3)”,这可能是该软件的版本信息,暗示这是一款名为“黄金眼”的图片浏览器,当前版本为4.3。这个名称可能寓意着该软件具有敏锐的图像处理能力,如同“黄金眼”般...
创建一个新的`Audio`对象,然后设置其`src`属性为音乐文件的路径,最后调用`play()`方法即可播放音乐。例如: ```javascript let audio = new Audio(); audio.src = 'path/to/music.mp3'; audio.play(); ``` 2...
"会议专用音频播放器sportsound"指的是专为会议场景设计的一款音频播放软件,名为SportsSounds Pro。这款应用可能具有针对会议需求优化的功能,如清晰的音质、方便的操作界面以及与会议流程相适应的特性。 【描述...
10. **播放位置控制**:通过获取音频流的长度和当前播放位置,用户可以使用滑块控制播放进度。 总之,开发一个Java音乐播放器涉及了多媒体处理、用户交互、文件操作等多个Java核心领域的知识。通过学习和实践,...
8. **UI反馈**:为了提供良好的用户体验,播放器的界面需要实时反映播放状态,比如显示当前播放的歌曲名、艺术家、进度条以及播放/暂停按钮的状态。 综上所述,这个"C#音乐播放器可随机单曲播放"项目涉及了C#基础、...
- **同步UI与音频状态**:在播放音乐时,需要实时更新UI以反映当前播放状态,比如进度条的长度和位置、播放/暂停按钮的状态等。这可能涉及到UI线程与后台音频处理线程之间的通信,需注意线程同步问题。 6. **文件...
该应用允许用户在线播放音乐,并且在用户离开播放页面时,音乐播放不会中断,而是通过一个浮动窗口持续显示。 首先,我们要了解Swift的基础知识。Swift是由Apple开发的一种编程语言,它具有现代编程语言的特点,如...
"同步MSN正在播放的音乐"表明该软件具有与MSN即时通讯软件的联动功能,能够在使用MSN聊天时自动分享或展示用户当前正在通过豆瓣电台收听的歌曲信息。 【描述详解】 描述中提到的"豆瓣电台桌面程序"是一款独立的应用...