On an Android device, where the only buttons are the volume buttons and a power button, I want to make the app react to presses on the power button (long and short). How is this done?
9 Answers
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.

- 633
- 1
- 8
- 9
-
4does this work with all API versions? I tries APIs 8 and 15 and there is no PREVENT_POWER_KEY param within LayoutParams. Could you maybe here value of this param? – Koger Sep 04 '12 at 15:06
-
1The value for WindowManager.LayoutParams.PREVENT_POWER_KEY is 0x80000000 But what it looks like is that this is either a hidden value or specific only to Cyanogenmod (which would be disturbing if true). The project I did this for was API 10 but I had modified the sdk to expose hidden APIs and I was running it on Cyanogenmod 7. – JT. Sep 22 '12 at 00:20
-
3onKeyDown only works when a long press event occurs the actually onKeyLongPress never gets fired by the Power button, at least on a Motorola Droid X2. – JPM Nov 27 '12 at 15:31
-
2@JPM, @JT.: Exactly the same problem here (Galaxy Note, ICS): onKeyDown only works when a long press event occurs, and the actually onKeyLongPress never gets fired. Moreover, Power button is not prevented by the `uses-permission` in the manifest. – Luis A. Florit Feb 16 '13 at 18:10
-
Its not working on Samsung S(Api lable 2.2). but working on ICS. How to solve this problem? – Atul Bhardwaj Jul 08 '13 at 10:57
-
-
3I can't see permission you have mentioned above, its not listed here http://developer.android.com/reference/android/Manifest.permission.html – Nauman Zubair May 28 '14 at 06:27
-
4The PREVENT_POWER_KEY was required for cyanogenmod only. Apparently stock Android has removed the ability to capture the power key sometime in the last couple of years. This approach may suit the needs of anybody who needs to do something when the power key is pressed: http://stackoverflow.com/questions/7682016/android-listen-for-power-key-press?rq=1 – JT. Jul 03 '14 at 17:07
-
@JT. I am on CyanogenMod 12 and I could not get it to work. Also I can detect other keys like volume up/down, back, menu buttons etc (saw in Log) but I could NOT detect power button using the onKeyDown. The screen just turn off. – tcboy88 Sep 06 '15 at 20:41
-
Solution:
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_POWER) {
Intent i = new Intent(this, ActivitySetupMenu.class);
startActivity(i);
return true;
}
return super.dispatchKeyEvent(event);
}

- 8,483
- 7
- 34
- 37
-
Yes, on single press this is not invoked. when you long press this reacts. – Khushboo Oct 28 '14 at 07:20
-
Would this work when the phone is off (er...screen locked)? I want a long-press of the power button to launch the voice command input so i don't have to take two seconds to unlock the phone, then invoke the voice command. – Kyle Sweet Nov 30 '16 at 22:16
On you activity add:
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_POWER) {
// do what you want with the power button
return true;
}
return super.onKeyDown(keyCode, event);
}
Though... this kind of keys are somehow special... not sure if it can give problems to you.

- 198,401
- 62
- 356
- 264
As mentioned here https://stackoverflow.com/a/15828592/1065357
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if(!hasFocus) {
Intent closeDialog = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
sendBroadcast(closeDialog);
}
}

- 1
- 1

