Android中通过耳机按键控制音乐播放的实现
今天在研究Android中实现Android 4.2.2源码中的Music应用的源码,关于通过耳机按键控制音乐播放的实现,有点好奇,就仔细分析了一下源码,
主要由 MediaButtonIntentReceiver 这个类来实现。
在AndroidManifest.xml中有如下Receiver的注册:
<receiver android:name="com.huawei.imax.music.MediaButtonIntentReceiver" >
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
<action android:name="android.media.AUDIO_BECOMING_NOISY" />
</intent-filter>
</receiver>
其实关键是对这两个ACTION的监控:
android.intent.action.MEDIA_BUTTON的说明如下,从注释看,就是媒体按键被按下后,通过 Intent.EXTRA_KEY_EVENT 中带上触发此事件的具体按钮事件:
/**
* Broadcast Action: The "Media Button" was pressed. Includes a single
* extra field, {@link #EXTRA_KEY_EVENT}, containing the key event that
* caused the broadcast.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_MEDIA_BUTTON = "android.intent.action.MEDIA_BUTTON";
android.intent.action.AUDIO_BECOMING_NOISY的说明如下(自己翻译的,大概这个意思),
从注释看,当音频变得“吵闹”,比如耳机拔出,或者A2DP音频通道(比如通过蓝牙音箱播放音乐就是一种A2DP的应用场景)断开,
音频系统将会自动将音频转到自带的扬声器。收到此intent的控制音频的应用可以暂停,降低音量或其它操作,以防扬声器突然发出声音让用户受惊:
/**
* Broadcast intent, a hint for applications that audio is about to become
* 'noisy' due to a change in audio outputs. For example, this intent may
* be sent when a wired headset is unplugged, or when an A2DP audio
* sink is disconnected, and the audio system is about to automatically
* switch audio route to the speaker. Applications that are controlling
* audio streams may consider pausing, reducing volume or some other action
* on receipt of this intent so as not to surprise the user with audio
* from the speaker.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_AUDIO_BECOMING_NOISY = "android.media.AUDIO_BECOMING_NOISY";
MediaButtonIntentReceiver 的关键实现如下:
public class MediaButtonIntentReceiver extends BroadcastReceiver
{
... @Override
public void onReceive(Context context, Intent intent)
{
String intentAction = intent.getAction();
if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intentAction))
{
Intent i = new Intent(context, MediaPlaybackService.class);
i.setAction(MediaPlaybackService.SERVICECMD);
i.putExtra(MediaPlaybackService.CMDNAME,
MediaPlaybackService.CMDPAUSE);
context.startService(i);
}
else if (Intent.ACTION_MEDIA_BUTTON.equals(intentAction))
{
KeyEvent event = (KeyEvent) intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT); if (event == null)
{
return;
} int keycode = event.getKeyCode();
int action = event.getAction();
long eventtime = event.getEventTime(); // single quick press: pause/resume.
// double press: next track
// long press: start auto-shuffle mode. String command = null;
switch (keycode)
{
case KeyEvent.KEYCODE_MEDIA_STOP:
command = MediaPlaybackService.CMDSTOP;
break;
case KeyEvent.KEYCODE_HEADSETHOOK:
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
command = MediaPlaybackService.CMDTOGGLEPAUSE;
break;
case KeyEvent.KEYCODE_MEDIA_NEXT:
command = MediaPlaybackService.CMDNEXT;
break;
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
command = MediaPlaybackService.CMDPREVIOUS;
break;
case KeyEvent.KEYCODE_MEDIA_PAUSE:
command = MediaPlaybackService.CMDPAUSE;
break;
case KeyEvent.KEYCODE_MEDIA_PLAY:
command = MediaPlaybackService.CMDPLAY;
break;
}
通过接收此事件的广播,想进行什么操作,完全看你的业务需求了。
一开始以为耳机插拔,是通过ACTION_HEADSET_PLUG这个Action来控制,但Music并没有监听此事件,
/**
* Broadcast Action: Wired Headset plugged in or unplugged.
*
* <p>The intent will have the following extra values:
* <ul>
* <li><em>state</em> - 0 for unplugged, 1 for plugged. </li>
* <li><em>name</em> - Headset type, human readable string </li>
* <li><em>microphone</em> - 1 if headset has a microphone, 0 otherwise </li>
* </ul>
* </ul>
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_HEADSET_PLUG =
"android.intent.action.HEADSET_PLUG";
自己测试了一下,在AndroidManifest.xml中静态注册,是不会生效的,为啥?
一个很简单的解释,如果你的应用还没有运行,这时插入耳机,系统如何把这个消息给这个应用?
因此,"android.intent.action.HEADSET_PLUG" 只能通过动态注册来接收此广播消息。
如果让 MediaButtonIntentReceiver 还接收"android.intent.action.HEADSET_PLUG"的广播消息,
则MediaButtonIntentReceiver会先收到 "android.media.AUDIO_BECOMING_NOISY" 这个消息,然后才会收到"android.intent.action.HEADSET_PLUG"这个消息?
为什么这样,代码层面还没有分析,后面抽空再研究下Android源码。
Android中通过耳机按键控制音乐播放的实现的更多相关文章
- AudioManager: android插上耳机仍然使用扬声器播放音频
手机音频的输出有外放(Speaker).听筒(Telephone Receiver).有线耳机(WiredHeadset).蓝牙音箱(Bluetooth A2DP)等输出设备.在平时,电话免提.插拔耳 ...
- html5 js控制音乐播放
<!DOCTYPE HTML><html><head><meta charset="UTF-8"><script lang ...
- Android查询系统的音频(音乐播放器的核心)
//查询系统的音频库 public static List<MusicBean> getMusicInfo(Context context){ List<MusicBean> ...
- Android使用的webcview中带有音乐播放控件,在关闭或分享时处于界面不可见状态下,声音仍在播放的问题解决
一. 问题出现原因 我们在做APP分享时,分享webview加载带有音乐播放控件的网页.当弹出分享界面,webview的网页处于后台状态或关闭该网页时,音乐声仍在播放.出现该类现象使我 ...
- Android大作业 --音乐播放器
1.项目成员(本次作业主要对上一次的音乐播放器进行完善) 韦家城 学号:1600802026 班级:161 博客:https://www.cnblogs.com/ln9969cc/ 邓乾尧 学号:1 ...
- Android 实现简单音乐播放器(一)
今天掐指一算,学习Android长达近两个月了,今天开始,对过去一段时间的学习收获以及遇到的疑难杂症做一些总结. 简单音乐播放器是我自己完成的第一个功能较为完整的APP,可以说是我的Android学习 ...
- 微信小程序-图片、录音、音频播放、音乐播放、视屏、文件
图片: wx.chooseImage(OBJECT) 从本地相册选择图片或使用相机拍照. OBJECT参数说明: 注:文件的临时路径,在小程序本次启动期间可以正常使用,如需持久保存,需在主动调用 wx ...
- Android中Services简析
Services是Android中四大基础组件(Activities. Services. Content Providers. BroadCast Receivers)之一,主要用于在后台长时间运行 ...
- 微信小程序后台音乐播放注意事项
wx.seekBackgroundAudio(OBJECT) 作用:控制音乐播放进度. 注意: 该事件 会触发 wx.onBackgroundAudioPlay(CALLBACK) 事件 ,也就是相当 ...
随机推荐
- C++创建对象的三种方式
C++在创建对象的时候,有三种方式: #include <iostream> using namespace std; class A { private: int n; public: ...
- java虚拟机内存溢出各种场景总结
java堆溢出 java堆用于存储对象实例,只要不断地创建对象,并且保证gc roots到对象之间有可达路径来避免垃圾回收机制来清楚这些对象,那么在 对象到达最大堆的容量限制后就会产生内存溢出溢出. ...
- foreach学习笔记
对集合进行遍历 只能获取集合元素,但是不能对集合进行操作. 迭代器除了遍历,还可以进行remove的动作. 如果是用ListIterator,还可以在遍历过程中进行增删改查的动作. for(Strin ...
- eclipse导出doc文档
选中需要导出的项目, 1 点击eclipse上面的Project,选择Generate javadoc..., 2 然后配置 javadoc command,比如我本地的路径为: C:\Program ...
- PHP函数积累
1.mt_rand(min,max):随机返回min,max之间的随整数机数. 2.date('Y-m-d H:m:s',时间戳),将时间戳格式化为相应的时间格式.time()取得时间戳 3.arra ...
- Linux 环境下 fork 函数和 exec 函数族的使用
前言 接触 Linux 已经有几个月了,以前在网上看各路大神均表示 Windows 是最烂的开发平台,我总是不以为然,但是经过这段时间琢磨,确实觉得 Linux 开发给我带来不少的便利.下面总结一下学 ...
- 【转载】Google Analytics 使用图文全攻略
转载自:Google Analytics 使用图文全攻略 最近一段时间,因为工作的需要,小励使用GA(GA是Google Analytics的简称)比较频繁,所以花时间研究了一下,从不太了解到会使用( ...
- 在Github上搭建你的博客
title: blog on github date: 2014-03-24 20:29:47 tags: [blog,github,hexo] --- **用Github写博文** 参考http:/ ...
- 链接分析算法之:HITS算法
链接分析算法之:HITS算法 HITS(HITS(Hyperlink - Induced Topic Search) ) 算法是由康奈尔大学( Cornell University ) 的Jo ...
- poj 3295 Tautology(栈)
题目链接:http://poj.org/problem?id=3295 思路分析:判断逻辑表达式是否为永真式问题.根据该表达式的特点,逻辑词在逻辑变量前,类似于后缀表达式求值问题. 算法中使用两个栈, ...