- Android — Bluetooth Buttons. Media Button Intents or Bluetooth Headset API?
- 1 Answer 1
- Related
- Hot Network Questions
- Subscribe to RSS
- Handle bluetooth headset clicks (ACTION_VOICE_COMMAND and ACTION_WEB_SEARCH) on Android
- How to Listen for Bluetooth Headset Buttons in an Android App?
- AndroidManifest.xml
- MainActivity.java
- MediaButtonIntentReceiver.java
- Registering a headset button click with BroadcastReceiver in Android
Android — Bluetooth Buttons. Media Button Intents or Bluetooth Headset API?
edit It think all this stuff is now well out of date, there have been many changes to this as android has developed. I’ll post an answer when I have worked it out (if noone else has). I really just want a background app to get first crack at bluetooth messages. end of edit I have an android app that needs input from the user — I want to use bluetooth headset buttons (actually bluetooth watch/band buttons — but technically the same!). I have been looking at media button examples, there are many here and elsewhere which all basically say:- 1) Put receiver/intent in manifest 2) Register receiver in main activity 3) Do processing in the receiver class This isn’t working for me (even cutting and pasting sample code), with no errors, but no events being triggered. However I also found this: http://developer.android.com/reference/android/bluetooth/BluetoothHeadset.html Which is a dedicated bluetooth headset api. has it superceded the media button approach? or is it just higher in the food chain? Should this be used instead of the Media Button Event stuff — or are they just different perspectives? If the media button stuff is the way, I can post my non-working code, but don’t want to waste anyones time if its an out of date approach! Thanks!
1 Answer 1
For examples of using bluetooth buttons — this is an excellent example.
It detects a hit on the headset ‘play’ button then pops a dialog asking which app to direct the ‘play’ to — it plays the choices via the headset so one can be selected without viewing the screen.
Related
Hot Network Questions
Subscribe to RSS
To subscribe to this RSS feed, copy and paste this URL into your RSS reader.
Site design / logo © 2023 Stack Exchange Inc; user contributions licensed under CC BY-SA . rev 2023.7.13.43530
By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy.
Handle bluetooth headset clicks (ACTION_VOICE_COMMAND and ACTION_WEB_SEARCH) on Android
I’m developing an Android application and I want it to interact with headset button clicks. I’m testing it in a Nexus 5 with Android KitKat 4.4. I tried first with a simple headset (not wireless). The button event received was KEYCODE_HEADSETHOOK (79). I created a MEDIA_BUTTON receiver to handle its clicks:
public class SearchActivity extends Activity < private AudioManager mAudioManager; private ComponentName mAudioReceiver; @Override protected void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.search); mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE); mAudioReceiver = new ComponentName(getPackageName(), MediaButtonIntentReceiver.class.getName()); >@Override protected void onResume() < super.onResume(); mAudioManager.registerMediaButtonEventReceiver(mAudioReceiver); >@Override protected void onPause() < super.onPause(); mAudioManager.unregisterMediaButtonEventReceiver(mAudioReceiver); >public static class MediaButtonIntentReceiver extends BroadcastReceiver < @Override public void onReceive(Context context, Intent intent) < Log.d("SA", "ON RECEIVE"); . abortBroadcast(); >> >
This code works with my wired headset only if the user performs a short click. Performing a long click opens Google Voice Search . I’d like to capture long clicks too, but I don’t mind if it’s not possible. After that I tested it with a bluetooth headset. Specifically, I’m using Moveteck Bluetooth Headset BH119A (you can see an image at the bottom of this post). This headset only has one button, and if I press it the following » activity » is opened: I’d like to capture this click event too if my Activity is opened. How can I do it? I tried adding the following filters to my receiver, but it’s not working either:
I also tried overriding onKeyDown in my Activity, but it’s not triggered. Anybody knows how can I intercept those events? This is my bluetooth headset: ** EDIT ** Following Toaster’s advice, I checked the whole log looking for the events my headset triggers. Wired headset long click This is the log when I long click in my wired headset (it opens Google Voice Search ):
12-10 09:24:36.644: I/MediaFocusControl(740): voice-based interactions: about to use ACTION_WEB_SEARCH 12-10 09:24:36.644: I/ActivityManager(740): START u0 from pid 740 12-10 09:24:36.754: I/ActivityManager(740): START u0 from pid 10153 12-10 09:24:36.764: I/InputDispatcher(740): Dropping event because there is no focused window or focused application. 12-10 09:24:36.764: I/InputDispatcher(740): Dropping event because there is no focused window or focused application. 12-10 09:24:36.774: I/GEL(1025): handleIntent(Intent < act=android.speech.action.WEB_SEARCH flg=0x10400000 cmp=com.google.android.googlequicksearchbox/com.google.android.launcher.GEL >) 12-10 09:24:36.774: V/SearchControllerCache(10153): creating SearchController 12-10 09:24:36.804: I/AudioRouter(10153): ROUTE_NONE->ROUTE_NO_BLUETOOTH 12-10 09:24:36.804: I/MediaFocusControl(740): AudioFocus requestAudioFocus() from android.media.AudioManager@4267ad58com.google.android.voicesearch.audio.AudioRouterImpl$1@42695f60 12-10 09:24:36.804: I/Velvet.SdchManager(10153): Sdch cache load complete. 12-10 09:24:36.814: W/IInputConnectionWrapper(18407): showStatusIcon on inactive InputConnection 12-10 09:24:36.814: I/Icing.InternalIcingCorporaProvider(10153): Updating corpora: A: NONE, C: DELTA 12-10 09:24:36.854: I/VS.G3EngineManager(10153): create_rm: m=GRAMMAR,l=en-US 12-10 09:24:36.854: W/Search.ConcurrentUtils(10153): Executor queue length is now 9. Perhaps some tasks are too long, or the pool is too small. [GrecoExecutor-1] 12-10 09:24:36.854: I/VS.G3EngineManager(10153): Brought up new g3 instance :/system/usr/srec/en-US/grammar.config for: en-USin: 9 ms 12-10 09:24:36.864: D/audio_hw_primary(189): out_set_parameters: enter: usecase(1: low-latency-playback) kvpairs: routing=4 12-10 09:24:36.864: D/audio_hw_primary(189): select_devices: out_snd_device(4: headphones) in_snd_device(0: ) 12-10 09:24:36.874: D/audio_hw_primary(189): select_devices: out_snd_device(0: ) in_snd_device(18: headset-mic) 12-10 09:24:36.874: D/(189): Failed to fetch the lookup information of the device 00000008 12-10 09:24:36.874: E/ACDB-LOADER(189): Error: ACDB AudProc vol returned = -19 12-10 09:24:38.864: I/LATENCY(10153): 0-4,45-2064, 12-10 09:24:38.874: I/AudioRouter(10153): ROUTE_NO_BLUETOOTH->ROUTE_NONE 12-10 09:24:38.874: I/MediaFocusControl(740): AudioFocus abandonAudioFocus() from android.media.AudioManager@4267ad58com.google.android.voicesearch.audio.AudioRouterImpl$1@42695f60 12-10 09:24:38.874: I/MicrophoneInputStream(10153): mic_close
protected void onResume() < IntentFilter f = new IntentFilter(Intent.ACTION_WEB_SEARCH); registerReceiver(myReceiver, f); >private BroadcastReceiver myReceiver = new BroadcastReceiver() < @Override public void onReceive(Context context, Intent intent) < Log.d("AA", "ON RECEIVE"); >>;
None of this options work. As I said, this scenario isn’t of much importance, I can deal with it.
Wireless headset simple click
The Wireless headset simple click is the one opening the Voice Dialer and it’s the event I really need to capture. This is the log output:
12-10 10:41:22.014: E/bt-rfcomm(21800): PORT_DataInd, p_port:0x7507a7e8, p_data_co_callback is null 12-10 10:41:22.014: D/HeadsetStateMachine(21800): processVrEvent: state=1 mVoiceRecognitionStarted: false mWaitingforVoiceRecognition: false isInCall: false 12-10 10:41:22.014: I/ActivityManager(740): START u0 from pid 21800 12-10 10:41:22.154: V/Avrcp(21800): New genId = 440, clearing = 1 12-10 10:41:22.154: D/HandsFreeIntentActivity(10153): #onStart(Intent < act=android.intent.action.VOICE_COMMAND flg=0x10800000 cmp=com.google.android.googlequicksearchbox/com.google.android.voicesearch.handsfree.HandsFreeIntentActivity >) 12-10 10:41:22.154: D/HandsFreeIntentActivity(10153): Starting activity: Intent < act=android.intent.action.VOICE_COMMAND flg=0x10000000 cmp=com.google.android.googlequicksearchbox/com.google.android.voicesearch.handsfree.HandsFreeActivity >12-10 10:41:22.154: I/ActivityManager(740): START u0 from pid 10153 12-10 10:41:22.204: D/OpenGLRenderer(10153): Enabling debug mode 0 12-10 10:41:22.214: W/IInputConnectionWrapper(18895): showStatusIcon on inactive InputConnection 12-10 10:41:22.244: I/ActivityManager(740): Displayed com.google.android.googlequicksearchbox/com.google.android.voicesearch.handsfree.HandsFreeActivity: +80ms (total +89ms) 12-10 10:41:22.374: I/AudioRouter(10153): ROUTE_NONE->ROUTE_BLUETOOTH_WANTED 12-10 10:41:22.384: I/MediaFocusControl(740): AudioFocus requestAudioFocus() from android.media.AudioManager@4267ad58com.google.android.voicesearch.audio.AudioRouterImpl$1@42695f60 12-10 10:41:22.384: V/Avrcp(21800): New genId = 441, clearing = 1 12-10 10:41:22.384: D/BluetoothManagerService(740): Message: 30 12-10 10:41:22.384: D/BluetoothHeadset(10153): Proxy object connected 12-10 10:41:22.384: I/BluetoothController(10153): BT device connected 12-10 10:41:22.394: I/AudioRouter(10153): BT required, starting SCO 12-10 10:41:22.394: I/BluetoothController(10153): Starting VR 12-10 10:41:22.394: D/BluetoothHeadset(10153): startVoiceRecognition() 12-10 10:41:22.394: D/HeadsetStateMachine(21800): Voice recognition started successfully 12-10 10:41:22.394: D/HeadsetStateMachine(21800): Initiating audio connection for Voice Recognition 12-10 10:41:22.394: W/bt-btm(21800): BTM Remote does not support 3-EDR eSCO 12-10 10:41:22.434: I/TextToSpeech(10153): Sucessfully bound to com.google.android.tts 12-10 10:41:22.454: I/TextToSpeech(10153): Connected to ComponentInfo 12-10 10:41:22.454: I/TextToSpeech(10153): Set up connection to ComponentInfo 12-10 10:41:22.484: D/dalvikvm(21966): GC_CONCURRENT freed 346K, 3% free 16647K/17064K, paused 2ms+3ms, total 13ms 12-10 10:41:22.764: D/audio_hw_primary(189): out_set_parameters: enter: usecase(1: low-latency-playback) kvpairs: routing=32 12-10 10:41:22.774: D/audio_hw_primary(189): select_devices: out_snd_device(11: bt-sco-headset) in_snd_device(0: ) 12-10 10:41:24.874: I/EventLogService(1148): Aggregate from 1386666683008 (log), 1386666683008 (data) 12-10 10:41:24.994: I/ServiceDumpSys(1148): dumping service [account] 12-10 10:41:25.994: D/dalvikvm(10153): GC_CONCURRENT freed 1582K, 15% free 23868K/27920K, paused 5ms+7ms, total 60ms 12-10 10:41:26.014: I/VS.G3EngineManager(10153): create_rm: m=GRAMMAR,l=en-US 12-10 10:41:26.024: I/VS.G3EngineManager(10153): Brought up new g3 instance :/system/usr/srec/en-US/grammar.config for: en-USin: 4 ms 12-10 10:41:26.024: D/audio_hw_primary(189): out_set_parameters: enter: usecase(1: low-latency-playback) kvpairs: routing=32 12-10 10:41:26.034: D/audio_hw_primary(189): select_devices: out_snd_device(0: ) in_snd_device(25: bt-sco-mic) 12-10 10:41:26.034: D/(189): Failed to fetch the lookup information of the device 00000015 12-10 10:41:26.034: E/ACDB-LOADER(189): Error: ACDB AudProc vol returned = -19
This time it seems it’s sending an ACTION_VOICE_COMMAND , so I tried to add it to the filter. I tried it two ways:
- Declaring the filter in the manifest:
protected void onResume() < IntentFilter f = new IntentFilter(Intent.ACTION_VOICE_COMMAND); registerReceiver(myReceiver, f); >private BroadcastReceiver myReceiver = new BroadcastReceiver() < @Override public void onReceive(Context context, Intent intent) < Log.d("AA", "ON RECEIVE"); >>;
Again, I’m not receiving these events, I don’t know why.
How to Listen for Bluetooth Headset Buttons in an Android App?
What is the proper way to handle Bluetooth media buttons in an Android app? At this point, all I want is an event to fire when I press the pause/play button on my Bluetooth headset. Somehow, I had a working solution yesterday, and today it just doesn’t work. Without reinstalling the app, or any update happening on my phone, the onReceive method of my subclass of BroadcastReceiver is never entered. I’m targeting Android 9.0, since this is just for myself. I used the information in these two questions for the solution: How to capture key events from bluetooth headset with android BroadcastReceiver for ACTION_MEDIA_BUTTON not working This is a bare minimum version of what was working yesterday, which currently does not work:
AndroidManifest.xml
MainActivity.java
package com.example.myapplication; import androidx.appcompat.app.AppCompatActivity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.media.AudioManager; import android.os.Bundle; public class MainActivity extends AppCompatActivity < MediaButtonIntentReceiver mMediaButtonReceiver = new MediaButtonIntentReceiver(); IntentFilter mediaFilter = new IntentFilter(Intent.ACTION_MEDIA_BUTTON); AudioManager mAudioManager = null; ComponentName mReceiverComponent = null; @Override protected void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); mReceiverComponent = new ComponentName(this, MediaButtonIntentReceiver.class); mediaFilter.setPriority(2139999999); registerReceiver(mMediaButtonReceiver, mediaFilter); >>
MediaButtonIntentReceiver.java
package com.example.myapplication; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.util.Log; public class MediaButtonIntentReceiver extends BroadcastReceiver < public MediaButtonIntentReceiver() < super(); Log.i("mylog", "init"); >@Override public void onReceive(Context context, Intent intent) < Log.i("mylog", "receive"); abortBroadcast(); >>
Registering a headset button click with BroadcastReceiver in Android
I have a headset with single button and want to do a simple Toast when the button is pressed. Right now I have the following code:
public class MediaButtonIntentReceiver extends BroadcastReceiver < public MediaButtonIntentReceiver() < super(); >@Override public void onReceive(Context context, Intent intent) < String intentAction = intent.getAction(); if (!Intent.ACTION_MEDIA_BUTTON.equals(intentAction)) < return; >KeyEvent event = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT); if (event == null) < return; >int action = event.getAction(); if (action == KeyEvent.ACTION_DOWN) < // do something Toast.makeText(context, "BUTTON PRESSED!", Toast.LENGTH_SHORT).show(); >abortBroadcast(); > >
public class mainActivity extends Activity < /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.main); IntentFilter filter = new IntentFilter(Intent.ACTION_MEDIA_BUTTON); MediaButtonIntentReceiver r = new MediaButtonIntentReceiver(); registerReceiver(r, filter); >>
Nothing happens though when I push the button though. I’m pretty sure something is wrong with my permissions/xml in the manifest. Here’s the receiver XML so far:
I notice in LogCat that when I press the button I get an error from «BluetoothIntentReceiver» saying «onReceive() Action : android.intent.action.MEDIA_BUTTON»