- 1,365
- 2
- 15
- 31
-
There is a problem with this solution, you will need to override this method for activities, menu, dialogs, fragments ... if you only do it in your activity, the user will be able to access the power menu when there is a dialog showing. – ChRoNoN Aug 09 '18 at 19:11
Sharing a method to listen for Power button long press. Works with API 23+ permissions:
Asking for system permission to draw overlay (This is not a normal or vulnerable permission). This is not a user permission, so You should really know, what you are doing, by asking for it.
public class MainActivity extends AppCompatActivity { public final static int REQUEST_CODE = 10101; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (checkDrawOverlayPermission()) { startService(new Intent(this, PowerButtonService.class)); } } public boolean checkDrawOverlayPermission() { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { return true; } if (!Settings.canDrawOverlays(this)) { /** if not construct intent to request permission */ Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())); /** request permission via start activity for result */ startActivityForResult(intent, REQUEST_CODE); return false; } else { return true; } } @Override @TargetApi(Build.VERSION_CODES.M) protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_CODE) { if (Settings.canDrawOverlays(this)) { startService(new Intent(this, PowerButtonService.class)); } } } }
Starting a service and adds a special view to
WindowManager
Waiting for an action inside
View
'sonCloseSystemDialogs
method.public class PowerButtonService extends Service { public PowerButtonService() { } @Override public void onCreate() { super.onCreate(); LinearLayout mLinear = new LinearLayout(getApplicationContext()) { //home or recent button public void onCloseSystemDialogs(String reason) { if ("globalactions".equals(reason)) { Log.i("Key", "Long press on power button"); } else if ("homekey".equals(reason)) { //home key pressed } else if ("recentapss".equals(reason)) { // recent apps button clicked } } @Override public boolean dispatchKeyEvent(KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK || event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP || event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_DOWN || event.getKeyCode() == KeyEvent.KEYCODE_CAMERA || event.getKeyCode() == KeyEvent.KEYCODE_POWER) { Log.i("Key", "keycode " + event.getKeyCode()); } return super.dispatchKeyEvent(event); } }; mLinear.setFocusable(true); View mView = LayoutInflater.from(this).inflate(R.layout.service_layout, mLinear); WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE); //params WindowManager.LayoutParams params = new WindowManager.LayoutParams( 100, 100, WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, PixelFormat.TRANSLUCENT); params.gravity = Gravity.LEFT | Gravity.CENTER_VERTICAL; wm.addView(mView, params); } @Override public IBinder onBind(Intent intent) { return null; } }
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="powerbuttonpress">
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service
android:name=".PowerButtonService"
android:enabled="true"
android:exported="true">
</service>
</application>
</manifest>
service_layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</LinearLayout>

- 20,020
- 5
- 65
- 90
-
1Brilliant! Thanks. One problem here is that soft keyboard cant be opened :( – Zohar Aug 31 '16 at 09:16
-
-
If anyone is having issues with the soft keyboard not showing, you can add `WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE` to your windowmanager params to fix it – Trevor Halvorson Aug 17 '17 at 18:06
-
2
-
1this method is not working for android 9, does anyone try it on android 9.? – Anurag Goel Sep 23 '18 at 04:57
-
This worked for me for a long time but seems to have been plugged in recent security patch of Android 9. "globalactions" is no longer reported although other reasons like "home" are – D2TheC Oct 11 '18 at 09:03
-
Its working perfectly for oreo and older versions. Not working in Pie. Anyone got a solution for making this work in pie? – Ana Mar 08 '19 at 06:20
Use Broadcast receiver for power button (Screen On/Off)event
here is solution: create broadcast receiver class
public class CallBroadCastReciever extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
//The screen off position
Toast.makeText(context,"Screen is off",Toast.LENGTH_LONG).show();
}
else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
//The screen on position
Toast.makeText(context,"Screen is on",Toast.LENGTH_LONG).show();
}
}}
then follow below steps: 1. Initialize receiver in activity
CallBroadCastReciever broadcastReceiver = new CallBroadCastReciever();
2.Declare receiver in manifest file in tag
<receiver android:name="com.android.CallBroadCastReciever">
<intent-filter>
<action android:name="android.intent.action.SCREEN_OFF"/>
<action android:name="android.intent.action.SCREEN_ON"/>
</intent-filter>
</receiver>
3.For send action and data from activity to receiver put below code in onCreate() or onStrat() method
IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
if (broadcastReceiver != null) {
registerReceiver(broadcastReceiver, intentFilter);
}}
4.Don't forget to unregister receiver in onDestory() method
protected void onDestroy() {
super.onDestroy();
if (broadcastReceiver != null) {
unregisterReceiver(broadcastReceiver);
} }

- 314
- 3
- 8
-
-
I am using the same approach for flashlight light blinking to stop on power button but its not working. – Anwar Zahid Aug 04 '21 at 04:43
You could overwrite the public boolean onKeyDown(int keyCode, KeyEvent event)
and public boolean onKeyUp(int keyCode, KeyEvent event)
functions in your Activity class and test if keyCode
is equal to KeyEvent.KEYCODE_POWER
.
I haven't tested this, but I would assume the system treats this like it does the Home
key in that you cannot stop the system from receiving the key event, you can only observe that it occurs. To test this, try returning True
from the above functions and see if this catches the key event.

- 3,328
- 1
- 24
- 22
For all android versions use this code.
I tried R. Zagórski's answer, but I am not able to run this code on Pie. However, I have updated their code in my answer.
PowerButtonService:
public class PowerButtonService extends Service {
public PowerButtonService() {
}
@Override
public void onCreate() {
super.onCreate();
LinearLayout mLinear = new LinearLayout(getApplicationContext()) {
//home or recent button
public void onCloseSystemDialogs(String reason) {
if ("globalactions".equals(reason)) {
Log.i("Key", "Long press on power button");
Intent intent = new Intent(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:" + "0000000000"));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_FROM_BACKGROUND);
startActivity(intent);
} else if ("homekey".equals(reason)) {
//home key pressed
} else if ("recentapss".equals(reason)) {
// recent apps button clicked
}
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK
|| event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP
|| event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_DOWN
|| event.getKeyCode() == KeyEvent.KEYCODE_CAMERA
|| event.getKeyCode() == KeyEvent.KEYCODE_POWER) {
Log.i("Key", "keycode " + event.getKeyCode());
}
return super.dispatchKeyEvent(event);
}
};
mLinear.setFocusable(true);
**// here I done with EDIT**
int LAYOUT_FLAG;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE;
}
View mView = LayoutInflater.from(this).inflate(R.layout.service_layout, mLinear);
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
//params
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
LAYOUT_FLAG,
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.LEFT | Gravity.CENTER_VERTICAL;
wm.addView(mView, params);
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
and service_layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_gravity="center"
android:gravity="center"
android:layout_height="match_parent">
</LinearLayout>

- 2,225
- 1
- 14
- 30
-
1I wouldn't use this code, it's going to make a phone call in the background to some mystery number. – Jeff Schmitz Apr 08 '20 at 20:05
-
1@JeffSchmitz You have to edit phone number here - intent.setData(Uri.parse("tel:" + "0000000000")); – Abhinav Gupta Jan 05 '21 at 06:28
you have to use this:
BroadcastReceiver screenoff = new BroadcastReceiver() {
public static final String Screenoff = "android.intent.action.SCREEN_OFF";
@Override
public void onReceive(Context context, Intent intent) {
if (!intent.getAction().equals(Screenoff)) return;
//put code to handle power press here
return;
}};

- 57,693
- 12
- 90
- 123

- 93
- 2
- 7
-
2
-
That intent filter didn't work, I'm receiving nothing on Android 6.0.1 – m0skit0 Nov 02 '18 at 11:27