Detect power button long press
Go with this
<uses-permission android:name="android.permission.PREVENT_POWER_KEY" />
And when you want to capture that event do this
@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);
}
It can be done with broadcast receiver. see this answer
I see many answers trying to hookin to the powerbutton. However, wouldn't it be more easy to listen for the shutdown event? I'm not sure if this fits your need, but it seems like it.
Simply register a Broadcastreceiver to the following action(s):
<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>
Don't forget to add the following permission:
<uses-permission android:name="android.permission.DEVICE_POWER" />
Sharing my method to do what you would like to achieve.
Basically, what it does is
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 ("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 final WindowManager.LayoutParams params; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { params = new WindowManager.LayoutParams( 100, 100, WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT); } else { params = new WindowManager.LayoutParams( 100, 100, WindowManager.LayoutParams.TYPE_PHONE, 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>
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 system pop-up, use the onWindowFocusChanged
method specified in one of the answers below.
The output will show the toast with "Clicked:26" as attached below.