当耳机的媒体按键被单击后,Android系统会发出一个广播,该广播的携带者一个Action名为MEDIA_BUTTON的Intent。监听该广播便可以获取手机的耳机媒体按键的单击事件。
在Android中有个AudioManager类,该类会维护MEDIA_BUTTON广播的分发,所以要实现耳机按键监听需要向AudioManager注册一个用于接收耳机按键单击事件的接收器:
1
2
3
4
5
|
AudioManager audioManager = (AudioManager)context
.getSystemService(Context.AUDIO_SERVICE);
ComponentName name = newComponentName(context.getPackageName(),
MediaButtonReceiver.
class
.getName());
audioManager.registerMediaButtonEventReceiver(name);
|
该方法的原型为:
publicvoid registerMediaButtonEventReceiver (PendingIntent eventReceiver)
Added in API level 18
Registera component to be the sole receiver of MEDIA_BUTTON intents. This is like registerMediaButtonEventReceiver(android.content.ComponentName), but allows the buttons to go to any PendingIntent. Note that you shouldonly use this form if you know you will continue running for the full timeuntil unregistering the PendingIntent.
Parameters
eventReceiver | target that will receive media button intents. The PendingIntent will be sent an ACTION_MEDIA_BUTTON event when a media button action occurs, with EXTRA_KEY_EVENT added and holding the key code of the media button that was pressed. |
从API注释中可知:
1、 在AudioManager对象注册一个MediaoButtonRecevie,使它成为MEDIA_BUTTON的唯一接收器,也就是说只有我能收到,其他的都收不到这个广播了,否则的话大家都收到会照成一定的混乱;
2、该广播必须在AndroidManifest.xml文件中进行声明,否则就监听不到该MEDIA_BUTTON广播了。
注,因为当我们注册了AudioManager媒体按键的接收器,并且该接收器是媒体按键的唯一接收器,所以要在不使用按键监听的时候取消该注册:
1
2
3
|
AudioManager audioManager = (AudioManager)context .getSystemService(Context.AUDIO_SERVICE);
ComponentName name = newComponentName(context.getPackageName(), MediaButtonReceiver.
class
.getName());
audioManager.unregisterMediaButtonEventReceiver(name);
|
当耳机媒体键发生单击事件的时候Android系统会发出两次广播,第一次是按键按下去的时候,第二次是松开按键的时候,为了能够准确的获知用户单击了几次媒体键,我们只需要在按键松开的时候处理单击事件即可:
1
2
3
4
|
KeyEvent keyEvent = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
//获得KeyEvent对象
if
(keyEvent.getAction()== KeyEvent.ACTION_UP){
//在这里处理单击事件
}
|
下面就分别讲解一下为了实现线控效果所用到的几个类:
1. 耳机线控管理工具类HeadSetUtil:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
package
com.jph.lc;
import
android.content.ComponentName;
import
android.content.Context;
import
android.media.AudioManager;
import
android.util.Log;
/**
* 耳机线控管理工具类 单例
* @author JPH
* @date 2015-6-9 下午4:03:45
*/
public
class
HeadSetUtil {
private
static
HeadSetUtil headSetUtil;
private
OnHeadSetListener headSetListener =
null
;
public
static
HeadSetUtil getInstance() {
if
(headSetUtil ==
null
) {
headSetUtil =
new
HeadSetUtil();
}
return
headSetUtil;
}
/**
* 设置耳机单击双击监听接口 必须在open前设置此接口,否则设置无效
* @param headSetListener
*/
public
void
setOnHeadSetListener(OnHeadSetListener headSetListener) {
this
.headSetListener = headSetListener;
}
/**
* 为MEDIA_BUTTON 意图注册接收器(注册开启耳机线控监听, 请务必在设置接口监听之后再调用此方法,否则接口无效)
* @param context
*/
public
void
open(Context context) {
if
(headSetListener==
null
){
throw
new
IllegalStateException(please set headSetListener);
}
AudioManager audioManager = (AudioManager) context
.getSystemService(Context.AUDIO_SERVICE);
ComponentName name =
new
ComponentName(context.getPackageName(),
MediaButtonReceiver.
class
.getName());
audioManager.registerMediaButtonEventReceiver(name);
Log.i(ksdinf, open);
}
/**
* 关闭耳机线控监听
* @param context
*/
public
void
close(Context context) {
AudioManager audioManager = (AudioManager) context
.getSystemService(Context.AUDIO_SERVICE);
ComponentName name =
new
ComponentName(context.getPackageName(),
MediaButtonReceiver.
class
.getName());
audioManager.unregisterMediaButtonEventReceiver(name);
}
/**
* 删除耳机单机双击监听接口
*/
public
void
delHeadSetListener() {
this
.headSetListener =
null
;
}
/**
* 获取耳机单击双击接口
*
* @return
*/
protected
OnHeadSetListener getOnHeadSetListener() {
return
headSetListener;
}
/**
* 耳机按钮单双击监听
*/
public
interface
OnHeadSetListener {
/**
* 单击触发,主线程。 此接口真正触发是在单击操作1秒后 因为需要判断1秒内是否仍监听到点击,有的话那就是双击了
*/
public
void
onClick();
/**
* 双击触发,此接口在主线程,可以放心使用
*/
public
void
onDoubleClick();
/**
* 三连击
*/
public
void
onThreeClick();
}
}
|
2.耳机媒体按键广播接收器MediaButtonReceiver:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
package
com.jph.lc;
import
java.util.Timer;
import
java.util.TimerTask;
import
android.content.BroadcastReceiver;
import
android.content.Context;
import
android.content.Intent;
import
android.os.Handler;
import
android.os.Message;
import
android.util.Log;
import
android.view.KeyEvent;
import
com.jph.lc.HeadSetUtil.OnHeadSetListener;
/**
* MEDIA_BUTTON耳机媒体按键广播接收器
* @author JPH
* @Date2015-6-9 下午8:35:40
*/
public
class
MediaButtonReceiver
extends
BroadcastReceiver{
private
Timer timer =
null
;
private
OnHeadSetListener headSetListener =
null
;
private
static
MTask myTimer =
null
;
/**单击次数**/
private
static
int
clickCount;
public
MediaButtonReceiver(){
timer =
new
Timer(
true
);
this
.headSetListener = HeadSetUtil.getInstance().getOnHeadSetListener();
}
@Override
public
void
onReceive(Context context, Intent intent) {
Log.i(ksdinf, onReceive);
String intentAction = intent.getAction() ;
if
(Intent.ACTION_MEDIA_BUTTON.equals(intentAction)){
KeyEvent keyEvent = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
//获得KeyEvent对象
if
(headSetListener !=
null
){
try
{
if
(keyEvent.getAction() == KeyEvent.ACTION_UP){
if
(clickCount==
0
) {
//单击
clickCount++;
myTimer =
new
MTask();
timer.schedule(myTimer,
1000
);
}
else
if
(clickCount==
1
) {
//双击
clickCount++;
}
else
if
(clickCount==
2
) {
//三连击
clickCount=
0
;
myTimer.cancel();
headSetListener.onThreeClick();
}
}
}
catch
(Exception e) {
}
}
}
abortBroadcast();
//终止广播(不让别的程序收到此广播,免受干扰)
}
/**
* 定时器,用于延迟1秒,判断是否会发生双击和三连击
*/
class
MTask
extends
TimerTask{
@Override
public
void
run() {
try
{
if
(clickCount==
1
) {
mhHandler.sendEmptyMessage(
1
);
}
else
if
(clickCount==
2
) {
mhHandler.sendEmptyMessage(
2
);
}
clickCount=
0
;
}
catch
(Exception e) {
// TODO: handle exception
}
}
};
/**
* 此handle的目的主要是为了将接口在主线程中触发
* ,为了安全起见把接口放到主线程触发
*/
Handler mhHandler =
new
Handler(){
@Override
public
void
handleMessage(Message msg) {
super
.handleMessage(msg);
if
(msg.what==
1
){
//单击
headSetListener.onClick();
}
else
if
(msg.what==
2
) {
//双击
headSetListener.onDoubleClick();
}
else
if
(msg.what==
3
) {
//三连击
headSetListener.onThreeClick();
}
}
};
}
|
该类中有个名为Mtask的内部类,该内部类是一个定时任务,该任务会在指定的时间里分析是否会发生双击和三连击。
另外,该类中还有一个myHandler对象,该对象是为了将回调监听发生在UI线程中,以方便UI的更新。
3.监听器的使用类MainActivity:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
package
com.jph.lc;
import
android.app.Activity;
import
android.os.Bundle;
import
android.util.Log;
import
android.widget.TextView;
import
com.jph.lc.HeadSetUtil.OnHeadSetListener;
/**
* 耳机线控实例,蓝牙耳机按钮监听(仿酷狗线控效果)
* @author JPH
* @Date2015-6-10 上午9:49:02
*/
public
class
MainActivity
extends
Activity {
TextView txt =
null
;
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txt = (TextView) findViewById(R.id.text);
HeadSetUtil.getInstance().setOnHeadSetListener(headSetListener);
HeadSetUtil.getInstance().open(
this
);
}
@Override
protected
void
onDestroy() {
super
.onDestroy();
HeadSetUtil.getInstance().close(
this
);
}
OnHeadSetListener headSetListener =
new
OnHeadSetListener() {
@Override
public
void
onDoubleClick() {
txt.setText(双击);
Log.i(ksdinf, 双击);
}
@Override
public
void
onClick() {
txt.setText(单击);
Log.i(ksdinf, 单击);
}
@Override
public
void
onThreeClick() {
txt.setText(三连击);
Log.i(ksdinf, 三连击);
}
};
}
|
该类中举要介绍了媒体按键监听的使用。