I know how to detect whether a headset is plugged in but some headsets (e.g Samsung EHS60ANNBE) come with the PAUSE/PLAY (a.k.a KeyEvent.KEYCODE_HEADSETHOOK) button only, without the PREV/NEXT...
I would like to be able to detect whether the headset currently plugged into the Android device has PREV/NEXT (a.k.a KeyEvent.KEYCODE_MEDIA_PREVIOUS/KeyEvent.KEYCODE_MEDIA_NEXT) or not.
Is this possible?
Are you using a BroadcastReceiver? I'm guessing you are.
from Android Dev:
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) {
//receive the key press event
KeyEvent event = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
//check the keypress
if (KeyEvent.**** == event.getKeyCode()) {
// Handle key press.
}
}
}
}
** a link with various keypress codes
Related
I want to detect the Chromebook lock, Unlock event. I am using Foreground service and register Broadcast to detect Intent.ACTION_SCREEN_ON, Intent.ACTION_SCREEN_OFF, Intent.ACTION_USER_PRESENT. Only getting Intent.ACTION_SCREEN_ON, Intent.ACTION_SCREEN_OFF broadcast but not getting Intent.ACTION_USER_PRESENT broadcast on Chromebook.
override fun onCreate() {
super.onCreate()
startForeground()
intentFilter = IntentFilter(Intent.ACTION_SCREEN_ON)
intentFilter = IntentFilter(Intent.ACTION_USER_PRESENT)
intentFilter.addAction(Intent.ACTION_SCREEN_OFF)
//other code
}
class XYZBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent) {
val action = intent.action
if (Intent.ACTION_USER_PRESENT == action) {
}
else if (Intent.ACTION_SCREEN_OFF == action) {
}
else if(Intent.ACTION_SCREEN_ON == action){
}
}
I am trying lots of methods from Android detect phone lock event, A way to get unlock event in android?, Android - detect phone unlock event, not screen on but nothing works for Chromebook.
Is there any other way to detect lock, Unlock events on Android Chromebook?
The information you're referring to may be outdated ...
Since API level 26 you won't receive this implicit broadcast on regular Android either:
https://developer.android.com/guide/components/broadcast-exceptions
i am working on a VoIP-Android-App. I would like to accept and decline Calls via a connnected Bluetooth Headset in an Activity.
What I have tried so far:
Using a Media Session to receive Media Button clicks.
Problem: If we start BluetoothSCO we do not receive any Media Button clicks. If we do not start BluetoothSCO we do receive Media Button clicks but we cannot differentiate long and short button clicks because downtime is always 0, the keycode is always KEYCODE_MEDIA_PLAY and the ACTION_DOWN is immediately followed by ACTION_UP. Those problems only occur if we are connected via Bluetooth. If we are connnected over a cable Headset we do get the appropriate keycodes (KEYCODE_HEADSETHOOK) and the downtime is not 0.
Using a BroadcastReceiver to listen for Bluetooth SCO connection changes.
private val scoReceiver = object : BroadcastReceiver() {
fun onReceive(context: Context, intent: Intent) {
val state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1)
val previousState = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_PREVIOUS_STATE, -1)
if (state == AudioManager.SCO_AUDIO_STATE_DISCONNECTED && previousState == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
Log.e(TAG, "SCO Disconnected")
hangupCall()
}
}
}
protected fun onStart() {
super.onStart()
val intentFilter = IntentFilter()
intentFilter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED)
registerReceiver(scoReceiver, intentFilter)
}
With this approach i can detect when the user wants to hang up the call, for example a long press on the bluetooth headset because this triggers the SCO to disconnect.
Problem: We can not detect if the user wants to accept an incoming call.
Using dispatchKeyEvent, onKeyDown and onKeyUp.
Problem: They never get called at all.
Does anyone has any advice or a best practice how to correctly handle bluetooth headsets? Any help is very appreciated. Thanks in advance!
During normal and virtual voice call (including ringing) all events of Bluetooth headset unit buttons are processed by Bluetooth Headset Service internaly and not broadcasted as button events. Bluetooth Headset Service redirects these events into Telecom framework (answer/hangupCall).
These events are handled internally in HeadsetStateMachine (under packages/apps/Bluetooth).
These events are forwarded to IBluetoothHeadsetPhone interface. The single application to which all the events are forwarded is defined at run-time by following binding code in HeadsetStateMachine.java. This is to allow phone manufacturers to forward them to custom phone application instead of default one in cases where default one is not used.
Intent intent = new Intent(IBluetoothHeadsetPhone.class.getName());
intent.setComponent(intent.resolveSystemService(context.getPackageManager(), 0));
if (intent.getComponent() == null || !context.bindService(intent, mConnection, 0)) {
Log.e(TAG, "Could not bind to Bluetooth Headset Phone Service");
}
To make the events get forwarded to your application instead of default phone application you would have to modify aosp code.
You would need to intercept the events at one of HeadsetStateMachine , BluetoothHeadsetPhone proxy or the phone application.
Unfortunately what you are looking for is currently not possible without modifying aosp code. Some headsets like Plantronics have custom BT events which are forwarded to all applications - some of the existing VoIP applications support these custom intents to support at-least answering calls for some of the headsets.
You should use android Telecom API and implement android.telecom.ConnectionService and android.telecom.Connection where you should override onAnswer() callback which will be called when you try to answer a call via bluetooth headset.
For more details read docs - https://developer.android.com/guide/topics/connectivity/telecom/selfManaged
I'm trying to implement an app that (mis-) uses a Bluetooth camera shutter release gadget for a completely different purpose. Here's the gadget in question:
http://www.amazon.co.uk/iPazzPort-Bluetooth-Shutter-Android-Smartphones/dp/B00MRTFB4M
As far as I can determine this uses Bluetooth v3 and is an HID device. It apparently fires the camera app shutter by simulating "volume up" (or maybe "volume down"?). Anyway, it does seem to work quite well, although sometimes you have to press the button twice - I think that maybe the first press reestablishes Bluetooth connection and the second, and subsequent, presses then just work.
I've tested it with two different devices running Android 2.3. I do want to be backwards-compatible to that version of Android.
What I want to do is to monitor all input from this device somehow, so my app can detect when the button has been pressed and then do what it wants to use the device for. (It's a kind of panic alarm system so you can press the button to indicate you need help.)
I don't want to get involved in trying to communicate with the device via Bluetooth. Android is already doing that, and it's working, and what I've read about Bluetooth and the HID protocol makes me want to avoid it if at all possible.)
I've tried overriding onKeyDown() and onKeyUp() and dispatchKeyEvent(). Sometimes they get called, sometimes they don't. And when they get called I'm seeing unexpected keyCodes like 66 (Enter) and 8 ("1").
What I'm asking is, is there some way to monitor all input from this Bluetooth HID device, without having to get involved in Bluetooth HID protocol support?
I never found a real answer to my question as such, but fortunately I found a work-around.
This particular Bluetooth gadget always connects to the paired device, sends some text, and then disconnects. So what I'm doing is creating a BroadcastReceiver to get Bluetooth connection (and disconnect) events, and using that to activate the alarm.
// Class used to receive Bluetooth connection and disconnect events. This checks the action is as
// expected (probably unnecessary) and that a request type has been selected, and sends the
// activation message to OutBack Server if so. (Monitoring the disconnect events is probably
// unnecessary, but is done just in case that saves a situation where a connection has been
// missed, or something.)
public class BluetoothReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context androidContext, Intent androidIntent) {
String actionOrNull = androidIntent.getAction();
if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(actionOrNull) ||
BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(actionOrNull)) {
Log.d(TAG, "BluetoothReceiver.onReceive() " + actionOrNull);
if (_btnActivate.isEnabled()) {
sendRequestActivationToServer();
}
}
}
}
...
// Reference to the object used to monitor Bluetooth connections and disconnections
private BluetoothReceiver _bluetoothReceiver = null;
...
// Last lifecycle method called before fragment becomes active. This is apparently the
// recommended place to register a receiver object, and is used to register a receiver object to
// monitor Bluetooth connections and disconnections.
#Override
public void onResume() {
super.onResume();
_bluetoothReceiver = new BluetoothReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
getActivity().registerReceiver(_bluetoothReceiver, intentFilter);
}
...
// First lifecycle method called when a fragment is on its way to being paused or destroyed. This
// is apparently the recommended place to unregister a receiver object, and is used to unregister
// the receiver object that monitors Bluetooth connections and disconnections.
#Override
public void onPause() {
super.onPause();
if (_bluetoothReceiver != null) {
getActivity().unregisterReceiver(_bluetoothReceiver);
_bluetoothReceiver = null;
}
}
This was inspired by this question and answer: How to receive intents for Bluetooth devices working?
My app can be controlled by normal headset. It simply overrides "onKeyDown". But key events from bluetooth headset are not captured - why? Or how to capture bluetooth key events?
the "log cat" shows the following if i press button on headset:
Bluetooth AT recv(3043): AT+VGS=15
AudioPolicyManagerBase(13654): FM radio recording off
AudioService(2261): sendVolumeUpdate, isKeyguardLocked...Not to update Volume Panel.
VolumePanel(2261): change volume by MSG_VOLUME_CHANGED
VolumePanel(2261): onVolumeChanged(streamType: 6, flags: 0)
VolumePanel(2261): Call setChangeSeekbarColor(false)
i also tried to handle media button actions but this isn't working. my idea is a free configurable key mapping: the user chooses "set key" my app hears on all keys (hardware, media buttons, bluetooth headset) then the user presses a key and the event/key code is stored in config.
Summerizing not working Answers:
Volume buttons must be captured by "VOLUME_CHANGED_ACTION". The problem is this intents are broadcasted to other apps and abortBroadcast() doesn't work (it works only for "ordered" Broadcasts). Another problem is that keys on cable headset and on phone trigger onReceive() twice (why?) the bluetooth headset trigger it once.
The next Problem is the 3rd key on Bluetooth headset. It triggers voice-command (s-voice starts on s3), i tried to capture many different intents regarding this but i can't "receive" this button press and don't know why.
At the end i want capture all kinds of buttons and don't want them handled by other apps (like using onKeyDown and returning true).
Add a broadcast listener to MEDIA_BUTTON:
<intent-filter android:priority="<some number>">
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
You should register your broadcast receiver inside your application (not in manifest file). Otherwise Google Music player will catch your broadcast and aboard it.
Your IntentFilter priority should be higher that other media players priorities in your phone)
Add android.permission.BLUETOOTH permission in manifest to support Bluetooth headset
After received you key you have to manually abort the broadcast using abortBroadcast().
However priorities and abortBroadcast() work fine as long as each app only responds while
e.g. something is played.
But several users also expect a "default player" to be launched (or start playing) upon button press, like the default player, so it might happen some app with a higher priority number won't let the intent come through to your app
In the onReceive, you can get the button event with
KeyEvent key = (KeyEvent)
intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
key.getKeyAction() tells you whether the button was released or pressed, key.getKeyCode() tells which button is pressed.
If you want to handle single button cable headsets as well, also
regard the key code KEYCODE_HEADSETHOOK
Override the onKeyDown method in any activity and check for
the KeyEvent.KEYCODE_MEDIA_KEYCODE_pressed_key
e.g.
boolean onKeyDown(int keyCode, KeyEvent event) {
AudibleReadyPlayer abc;
switch (keyCode) {
case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
// code for fast forward
return true;
case KeyEvent.KEYCODE_MEDIA_NEXT:
// code for next
return true;
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
// code for play/pause
return true;
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
// code for previous
return true;
case KeyEvent.KEYCODE_MEDIA_REWIND:
// code for rewind
return true;
case KeyEvent.KEYCODE_MEDIA_STOP:
// code for stop
return true;
}
return false;
}
Volume key integration example
Android - Volume Buttons used in my application
This one may need permission
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
Or you can try slimier implementations over the following link
Android Developer Blog : Handling remote control buttons
Android Tales : Add Headset button support to your Android application
Check out this article. It explains how to implement something similar using media button actions.
I know you've mentioned that you walked this way without success, still give it a try. Point your attention to gotchas related to registering broadcast receiver, setting intent filter priorities and adding permissions (all explained in the article).
Hope this will help.
If you are trying to listen for this from an activity, use onKeyDown() and catch the KEYCODE_MEDIA_PLAY_PAUSE (KEYCODE_MEDIA_PLAY and KEYCODE_MEDIA_PAUSE post ICS) key events.
Also for the broadcast receiver solution to work make sure there arent other apps installed and running in the background that catch these events which might take priority over yours.
Also look at this: Android - registering a headset button click with BroadcastReceiver
I'd like to detect when a user presses any hardware button on a sleeping android phone (or at least the home and the power button).
Until now I have used a BroadcastReceiver for the ACTION_SCREEN_ON event, which works great but it is also raised when e.g. you get a message, a phone call or when an alarm starts.
ACTION_USER_PRESENT is also no option because this is only raised when the user really is present an knows the unlock code, so he isn't tampering with the phone.
Is there a way to handle that?
no its not possible
but this can be used for other purpose
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_MENU)
{
}
return true;
}