Long press the power button

I read some posts here on Stackoverflow, and I did not find a good solution, I wonder if it is possible to determine when the user presses the power button for a long time while trying to turn off the device, I would like to find out if you can detect this event and enable or disable showing this dialog box in which it appears (reboot, shutdown, etc.)

I tried this:

@Override public boolean dispatchKeyEvent(KeyEvent event) { Toast.makeText(MainActivity.this, event.getKeyCode(), Toast.LENGTH_SHORT).show(); return true; } 

but it does not appear, it should also work as a service, I mean that the application may or may not be open to show this toast.

EDIT

This is how I put onCloseSystemDialog

 //home or recent button public void onCloseSystemDialogs(String reason) { if ("globalactions".equals(reason)) { Toast.makeText(PowerButtonService.this, "yaps", Toast.LENGTH_SHORT).show(); Intent i= new Intent(getBaseContext(), Demo.class); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); getApplication().startActivity(i); //} else if ("homekey".equals(reason)) { //home key pressed //} else if ("recentapss".equals(reason)) { // recent apps button clicked } } 

It works fine, but only when the device is unlocked, when the device is locked, nothing is displayed.

I am also trying to figure out how to remove the dialog box when the user presses the power button. I tried to do this:

 getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD); 

But if I want to show it again, how can I do it?

+17
android events android-studio
Aug 21 '16 at 13:06 on
source share
11 answers

Share your method to do what you would like to achieve.

In essence, this

  1. Requesting system permission to draw an overlay (this is not an ordinary or vulnerable permission). This is not user permission, so you should really know what you are doing when requesting 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)); } } } } 
  2. Starting a service and adding a custom view to WindowManager

  3. Waiting for an action inside the View onCloseSystemDialogs 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 ("recentapps".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> 
+17
Aug 29 '16 at 11:20
source share
— -

I see a lot of answers trying to hook the power button. However, wouldn't it be easier to listen to the shutdown event? I'm not sure if this fits your needs, but it seems like that.

Just register Broadcastreceiver for the following actions :

 <receiver android:name=".ShutdownReceiver"> <intent-filter> <action android:name="android.intent.action.ACTION_SHUTDOWN" /> <action android:name="android.intent.action.QUICKBOOT_POWEROFF" /> </intent-filter> </receiver> 

Remember to add the following permission:

<uses-permission android:name="android.permission.DEVICE_POWER" />

+6
Aug 29 '16 at 19:01
source share

This simple solution works:

  @Override public boolean dispatchKeyEvent(KeyEvent event) { int keyPressed = event.getKeyCode(); if(keyPressed==KeyEvent.KEYCODE_POWER){ Log.d("###","Power button long click"); Toast.makeText(MainActivity.this, "Clicked: "+keyPressed, Toast.LENGTH_SHORT).show(); return true;} else return super.dispatchKeyEvent(event); } 

If you want to stop the system popup , use the onWindowFocusChanged method specified in one of the answers below.

The output will show a toast with "Clicked: 26", as attached below. enter image description here

+5
Aug 29 '16 at 2:31 on
source share

Go with it

 <uses-permission android:name="android.permission.PREVENT_POWER_KEY" /> 

And when you want to capture this event, do it

 @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_POWER) { // this is method which detect press even of button 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) { // Here we can detect long press of power button return true; } return super.onKeyLongPress(keyCode, event); } 

This can be done using a broadcast receiver. see this answer

+5
Aug 29 '16 at 6:03
source share

Try the following:

 @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); } 
+3
Aug 24 '16 at 7:34
source share

