Android 像主页按钮一样覆盖电源按钮

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10077905/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 02:25:05  来源:igfitidea点击:

Override Power button just like Home button

androidoverridinghome-button

提问by Mohammed Azharuddin Shaikh

Well, I am doing something in which I want to disable all hard buttons of the device.

好吧,我正在做一些我想禁用设备的所有硬按钮的事情。

Hard buttons like Power, Home, Volume up, Volume down, Search, Back.

硬按钮,如电源、主页、音量增大、音量减小、搜索、返回。

I have successfully overridden almost all buttons hereexcept Power.

我已经成功覆盖几乎所有的按钮,在这里除了电源。

So I just want you people to see and please share some ideas so that I get can away with it.

所以我只是想让你们看到并请分享一些想法,这样我就可以摆脱它。

I am getting the long pressPower keyevent in onDispatchKeyEvent(), in the same way I want to catch the short click of the same. Moreover when pressing power I also tried to stop Screen offby getting the Broadcastof SCREEN_OFFand I succeeded in receiving it but I was not able to handle it.

我在 中长按Power keyevent onDispatchKeyEvent(),以同样的方式我想捕捉相同的短按。此外压迫力时,我还试图阻止屏幕关闭通过获取BroadcastSCREEN_OFF,我成功地接受它,但我不能处理它。

Thanks.

谢谢。

Then, I had created a ReceiverScreen which receives broadcast of Screen on/off

然后,我创建了一个接收屏幕开/关广播的 ReceiverScreen

ReceiverScreen.java

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

禁用硬按钮.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();
}
}

回答by MrGomez

Phew. This is quite a contended question, with a great deal of commentary behind it.

呼。这是一个很有争议的问题,背后有很多评论。

Let me begin by rephrasing your question a bit. If I understand clearly, you'd like to disable all physical buttons on the device for the duration of your activity. This is inclusive of the power button, which you detect by handling the ACTION_SCREEN_OFFintent. Your current (successful) workaround for this scenario is to broadcast an ACTION_SCREEN_ON, kicking the screen back to life when it's turned off, provided the host implements this correctly.

让我先重新表述一下你的问题。如果我理解清楚,您希望在活动期间禁用设备上的所有物理按钮。这包括您通过处理ACTION_SCREEN_OFF意图检测到的电源按钮。您当前(成功)针对此场景的解决方法是广播ACTION_SCREEN_ON,在屏幕关闭时使屏幕恢复生机,前提是主机正确实现了这一点。

You'd now like to go the extra mile, by rendering this action unnecessary, if (and only if) you are able to catch and handle ACTION_SCREEN_OFFbefore it gets sent to the system. Is this possible, and if so, how?

如果(且仅当)您能够ACTION_SCREEN_OFF在将其发送到系统之前进行捕获和处理,您现在想要加倍努力,通过使此操作变得不必要。这是可能的,如果是,如何?

This bears some discussion. The short version, however, is simple: 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 操作系统的核心进行自定义修改,这对于数量有限的设备是不可能的。

The Android system, as far as is documented, defines this as a broadcast action. Following the publish-subscribe patternof message propagation, this message will notify all concerned parties of this action. Because this message is sent by the system, because the message stack is managed by the system, and because the message is also receivedby the system, your code simply isn't injected in the right place to block the reception of this message.

就文档而言,Android 系统将其定义为广播操作。遵循消息传播的发布订阅模式,此消息将通知所有相关方此操作。因为这条消息是由系统发送的,因为消息栈是由系统管理的,而且因为这条消息也被系统接收,所以你的代码没有注入到正确的地方来阻止这条消息的接收。

Furthermore, for some devices, this will be a physicalswitch that has no programmatic interrupt whatsoever. At best, the Android system can hope to handle for the event when it happens, which is precisely why this broadcast message is something of a special case in the service stack. To the best of my knowledge and based upon the sparse documentation on this scenario, this is why it's not an out-of-the-box, supported feature, before we consider any of the possible vectors for abuse.

