Note that there are some explanatory texts on larger screens.

plurals
  1. POHandle bluetooth headset clicks (ACTION_VOICE_COMMAND and ACTION_WEB_SEARCH) on Android
    primarykey
    data
    text
    <p>I’m developing an <code>Android</code> application and I want it to interact with <code>headset</code> button clicks. I’m testing it in a <strong>Nexus 5 with Android KitKat 4.4</strong>.</p> <p>I tried first with a simple headset (not wireless). The button event received was <code>KEYCODE_HEADSETHOOK</code> (79). I created a <code>MEDIA_BUTTON</code> <code>receiver</code> to handle its clicks:</p> <pre><code>&lt;receiver android:name="com.example.mytest.SearchActivity$MediaButtonIntentReceiver"&gt; &lt;intent-filter&gt; &lt;intent-filter android:priority="1000000000"&gt; &lt;action android:name="android.intent.action.MEDIA_BUTTON" /&gt; &lt;/intent-filter&gt; &lt;/intent-filter&gt; &lt;/receiver&gt; </code></pre> <p>This is the activity holding the receiver:</p> <pre><code>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(); } } } </code></pre> <p>This code works with my wired headset <strong>only if the user performs a short click</strong>. Performing a long click opens <code>Google Voice Search</code>. I’d like to capture long clicks too, but I don’t mind if it’s not possible.</p> <p>After that I tested it with a <code>bluetooth</code> 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 "<code>activity</code>" is opened:</p> <p><img src="https://i.stack.imgur.com/FgeNF.png" alt="enter image description here"></p> <p>I’d like to capture this click event too if my <code>Activity</code> is opened. How can I do it? I tried adding the following filters to my receiver, but it’s not working either:</p> <pre><code>&lt;action android:name="android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT" /&gt; &lt;action android:name="android.intent.action.VOICE_COMMAND" /&gt; &lt;action android:name="android.intent.action.CALL_BUTTON" /&gt; </code></pre> <p>I also tried overriding <code>onKeyDown</code> in my Activity, but it’s not triggered.</p> <p>Anybody knows how can I intercept those events?</p> <p>This is my bluetooth headset:</p> <p><img src="https://i.stack.imgur.com/zPDvy.jpg" alt="enter image description here"></p> <hr> <p>** EDIT **</p> <p>Following Toaster’s advice, I checked the whole log looking for the events my headset triggers.</p> <p><strong>Wired headset long click</strong></p> <p>This is the log when I long click in my wired headset (it opens <code>Google Voice Search</code>):</p> <pre><code>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 {act=android.speech.action.WEB_SEARCH flg=0x10800000 cmp=com.google.android.googlequicksearchbox/.SearchActivity} from pid 740 12-10 09:24:36.754: I/ActivityManager(740): START u0 {act=android.speech.action.WEB_SEARCH flg=0x10000000 cmp=com.google.android.googlequicksearchbox/com.google.android.launcher.GEL} 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-&gt;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-&gt;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 </code></pre> <p>It seems it triggers an <code>ACTION_WEB_SEARCH</code> event, so I tried to add it to the filter. I tried it two ways:</p> <ol> <li><p>Declaring the filter in the manifest:</p> <pre><code>&lt;action android:name="android.intent.action.WEB_SEARCH" /&gt; </code></pre></li> <li><p>Declaring the filter programmatically:</p> <pre><code>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"); } }; </code></pre></li> </ol> <p>None of this options work. As I said, this scenario isn’t of much importance, I can deal with it.</p> <hr> <p><strong>Wireless headset simple click</strong></p> <p>The Wireless headset simple click is the one opening the Voice Dialer and <strong>it’s the event I really need to capture</strong>. This is the log output:</p> <pre><code>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 {act=android.intent.action.VOICE_COMMAND flg=0x10000000 cmp=com.google.android.googlequicksearchbox/com.google.android.voicesearch.handsfree.HandsFreeIntentActivity} 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 {act=android.intent.action.VOICE_COMMAND flg=0x10000000 cmp=com.google.android.googlequicksearchbox/com.google.android.voicesearch.handsfree.HandsFreeActivity} 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-&gt;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{com.google.android.tts/com.google.android.tts.service.GoogleTTSService} 12-10 10:41:22.454: I/TextToSpeech(10153): Set up connection to ComponentInfo{com.google.android.tts/com.google.android.tts.service.GoogleTTSService} 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 </code></pre> <p>This time it seems it’s sending an <code>ACTION_VOICE_COMMAND</code>, so I tried to add it to the filter. I tried it two ways:</p> <ol> <li><p>Declaring the filter in the manifest:</p> <pre><code>&lt;action android:name="android.intent.action.VOICE_COMMAND" /&gt; </code></pre></li> <li><p>Declaring the filter programmatically:</p> <pre><code>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"); } }; </code></pre></li> </ol> <p>Again, I’m not receiving these events, I don’t know why.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload