編輯:關於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" 是必須的。
(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
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
項目中,我需要PopupWindow的時候特別多,這個東西也特別的好使,所以我今天給大家寫一款PopupWindow 仿微信彈出效果,這樣大家直接拿到項目裡就可以用了!首
使用ViewPager作為一個頁面進行切換,裡面可以存放很多View,但有時在操作View時不小心滑動一下就有可能跳到下一頁,這並不是我們想要的,這裡就需要重寫ViewP
Android應用開發-小巫CSDN博客客戶端之獲取評論列表 上一篇博客介紹了博文詳細內容的業務邏輯實現,本篇博客介紹小巫CSDN博客客戶端的最後一項功能,獲取評論列表,
關於Android Studio的好處我就不用說了,下面兩點就足矣讓你轉投Android Studio了: 1、Andro