代码之家  ›  专栏  ›  技术社区  ›  Lars D

如何在Android中连接到电源按钮?

  •  29
  • Lars D  · 技术社区  · 14 年前

    在Android设备上,只有音量按钮和电源按钮,我想让应用程序对按下电源按钮(长和短)做出反应。这是怎么做到的?

    7 回复  |  直到 14 年前
        1
  •  41
  •   JT.    12 年前

    现有的答案并不能完全回答这个问题,并且遗漏了足够的细节,如果没有更多的调查,这些答案将不起作用。我将分享我在解决这个问题上学到的东西。

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

    要处理短按和长按,请向activity类添加以下覆盖:

    @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);
    }
    

    注意:值得注意的是,onKeyDown()将在onKeyLongPress触发之前触发多次,因此您可能需要在onKeyUp()或其他逻辑上触发,以防止在用户真正按下onKeyDown()时对一系列onKeyDown()调用执行操作。

    我想下一部分只针对Cyanogenmod。 如果 常量未定义,则不需要它。

    要开始截取电源键,您需要在活动中设置以下标志:

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

    getWindow().clearFlags(WindowManager.LayoutParams.PREVENT_POWER_KEY);
    

        2
  •  8
  •   Lars D    14 年前

    @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
  •  4
  •   Cristian    14 年前

    在活动中添加:

    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);
    }
    

    不过。。。这种钥匙有点特别。。。不确定是否会给你带来麻烦。

        4
  •  4
  •   Community Marino Di Clemente    7 年前

    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);
        }
    }
    
        5
  •  4
  •   R. Zagórski Krishnraj Anadkat    8 年前

    分享一个方法,听电源按钮长按。使用API 23+权限:

    1. 请求系统权限 draw overlay

      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. WindowManager

    3. 在里面等待行动 View onCloseSystemDialogs

      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;
          }
      }
      

    <?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>
    

    服务单元布局:

    <?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>
    
        6
  •  1
  •   Aaron C    14 年前

    你可以覆盖 public boolean onKeyDown(int keyCode, KeyEvent event) public boolean onKeyUp(int keyCode, KeyEvent event) 活动类中的函数并测试 keyCode 等于 KeyEvent.KEYCODE_POWER .

    我还没有测试过这个,但是我假设系统会像对待 Home True

        7
  •  0
  •   Adriano Carneiro Tigran    13 年前

    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;
    
    }};
    
        8
  •  0
  •   civani mahida    5 年前

    使用 广播接收机

    下面是解决方案:创建广播接收器类

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

    然后执行以下步骤: 1初始化活动中的接收器

    CallBroadCastReciever broadcastReceiver = new CallBroadCastReciever();
    

    2.在标签的清单文件中声明接收者

     <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>
    

    IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
    
    if (broadcastReceiver != null) {
        registerReceiver(broadcastReceiver, intentFilter);
    }}
    

    4.别忘了在onDestory()方法中注销接收器

     protected void onDestroy() {
            super.onDestroy();
     if (broadcastReceiver != null) {
                    unregisterReceiver(broadcastReceiver);
                 } }
    
        9
  •  0
  •   Abhinav Gupta Eduardo Oliveira    4 年前

    我试过了 R. Zagórski 的答案,但我无法在Pie上运行此代码。不过,我已经更新了他们的代码在我的答案。

    电源按钮服务:

    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;
        }
    }
    

    <?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>