線控耳機監聽

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

?

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

?

該類中有個名為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, 三連擊);
????????}
????};
}

?

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

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/387955.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/387955.shtml
英文地址,請注明出處:http://en.pswp.cn/news/387955.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

當編程語言掌握在企業手中,是生機還是危機?

2019年4月,Java的收費時代來臨了! Java是由Sun微系統公司在1995年推出的編程語言,2010年Oracle收購了Sun之后,Java的所有者也就自然變成了Oracle。2019年,Oracle宣布將停止Java 8更新的免費支持,未來Java的…

sql如何處理null值_如何正確處理SQL中的NULL值

sql如何處理null值前言 (Preface) A friend who has recently started learning SQL asked me about NULL values and how to deal with them. If you are new to SQL, this guide should give you insights into a topic that can be confusing to beginners.最近開始學習SQL的…

名言警句分享

“當你想做一件事,卻無能為力的時候,是最痛苦的。”基拉大和轉載于:https://www.cnblogs.com/yuxijun/p/9986489.html

文字創作類App分享-簡書

今天我用Mockplus做了一套簡書App的原型,這是一款文字創作類的App,用戶通過寫文、點贊等互動行為,提高自己在社區的影響力,打造個人品牌。我運用了Mockplus基礎組件、交互組件、移動組件等多個組件庫,簡單拖拽&#xf…

數據可視化 信息可視化_動機可視化

數據可視化 信息可視化John Snow’s map of Cholera cases near London’s Broad Street.約翰斯諾(John Snow)在倫敦寬街附近的霍亂病例地圖。 John Snow, “the father of epidemiology,” is famous for his cholera maps. These maps represent so many of our aspirations …

android 接聽和掛斷實現方式

轉載▼標簽: android 接聽 掛斷 it 分類: android應用技巧 參考:android 來電接聽和掛斷 支持目前所有版本 注意:android2.3版本及以上不支持下面的自動接聽方法。 (會拋異常:java.lang.Securi…

Eclipse External Tool Configration Notepad++

Location: C:\Program Files\Notepad\notepad.exe Arguments:  ${resource_loc} 轉載于:https://www.cnblogs.com/rgqancy/p/9987610.html

利用延遲關聯或者子查詢優化超多分頁場景

2019獨角獸企業重金招聘Python工程師標準>>> MySQL并不是跳過offset行,而是取offsetN行,然后返回放棄前offset行,返回N行,那當offset 特別大的時候,效率就非常的低下,要么控制返回的總頁數&…

客戶流失_了解客戶流失

客戶流失Big Data Analytics within a real-life example of digital music service數字音樂服務真實示例中的大數據分析 Customer churn is a key predictor of the long term success or failure of a business. It is the rate at which customers are leaving your busine…

Java 動態加載class 并反射調用方法

反射方法: public static void main(String[] args) throws Exception { File filenew File("D:/classtest");//類路徑(包文件上一層) URL urlfile.toURI().toURL(); ClassLoader loadernew URLClassLoader(new URL[]{url});//創…

Nginx:Nginx limit_req limit_conn限速

簡介 Nginx是一個異步框架的Web服務器,也可以用作反向代理,負載均衡器和HTTP緩存,最常用的便是Web服務器。nginx對于預防一些攻擊也是很有效的,例如CC攻擊,爬蟲,本文將介紹限制這些攻擊的方法,可…

快速數據庫框架_快速學習新的數據科學概念的框架

快速數據庫框架重點 (Top highlight)數據科學 (Data Science) Success in data science and software engineering depends on our ability to continuously learn new models and concepts.數據科學和軟件工程的成功取決于我們不斷學習新模型和概念的能力。 Both domains are…

Linux實戰教學筆記12:linux三劍客之sed命令精講

第十二節 linux三劍客之sed命令精講 標簽(空格分隔): Linux實戰教學筆記-陳思齊 ---更多資料點我查看 1,前言 我們都知道,在Linux中一切皆文件,比如配置文件,日志文件,啟動文件等等。…

activiti 為什么需要采用樂觀鎖?

樂觀鎖 為什么需要采用樂觀鎖? 由于activiti一個周期的transaction時間可能比較長,且同一流程實例中存在任務并發執行等場景。設計者將update、insert、delete事務性的操作推遲至command結束時完成,這樣盡量降低鎖沖突的概率,由…

Python實現三級菜單(字典和列表的使用)

menu { 北京: { 海淀: { 五道口: { soho: {}, 網易: {}, google: {} }, 中關村: { 愛奇藝: {}, 汽車之家: {}, 優酷: {} …

停止使用p = 0.05

How many of you use p0.05 as an absolute cut off? p ≥ 0.05 means not significant. No evidence. Nada. And then p < 0.05 great it’s significant. This is a crude way of using p-values, and hopefully I will convince you of this.你們中有多少人使用p 0.05作…

centos7系統根目錄擴容

比如 點擊了后 點擊創建虛擬磁盤 選擇一個 20G 然后啟動虛擬機使用fdisk查看所有的磁盤 看是否新增了一個20G的硬盤 [rootlocalhost ~]# fdisk -l磁盤 /dev/sda&#xff1a;8589 MB, 8589934592 字節&#xff0c;16777216 個扇區 Units 扇區 of 1 * 512 512 bytes 扇區大小(…

instrumentation模擬很多activity的操作

android.app.Instrumentation好像原來是用來做測試的, 可以用來模擬很多activity的操作 主要代碼如下 如果在文本框中輸入24,或者25 點擊按鈕就能模擬音量加減鍵 鍵值可以查看android.view.KeyEvent [java] view plaincopy package com.qefee.testinstrumentation; import…

成像數據更好的展示_為什么更多的數據并不總是更好

成像數據更好的展示Over the past few years, there has been a growing consensus that the more data one has, the better the eventual analysis will be.在過去的幾年中&#xff0c;越來越多的共識是&#xff0c;數據越多&#xff0c;最終的分析就越好。 However, just a…

支付寶架構

支付寶系統架構圖如下&#xff1a; 支付寶架構文檔有兩個搞支付平臺設計的人必須仔細揣摩的要點。 一個是賬務處理。在記賬方面&#xff0c;涉及到內外兩個子系統&#xff0c;外部子系統是單邊賬&#xff0c;滿足線上性能需求&#xff1b;內部子系統走復式記賬&#xff0c;滿足…