您的位置:首页 > 移动开发 > Android开发

android之BroadcastReceiver应用实列(耳机按键切换下一首音乐)

2015-12-06 11:31 996 查看
当你用耳机听音乐的时候,想通过耳机上的按钮来快速切换下一首、上一首音乐是不是很方便呢!如果,你的手机有这样一个功能当然是不错的!下面来看看我是如何实现的!

对于这个功能的开发,首先要知道两点:(1)耳机按键事件如何获取(短按和长按事件);(2)如果切换上一首音乐、切换下一首音乐。所以我们先来解决这两个问题:

(1)耳机按键事件如何获取。

首先来看看耳机按钮的事件是否有传递到上层framwork。查上耳机、连接USB,然后通过log查看工具,我们通过打印的LOG信息可以很快知道,其事件是会上传上来的。

01-01 01:07:44.524: D/WindowManager(514): interceptKeyTi keyCode=85 down=false repeatCount=0 keyguardOn=false mHomePressed=false canceled=false

01-01 01:07:47.644: D/WindowManager(514): interceptKeyTi keyCode=86 down=true repeatCount=0 keyguardOn=false mHomePressed=false canceled=false

通过上面的LOG信息,你可以知道长按耳机上的按钮,其 keyCode=86;短按耳机上的按钮,其 keyCode=85;

PhoneWindowManager.java里面的这方法interceptKeyBeforeQueueing就是按键时间的接口函数!

(2)如果切换上一首音乐、切换下一首音乐。

我们知道,音乐的播放其实是运行一个service的!在Music里面,我们可以很快知道这个service其实就是:MediaPlaybackService。通过这个service 的onStartCommand方法可以知道,在onStartCommand里面其实是根据intent带回来的不同参数来控制音乐播放的,比如暂停、播放、下一首、上一首等。

上面两个问题已经解决了!接下来的问题就是如果把这两个问题关联起来!也就是耳机事件如何传递到这个music的app里面来!说的具体一点,就是耳机按键时间如果传递到这个播放音乐的service里面来!!我们知道service的直接父类其实是ContextWrapper,想对于activity,并没有实现Window.Callback, KeyEvent.Callback,这两个接口,所以更本上是无法接受这个耳机按键事件的!

那怎么解决这个问题呢!很快想到了BroadcastReceiver,用BroadcastReceiver来接受按键事件! 在music这个app里面定义一个BroadcastReceiver,在PhoneWindowManager里面把检测到的事件发送到我们再music里面定义的BroadcastReceiver。这样问题就解决了!

以上就是解决这个问题的基本思路!不过,一些细微的问题需要注意,下面一个个来说:

(1)在music定义的BroadcastReceiver由于是监听这个app外面的广播事件,所以只是在代码里面动态注册是不可取的!必须AndroidManifest.xml这样定义:

android:exported=”true” >

这里的android:exported=”true” 是必须的。

(2)在PhoneWindowManager中,检测到耳机按键事件,如下方式发送广播:

[code]Intent intent = new Intent();
intent.putExtra("music_change", music_change);
intent.setClassName("com.android.music", "com.android.music.HEADSET_key_Receiver");//
intent.setAction("com.android.music.HEADSET_key_input");


这里最好setClassName,这样一来效率高。

(3)在PhoneWindowManager中,检测到耳机按键的事件是down事件。

(4)在PhoneWindowManager中,检测到耳机按键事件时候最好能检测一下手机是否在播放音乐:

final AudioManager am = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);

if (am == null) {

Log.w(TAG, “isMusicActive: couldn’t get AudioManager reference”);

return false;

}

return am.isMusicActive();

}

还需要检测一下在在通话过程中incall

ITelephony telephonyService = getTelephonyService();

if (telephonyService != null) {// 这里检测一下是否当前正在通常 incall

try {

if (!telephonyService.isIdle()) {

// Suppress PLAY/PAUSE toggle when phone is ringing or in-call

// to avoid music playback.

return;

}

} catch (RemoteException ex) {

Log.w(TAG, “ITelephony threw RemoteException”, ex);

}

}

(5)在music定义的BroadcastReceiver中在start播放音乐的service的时候,最好能够检测一下这个service是否处于运行当中:

private boolean isMusicServiceRunning(Context context) {

boolean isServiceRuning = false;

ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);

final int maxServciesNum = 100;

List list = am.getRunningServices(maxServciesNum);

for (RunningServiceInfo info : list) {

if (MediaPlaybackService.class.getName().equals(info.service.getClassName())) {

isServiceRuning = true;

break;

}

}

// MusicLogUtils.d(“yuyongjun”, “isMusicServiceRunning ” + isServiceRuning + “, Runing service num is ” + list.size());

return isServiceRuning;

}

(6)尽管播放音乐的service是一个运行的service,但是并不代表现在正在播放音乐(比如 暂停播放等)。所以,是否正在播放音乐其实需要在这个service(MediaPlaybackService)中才能确认。所以,我们start这个service的时候需要带一个标识:

Intent i = new Intent(context, MediaPlaybackService.class);

i.setAction(MediaPlaybackService.SERVICECMD);

i.putExtra(MediaPlaybackService.CMDNAME, command);

i.putExtra(MediaPlaybackService.DELTATIME, deltaTime);

i.putExtra(HEADSET_key_input, “true”);

context.startService(i);

上面的 i.putExtra(HEADSET_key_input, “true”);用于标示是耳机按钮事件触发。所以在MediaPlaybackService的onStartCommand有如下代码判断。

// yuyongjun _start 2014-4-16 FeatureOption.BASICOM_HEADSET_KEY_CONTROL_MUSIC_CHANGE_SONG

String HEADSET_key_input = intent.getStringExtra(HEADSET_key_Receiver.HEADSET_key_input);

if(HEADSET_key_input != null && HEADSET_key_input.equals(“true”))

{

if(false == mIsSupposedToBePlaying)

{

return START_STICKY;

}

MusicLogUtils.d(“yuyongjun”, “onStartCommand: HEADSET_key_input”);

}// yuyongjun _end 2014-4-16
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: