Вопрос по android – Переопределить кнопку питания, как кнопка «Домой»

36

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

Жесткие кнопки, такие как Power, Home, Volume up, Volume down, Search, Back.

Я успешно переопределил почти все кнопкиВот кроме силы.

Поэтому я просто хочу, чтобы вы, люди, увидели и поделились некоторыми идеями, чтобы я мог с этим покончить.

Я получаюlong press Power Keyevent вonDispatchKeyEvent()Точно так же я хочу поймать короткий щелчок того же. Более того при нажатии power я тоже пытался остановитьсяScreen off получивBroadcast изSCREEN_OFF и мне удалось получить его, но я не смог справиться с этим.

Благодарю.

Затем я создал ReceiverScreen, который получает трансляцию экрана вкл / выкл

ReceiverScreen.java

public class ReceiverScreen extends BroadcastReceiver {

    public static boolean wasScreenOn = true;

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
            // do whatever you need to do here
            wasScreenOn = false;
        } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
            // and do whatever you need to do here
            wasScreenOn = true;
        }
    }
}

DisableHardButton.java

public class DisableHardButton extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);
    IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
    filter.addAction(Intent.ACTION_SCREEN_OFF);
    BroadcastReceiver mReceiver = new ReceiverScreen();
    registerReceiver(mReceiver, filter);
    }

@Override
    protected void onPause() {
        // when the screen is about to turn off
        if (ScreenReceiver.wasScreenOn) {
            // this is the case when onPause() is called by the system due to a screen state change
            System.out.println("SCREEN TURNED OFF");

    } else {
        // this is when onPause() is called when the screen state has not changed
    }
    super.onPause();
}

@Override
protected void onResume() {
    // only when screen turns on
    if (!ScreenReceiver.wasScreenOn) {
        // this is when onResume() is called due to a screen state change
        System.out.println("SCREEN TURNED ON");
    } else {
        // this is when onResume() is called when the screen state has not changed
    }
    super.onResume();
}
}
Вы не можете сделать это со стандартным Android. Также есть много вопросов относительно этого наStackoverflow.comЧто вы ожидаете здесь, на вашем сейчас? Luksprog
Почему вы, люди, всегда думаете о неправильном использовании технологий? Я не могу понять Azhar Shaikh
Таким образом, вы можете похитить чей-то телефон? Bill
рутованное или некорневое устройство? Morrison Chang
@MorrisonChang не-root Azhar Shaikh

Ваш Ответ

6   ответов
50

за которым стоит множество комментариев.

Позвольте мне начать с перефразирования вашего вопроса. Если я правильно понимаю, вы хотели бы отключить все физические кнопки на устройстве на время вашей активности. Это включает кнопку питания, которую вы обнаруживаете, обращаясь сACTION_SCREEN_OFF намерение. Ваш текущий (успешный) обходной путь для этого сценария заключается в трансляцииACTION_SCREEN_ONвозвращать экран к жизни, когда он выключен, при условии, что хост реализует это правильно.

Теперь вы хотели бы пройти лишнюю милю, сделав это действие ненужным, если (и только если) вы сможете поймать и обработатьACTION_SCREEN_OFF прежде чем он будет отправлен в систему. Возможно ли это, и если да, то как?

Это вызывает некоторое обсуждение. Короткая версия, однако, проста:this is not possible, without custom modification to your firmware or the core of the Android operating system, for a limited number of devices.

Система Android, насколько это задокументировано, определяет это какbroadcast action, Послешаблон публикации-подписки о распространении сообщения, это сообщение будет уведомлять все заинтересованные стороны об этом действии. Потому что это сообщение отправлено системой, потому что стек сообщений управляется системой, и потому что сообщение такжеreceived системой ваш код просто не введен в нужном месте, чтобы заблокировать прием этого сообщения.

Кроме того, для некоторых устройств это будетphysical переключатель, который не имеет никакого программного прерывания. В лучшем случае система Android может рассчитывать на событие, когда это произойдет, именно поэтому это широковещательное сообщение является чем-то особенным в стеке услуг. Насколько мне известно, и, основываясь на редкой документации по этому сценарию, именно поэтому он не является готовой поддерживаемой функцией, прежде чем мы рассмотрим любой из возможных векторов злоупотребления.

Ваш лучший выход на самом деле гораздо проще, если у вас есть возможность изменить физическое оборудование для рассматриваемого устройства: ограничить доступ, отключить или иным образом отключить кнопку физического питания. Во многих сценариях это нежелательно, но это работает в ситуациях, когда ваше устройство Android используется, например, в качестве точки продажи или машины общего пользования. Если это неосуществимо, наложение физических ограничений на доступ к кнопке питания может быть единственным, что требуется для обработки оставшихся случаев (например, точечных попыток переключения экрана) путем отправкиACTION_SCREEN_ON.

Просто помните, что эта стратегия не является надежной. Делайте это грамотно и документируйте процедуру хорошо, чтобы вы не стали кормом для следующего2600 экспонатов & # xE9;.

Желаем удачи в вашем приложении.

