Detect power button long press

前端 未结 11 2205
轮回少年
轮回少年 2020-11-27 18:38

I\'ve been reading some posts here on Stackoverflow, and I didn\'t find a good solution, I\'m wondering if it\'s possible to detect when the user long press the power button

相关标签:
11条回答
  • 2020-11-27 19:01

    From Skizo-ozᴉʞS question, what I understand, you actually want to prevent the behavior of the power button and that can't be done. just like the home button pressed some events in android can't be prevented to avoid people having apps they can't quit.

    0 讨论(0)
  • 2020-11-27 19:04

    The method used above by R. Zagórski worked for me very well for a long time, but from some revision of Android 9 the onCloseSystemDialogs method stopped receiving "globalactions".

    As a workaround, my app is already using Accessibility. From inside the AccessibilityService you can add this code in 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
    
        }
            ....
    

    Note that were I put the comment "TRIGGER YOUR CODE HERE" I actually just call the same code that was previously in onCloseSystemDialogs.

    Note that so far this is only tested to be working on a Pixel 2 running latest Android. I do not have any other phones running a recent enough version so can't test if the solution is sufficiently generic across phones.

    0 讨论(0)
  • 2020-11-27 19:07

    Sharing my method to do what you would like to achieve.

    Basically, what it does is

    1. 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));
                  }
              }
          }
      }
      
    2. Starting a service and adds a special view to WindowManager

    3. Waiting for an action inside View's 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
             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>
    
    0 讨论(0)
  • 2020-11-27 19:07

    The accepted answer works flawlessly till Android Oreo but not in Android P. To make it work in android P you'll need to use Accessibility Service

    Service Class

    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() {
    
        }
    }
    

    As you cannot use startService() method to start an Accessibility Service,

    So here it is how you can enable it.

    Intent openSettings = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
    openSettings.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(openSettings);
    
    0 讨论(0)
  • 2020-11-27 19:08

    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

    0 讨论(0)
  • 2020-11-27 19:08

    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 Button Of power show toast for test...

    0 讨论(0)
提交回复
热议问题