Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android之BroadcastReceiver應用實列(耳機按鍵切換下一首音樂)

android之BroadcastReceiver應用實列(耳機按鍵切換下一首音樂)

編輯:關於Android編程

當你用耳機聽音樂的時候,想通過耳機上的按鈕來快速切換下一首、上一首音樂是不是很方便呢!如果,你的手機有這樣一個功能當然是不錯的!下面來看看我是如何實現的!

對於這個功能的開發,首先要知道兩點:(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中,檢測到耳機按鍵事件,如下方式發送廣播:

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中,檢測到耳機按鍵事件時候最好能檢測一下手機是否在播放音樂:

boolean isMusicActive() {
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

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved