I need catch long press of volume button when phone is sleeping(screen off) and I know this code:
#Override
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)
{
// to your stuff here
return true;
}
return super.onKeyLongPress(keyCode, event);
}
is not helpful(it works only in active intent
I'm curious about this too.
While this isn't necessarily an answer, I have done some research on Services (to catch the volume press I'm guessing) and BroadcastReceivers (onReceive() would receive an intent for ACTION_SCREEN_OFF and probably set a flag for the screen being off). My thinking is starting the service when the screen turns off and kill it when the screen turns on, but I don't know how to join onKeyLongPress and the service.
The sequence I see happening is this: Screen turns off -> BroadcastReceiver receives this command and starts the service to watch for volume press -> receive volume press and do your logic -> kill the service if the screen turns on.
I found a site that apparently handles screen off/on and has an example for an activity and a service but I can't get something together yet:
http://thinkandroid.wordpress.com/2010/01/24/handling-screen-off-and-screen-on-intents/
One thing I'm worried about when using a service is battery life and processing time but that will be testing down the road. I will hopefully be able to mitigate that with killing the service when the screen turns on. I'll try to keep this entry updated as I make progress.
Good luck!
Related
My app has a long running background service. I registered my service with a broadcastreceiver which handles SCREEN_ON and SCREEN_OFF actions. However, the problem with using this approach is that while it does work, whenever the phone was woken up by incoming phone calls, power cable plugin events or alarmmanager etc, SCREEN_ON action also triggers and I don't want that.
Is it possible to "physically" capture the power button click events when only my background service is running? I'm not trying to override power button.
The existing answers don't completely answer the question and leave out enough details that they won't work without more investigation. I'll share what I've learned solving this.
First you need to add the following permission to your manifest file:
<uses-permission android:name="android.permission.PREVENT_POWER_KEY" />
To handle short and long presses add the following overrides to your activity class:
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_POWER) {
// Do something here...
event.startTracking(); // Needed to track long presses
return true;
}
return super.onKeyDown(keyCode, event);
}
#Override
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_POWER) {
// Do something here...
return true;
}
return super.onKeyLongPress(keyCode, event);
}
Note: It is worth noting that onKeyDown() will fire multiple times before onKeyLongPress does so you may want to trigger on onKeyUp() instead or other logic to prevent acting upon a series of onKeyDown() calls when the user is really holding it down.
I think this next part is for Cyanogenmod only. If the PREVENT_POWER_KEY constant is undefined then you should not need it.
To start intercepting the power key you need to set the following flag from your activity:
getWindow().addFlags(WindowManager.LayoutParams.PREVENT_POWER_KEY);
To stop intercepting the power key (allowing standard functionality):
getWindow().clearFlags(WindowManager.LayoutParams.PREVENT_POWER_KEY);
You can switch back and forth between the two modes repeatedly in your program if you wish.
reference :
https://stackoverflow.com/a/10365166/2724418
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
How can I make as long as the app is opened, the users shouldn't be allowed to change the volume of the device?, if this is possible.
I have found that you can set the volume to mute with AudioManger:
AudioManager volumeControl = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
volumeControl.setStreamMute(AudioManager.STREAM_MUSIC, true);
However this is not what I'm looking for. I want when the user enters the application to lock its current volume and does not allow to change it, while in background a melody is playing increasing the volume. (this is the reasons for why I don't want let user control the volume)
I was thinking if there's a possibility to override the Volume up, Volume down keys? just like we can override the Back button.
I was thinking if there's a possibility to override the Volume up, Volume down keys? just like we can override the Back button.
Yes, you can handle it in the same way.
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)){
//Nothing
}
return true;
}
#sarnold I can see the use case if it is an alarm clock. Many people want this feature in alarm clocks to stop themselves from turning the sound off when they are wanting to wake up.
Either way, be aware that you may annoy your users doing things like this. It should be avoided if at all possible.
EDIT: Setting the Volume
AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE);
am.setStreamVolume(AudioManager.STREAM_MUSIC,6,0);
Alright as I have been asking the last couple days and inching closer and closer to the final outcome of this question:
Is it possible to use the volume (up / down) buttons to start an app?
Here is the code I am working with:
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
Log.w("myApp", "LONG PRESS");
}
//my code here
return super.onKeyLongPress(keyCode, event);
}
I am wondering what I am doing wrong. Nothing in the code is giving me errors, its just not running when I tell it to.
Note:
I am testing this on a live android if that helps out at all.
Any advice would be wonderful.
Is it possible to use the volume (up / down) buttons to start an app?
No, sorry. You cannot use hardware buttons to start apps, with the exception of the CAMERA button (where it exists) or the MEDIA button (where it exists, typically on headsets). For those, you would register a BroadcastReceiver in the manifest for their respective broadcasts, and bear in mind that those broadcasts are only sent out if the foreground activity does not consume the key event (e.g., music player pausing when the MEDIA button is pressed).
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;
}