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

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

Ответ 1

Решение:

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

Ответ 2

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

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

<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 undefined, вам не нужно.

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

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

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

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

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

Ответ 3

В вашей деятельности добавьте:

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

Как упоминалось здесь fooobar.com/questions/21963/...

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    if(!hasFocus) {
       Intent closeDialog = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
        sendBroadcast(closeDialog);
    }
}

Ответ 5

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

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

    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));
                }
            }
        }
    }
    
  • Запуск службы и добавление специального представления в WindowManager

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

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>

Ответ 6

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

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

Ответ 7

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

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;

}};