Как подключить кнопку включения в Android? - PullRequest
29 голосов
/ 13 сентября 2010

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

Ответы [ 8 ]

39 голосов
/ 28 апреля 2012

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

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

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

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

7 голосов
/ 15 сентября 2010

Решение:

@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);
}
4 голосов
/ 29 августа 2016

Совместное использование метода для прослушивания кнопки питания длительным нажатием.Работает с разрешениями 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. Ожидание действия внутри 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>
4 голосов
/ 13 сентября 2010

Относительно вашей активности добавьте:

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

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

3 голосов
/ 05 апреля 2013

Как упомянуто здесь 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);
    }
}
1 голос
/ 13 сентября 2010

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

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

0 голосов
/ 22 апреля 2019

Для всех версий Android используйте этот код.

Я пробовал R.Zagórski , но я не могу запустить этот код на Pie.Однако я обновил их код в своем ответе.

PowerButtonService:

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:" + "9690008019"));
                    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;
    }
}

и service_layout:

<?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>
0 голосов
/ 31 июля 2011

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

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;

}};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...