此外,对于某些设备,这将是一个没有任何程序中断的物理交换机。充其量,Android 系统可以希望在事件发生时对其进行处理,这正是为什么此广播消息在服务堆栈中是特殊情况的原因。据我所知,并基于有关此场景的稀疏文档,这就是为什么在我们考虑任何可能的滥用载体之前,它不是开箱即用的受支持功能的原因。

Your best recourse is actually a much simpler one, if you have the ability to modify the physical hardware for the device in question: restrict access to, mangle, or otherwise disable the physical power button. In many scenarios this is undesirable, but this works in situations where your Android device is being used, for example, as a point-of-sale or a public service machine. If this is unworkable, placing physical restrictions on access to the power button may be all that's required, handling for the remainder of cases (for example, spot attempts to toggle the screen) by sending ACTION_SCREEN_ON.

如果您能够修改相关设备的物理硬件,那么您最好的求助方法实际上要简单得多:限制访问、破坏或以其他方式禁用物理电源按钮。在许多情况下,这是不可取的,但是这适用于您的 Android 设备被用作销售点或公共服务机器的情况。如果这是行不通的,则可能只需要对电源按钮的访问进行物理限制,通过发送ACTION_SCREEN_ON.

Just remember, this strategy isn't foolproof. Do this competently and document the procedure well, lest you become fodder for the next 2600 exposé.

请记住,这种策略并非万无一失。称职地执行此操作并记录该过程,以免您成为下一次2600 次曝光的素材

Best of luck with your application.

祝您申请顺利。

回答by amalBit

On the contrary to all the answers .. Check this out:

与所有答案相反.. 看看这个:



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

What it does:

它能做什么:

Whenever the user presses the power button. We cancel the Dialog before its even seen!! :) . This works for me.. (Tested on note2)

每当用户按下电源按钮时。我们甚至在它看到之前就取消了对话框!!:) 。这对我有用..(在note2上测试)

回答by Sileria

Here is what I have done:

这是我所做的:

(1) Create a receiver class:

(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) The two methods that are called above looked like this:

(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) In the main activity class onCreate() method register the receiver:

(3) 在主活动类的 onCreate() 方法中注册接收者:

    IntentFilter filter = new IntentFilter( Intent.ACTION_SCREEN_ON );
    filter.addAction( Intent.ACTION_SCREEN_OFF );
    registerReceiver(new ScreenReceiver(), filter);

回答by Radhey

I know its too late ,but may be helpful for other developers in future. Tested over Android N. Reference from https://stackoverflow.com/a/15828592/1065357

我知道为时已晚,但将来可能对其他开发人员有所帮助。在Android N 上测试。参考来自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);
        }
    }

回答by MKJParekh

You can get to know about the Power Button press, but I dont think you will get to override it and you will be able to dismiss the dialog for power off and show something else.

您可以了解电源按钮按下,但我认为您不会覆盖它,您将能够关闭电源关闭对话框并显示其他内容。

Here is what I have tried,

这是我尝试过的,

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

and declaration in Manifest as,

并在 Manifest 中声明为,

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

回答by Shankar Agarwal

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

        return true;
    }

    return super.dispatchKeyEvent(event);
}

have you tried the above code where we can handle power key event. Also have a look at this LINKwhich has handled power button pressed event.

您是否尝试过上面的代码,我们可以在其中处理电源键事件。也看看这个LINK,它处理了电源按钮按下事件。

回答by B.shruti

If someone is looking for a solution to develop your app into kiosk mode/COSU(Corporate Owned Single Use application)where you need to disable various hardware buttons then please follow the below link -

如果有人正在寻找将您的应用程序开发为自助服务终端模式/COSU(企业拥有的单一用途应用程序)的解决方案,您需要禁用各种硬件按钮,请点击以下链接 -

https://www.andreasschrade.com/2015/02/16/android-tutorial-how-to-create-a-kiosk-mode-in-android/

https://www.andreasschrade.com/2015/02/16/android-tutorial-how-to-create-a-kiosk-mode-in-android/