For Long Press .... Please Try this ...

 import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.KeyEvent; import android.view.WindowManager; import android.widget.Toast; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class demo extends Activity { private final List<Integer> blockedKeys = new ArrayList<>(Arrays.asList(KeyEvent.KEYCODE_VOLUME_DOWN, KeyEvent.KEYCODE_VOLUME_UP, KeyEvent.KEYCODE_POWER)); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD); setContentView(R.layout.demo); } @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (!hasFocus) { // Close every kind of system dialog Intent closeDialog = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); sendBroadcast(closeDialog); Toast.makeText(demo.this, "Your LongPress Power Button", Toast.LENGTH_SHORT).show(); } } @Override public void onBackPressed() { // nothing to do here // … really } @Override public boolean dispatchKeyEvent(KeyEvent event) { if (blockedKeys.contains(event.getKeyCode())) { return true; } else { return super.dispatchKeyEvent(event); } } } 

Long press the Power Show toast button for the test ...

enter image description here

+3
Aug 27 '16 at 5:31 on
source share

The method used by R. Zagorsky worked for me very well for a long time, but with some revision of Android 9, the onCloseSystemDialogs method stopped receiving "global actions".

As a workaround, my application already uses Accessibility. From within the AccessibilityService, you can add this code to onAccessibilityEvent

 @Override public void onAccessibilityEvent(AccessibilityEvent event) { Log.i(TAG,"Accessibilityevent"); if (event == null || event.getPackageName()==null||event.getClassName()==null) return; if (event.getClassName().toString().contains("globalactions")){ //TRIGGER YOUR CODE HERE } .... 

Please note that if I put the comment "TRIGGER YOUR CODE HERE", I actually just call the same code that was previously in onCloseSystemDialogs .

Please note that so far this has only been tested to work with the Pixel 2 running the latest version of Android. I do not have other phones with a fairly recent version, so I can’t check if the solution is common enough for all phones.

+3
Oct 11 '18 at 9:37
source share

From the question of Skizo-ozᴉʞS, what I understand is, you really want to prevent the power button from behaving, and this is not possible. just as the home button is pressed, some events in the android cannot be prevented in order to avoid people whose applications cannot exit.

+2
Aug 29 '16 at 11:35
source share

You can catch the power button event by overriding the KeyDown method

 @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_POWER) { Log.e("key","long"); /*//disable the system dialog Intent closeDialog = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); sendBroadcast(closeDialog);*/ Toast.makeText(getApplicationContext(),"Power",Toast.LENGTH_SHORT).show(); } return super.onKeyDown(keyCode, event); } 

As far as I know, we can’t do this outside the scope of the activity (e.g. background service)

+1
Aug 24 '16 at 6:28
source share

The accepted answer works flawlessly until Android Oreo, but not until Android P. For it to work in Android P, you need to use the Accessibility Service

Class of service

 import android.accessibilityservice.AccessibilityService; import android.util.Log; import android.view.accessibility.AccessibilityEvent; import com.bm.yucasa.Utils.LocationSetup; import static com.bm.yucasa.controller.AppController.TAG; public class PowerServiceTwo extends AccessibilityService { @Override public void onAccessibilityEvent(AccessibilityEvent event) { Log.i(TAG,"Accessibilityevent"); if (event == null || event.getPackageName()==null||event.getClassName()==null) return; if (event.getClassName().toString().contains("globalactions")){ LocationSetup locationSetup = LocationSetup.getInstance(PowerServiceTwo.this); if (locationSetup.isConnected) { locationSetup.startOnDemandLocationUpdates(false, "0"); } else { //Toast.makeText(getApplicationContext(), "please check gps", Toast.LENGTH_SHORT).show(); } } } @Override public void onInterrupt() { } } 

Since you cannot use the startService () method to start the accessibility service,

So here is how you can enable it.

 Intent openSettings = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS); openSettings.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(openSettings); 
+1
Mar 20 '19 at 6:45
source share

Try the following:

  @Override public boolean onKeyLongPress( int keyCode, KeyEvent event ) { if( keyCode == KeyEvent.KEYCODE_POWER ) { //Handle what you want in long press. return true; } return super.onKeyLongPress( keyCode, event ); } 

Add this to the manifest:

  <uses-permission android:name="android.permission.DEVICE_POWER" /> <uses-permission android:name="android.permission.PREVENT_POWER_KEY" /> 
0
Aug 30 '16 at 9:11
source share



All Articles