Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android耳機線控詳解,藍牙耳機按鈕監聽(仿酷狗線控效果)

Android耳機線控詳解,藍牙耳機按鈕監聽(仿酷狗線控效果)

編輯:關於Android編程

 

當耳機的媒體按鍵被單擊後,Android系統會發出一個廣播,該廣播的攜帶者一個Action名為MEDIA_BUTTON的Intent。監聽該廣播便可以獲取手機的耳機媒體按鍵的單擊事件。

在Android中有個AudioManager類,該類會維護MEDIA_BUTTON廣播的分發,所以要實現耳機按鍵監聽需要向AudioManager注冊一個用於接收耳機按鍵單擊事件的接收器:

 

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媒體按鍵的接收器,並且該接收器是媒體按鍵的唯一接收器,所以要在不使用按鍵監聽的時候取消該注冊:

 

AudioManager audioManager = (AudioManager)context    .getSystemService(Context.AUDIO_SERVICE);
ComponentName name = newComponentName(context.getPackageName(),    MediaButtonReceiver.class.getName());
audioManager.unregisterMediaButtonEventReceiver(name);

 

當耳機媒體鍵發生單擊事件的時候Android系統會發出兩次廣播,第一次是按鍵按下去的時候,第二次是松開按鍵的時候,為了能夠准確的獲知用戶單擊了幾次媒體鍵,我們只需要在按鍵松開的時候處理單擊事件即可:

 

KeyEvent keyEvent = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT); //獲得KeyEvent對象
if(keyEvent.getAction()== KeyEvent.ACTION_UP){
//在這裡處理單擊事件
}

 

下面就分別講解一下為了實現線控效果所用到的幾個類:

1. 耳機線控管理工具類HeadSetUtil:

 

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();
	}
}
該類主要負責媒體按鍵接收器的注冊和自定義媒體按鍵回調監聽器的設置。該類中包含一個OnHeadSetListener接口,該接口中的onClick(),onDoubleClick(),onThreeClick()三個方法分別會在單擊事件,雙擊事件,以及三連擊事件發生時被回調。需要指出的是,單擊和雙擊事件會有1秒的延遲,這是因為在這1秒內需要監聽是否還有單擊發生的原因,當然這1s也不是絕對的,你也可以根據實際的業務需要自定義事件。在下面講解的這個類中將會解開酷狗線控的原理。

 

2.耳機媒體按鍵廣播接收器MediaButtonReceiver:

 

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();
			}
		}
	};
		
}
該類主要負責接收系統發出的媒體案件的單擊事件,並對單擊事件做相應的處理以達到單擊,雙擊,三連擊的效果。需要指出的是該類在實例化的時候會獲取OnHeadSetListener監聽器,所以要在調用HeadSetUtil類的open方法用之前設置OnHeadSetListener,否則將不會對媒體按鍵事件做處理。

 

該類中有個名為Mtask的內部類,該內部類是一個定時任務,該任務會在指定的時間裡分析是否會發生雙擊和三連擊。

另外,該類中還有一個myHandler對象,該對象是為了將回調監聽發生在UI線程中,以方便UI的更新。

3.監聽器的使用類MainActivity:

 

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, 三連擊);
		}
	};
}

 

該類中舉要介紹了媒體按鍵監聽的使用。

 

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