Я не знаю устройства, котороеdoesn't используйте физический выключатель для питания по крайней мере.
Дополнительный балл за улучшение этого ответа: есть ли у кого-нибудь хороший список устройств, работающих под управлением Android и использующих переключатели физических устройств для состояния экрана и питания? Учитывая природу Android с открытым исходным кодом, ясно,why это дизайнерское решение, но я не могу найти хороший, текущий список примеров, чтобы привести здесь.
Я тоже согласился, что это невозможно без каких-либо модификаций при прошивке. @MrGomez Во-первых, позвольте мне рассказать вам раньше, что я узнаю,you cant override the HOME button но все же я что-то сделал с этим (ссылка вставлена выше), так что я хочу то же самоеPower кнопка. Ожидая некоторую неприятную идею. Я не жду ответа до сих пор, но +1 для вас. Azhar Shaikh
@hotveryspicy Согласен. Интересной особенностью кнопки «Домой» на Android является то, что она не гарантированно является физической и, действительно, она не имеет такой же связи состояния питания. Таким образом, на уровне операционной системы его можно отключить с помощью хитрых обходных путей (т. Е. Потерянных тем,TYPE_KEYGUARDили, в некоторых случаях, просто притворяясь, что у системы есть физический ключ, когда он этого не делает. Однако когда у вас есть что-то, что изменяет состояние питания в аппаратном обеспечении, это становится более сложным, граничащим с решениями, которые еще более запутаны (если это имеет смысл). Спасибо за вашу поддержку, в любом случае. :)
@MrGomez Убежден, это ответ на данный момент, ноI попытаюсь. большое спасибо. Azhar Shaikh
1

что это слишком поздно, но может быть полезно для других разработчиков в будущем. ПротестированоAndroid N . Reference from 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);
        }
    }
onWindowFocusChanged не вызывается при нажатии кнопки питания.
2

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

Вот что я пробовал,

package com.easylogs.app;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;

public class CloseSystemDialogsIntentReceiver extends BroadcastReceiver {
    public void onReceive(final Context context, final Intent intent) {
        Log.i("HERE", "------------------------------------HERE");
        Toast.makeText(context, "OFFFFFFFFFFFFFFFF",Toast.LENGTH_LONG).show();
    }
}

и декларация в Манифесте как,

    <receiver android:name="CloseSystemDialogsIntentReceiver">
    <intent-filter>
            <action android:name="android.intent.action.CLOSE_SYSTEM_DIALOGS" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </receiver>
Я могу получить событие Power long click вonDispatchKey(), но я хочу поймать короткое нажатие клавиши и переопределить как-то может иллюзия. Azhar Shaikh
2

@Override
public boolean dispatchKeyEvent(KeyEvent event) {
    if (event.getKeyCode() == KeyEvent.KEYCODE_POWER) {

        return true;
    }

    return super.dispatchKeyEvent(event);
}

где мы можем обработать событие Power Key. Также посмотрите на этоССЫЛКА НА САЙТ который обработал событие нажатия кнопки питания.

все еще не то решение, которое я хочу, я тоже получаю событие SCREEN_OFF, но я не хочу, чтобы экран выключался. +1 еще Azhar Shaikh
попробую еще раз ...
Вы смотрели на ссылку?
Вы пробовали самостоятельно ?, если это так просто, то это не будет спрашиваться здесь. Azhar Shaikh
8

@Override
public boolean dispatchKeyEvent(KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_POWER) {
                Log.i("", "Dispath event power");
                Intent closeDialog = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
                sendBroadcast(closeDialog);
                return true;
        }

        return super.dispatchKeyEvent(event);
}

Что оно делает:

Всякий раз, когда пользователь нажимает кнопку питания. Мы отменяем диалог еще до того, как его увидим !! :) Это работает для меня .. (проверено на note2)

Я могу подтвердить, что это работает на моем Moto G, работающем на Android 4.4.4
@ rup35h на какой версии андроида вы работаете?
@amalBit я использую 5.1
@amalBit я использую этот код в Activity. Но когда я нажимаю кнопку питания, я все еще вижу диалоговое окно.
Привет venkat .. Вышеупомянутый код работает для вас ... Я попробовал это в Moto X, но экран гаснет.
4

(1) Создайте класс получателя:

public class ScreenReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        switch (action) {
            case Intent.ACTION_SCREEN_OFF:
                BaseActivity.unlockScreen();
                break;

            case Intent.ACTION_SCREEN_ON:
                // and do whatever you need to do here
                BaseActivity.clearScreen();
        }
    }
}

(2) Два метода, которые вызываются выше, выглядят так:

public static void unlockScreen () {
    if (current == null) return;

    Log.i( Constants.TAG, "Turning on screen ... " );

    Window window = current.getWindow();
    window.addFlags( WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD );
    window.addFlags( WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED );
    window.addFlags( WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON   );
}

public static void clearScreen () {
    if (current == null) return;

    Log.i( Constants.TAG, "Clearing screen flag when on ... " );

    Window window = current.getWindow();
    window.clearFlags( WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD );
    window.clearFlags( WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED );
    window.clearFlags( WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON   );
}

private static BaseActivity current;

@Override
protected void onResume () {
    current = this;
}

(3) В методе onCreate () основного класса активности зарегистрируйте получателя:

    IntentFilter filter = new IntentFilter( Intent.ACTION_SCREEN_ON );
    filter.addAction( Intent.ACTION_SCREEN_OFF );
    registerReceiver(new ScreenReceiver(), filter);
не работает, разблокировка экрана выполняется, но экран по-прежнему выключается.
хорошее решение :)

Похожие вопросы