Как подключиться к кнопке Power в Android?

На устройстве Android, где единственными кнопками являются кнопки регулировки громкости и кнопка питания, я хочу заставить приложение реагировать на нажатия кнопки питания (длинная и короткая). Как это делается?

Solutions Collecting From Web of "Как подключиться к кнопке Power в Android?"

Существующие ответы не полностью отвечают на вопрос и оставляют достаточно подробностей, что они не будут работать без дальнейшего расследования. Я расскажу, что я узнал, решая это.

Сначала вам нужно добавить в файл манифеста следующие разрешения:

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

Для обработки коротких и длинных нажатий добавьте в класс активности следующие переопределения:

 @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 (), когда пользователь действительно удерживает ее ,

Я думаю, что эта следующая часть предназначена только для Cyanogenmod. Если константа PREVENT_POWER_KEY не определена, вам не нужно.

Чтобы начать перехват ключа питания, вам необходимо установить следующий флаг из вашей активности:

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

Чтобы остановить перехват ключа питания (разрешая стандартную функциональность):

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

Вы можете переключаться между двумя режимами повторно в своей программе, если хотите.

Решение:

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

На вас активность добавляет:

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

Хотя … такие ключи как-то особенные … не уверены, что это может дать вам проблемы.

Как упоминалось здесь, 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); } } 

Вы можете перезаписать public boolean onKeyDown(int keyCode, KeyEvent event) и public boolean onKeyUp(int keyCode, KeyEvent event) в вашем классе Activity и протестировать, если keyCode равен KeyEvent.KEYCODE_POWER .

Я не тестировал это, но я бы предположил, что система относится к этому так, как к ключу Home поскольку вы не можете остановить систему от получения ключевого события, вы можете только заметить, что это происходит. Чтобы проверить это, попробуйте вернуть True из вышеуказанных функций и посмотреть, не попадает ли это событие ключа.

Совместное использование метода для длительного нажатия кнопки питания. Работает с разрешениями API 23+:

  1. Запрос системного разрешения на наложение (это не нормальное или уязвимое разрешение). Это не пользовательское разрешение, поэтому вы должны действительно знать, что вы делаете, прося об этом.

     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. Ожидание действия внутри метода 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; } } 

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> 

Вы должны использовать это:

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