38

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

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

我已经成功地覆盖了除了电源之外的几乎所有按钮

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

我得到了长按Power keyevent in onDispatchKeyEvent(),就像我想抓住它的短按一样。此外,当按下电源时,我还尝试通过获取of来停止屏幕关闭,并且我成功接收了它,但我无法处理它。BroadcastSCREEN_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();
}
}
4

7 回答 7

55

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

让我先稍微改一下你的问题。如果我理解清楚,您希望在活动期间禁用设备上的所有物理按钮。这包括电源按钮,您可以通过处理ACTION_SCREEN_OFF意图来检测它。对于这种情况,您当前(成功的)解决方法是广播一个ACTION_SCREEN_ON,当它关闭时将屏幕踢回生活,前提是主机正确实现了这一点。

如果(且仅当)您能够ACTION_SCREEN_OFF在它被发送到系统之前捕获并处理它,您现在希望通过使该操作变得不必要来加倍努力。这可能吗?如果可以,怎么做?

这值得商榷。然而,简短的版本很简单:如果不对您的固件或 Android 操作系统的核心进行自定义修改,这对于有限数量的设备是不可能的。

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

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

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

请记住,这种策略并非万无一失。做好这件事并做好记录程序,以免你成为下一个2600 曝光的素材。

祝你的申请好运。

于 2012-04-12T05:42:30.100 回答
11

与所有答案相反..检查一下:


@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上测试)

于 2014-08-13T09:29:28.320 回答
5

这是我所做的:

(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)在主Activity类的onCreate()方法中注册receiver:

    IntentFilter filter = new IntentFilter( Intent.ACTION_SCREEN_ON );
    filter.addAction( Intent.ACTION_SCREEN_OFF );
    registerReceiver(new ScreenReceiver(), filter);
于 2015-08-27T17:55:34.143 回答
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>
于 2012-04-12T09:09:17.970 回答
2
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
    if (event.getKeyCode() == KeyEvent.KEYCODE_POWER) {

        return true;
    }

    return super.dispatchKeyEvent(event);
}

您是否尝试过上面的代码,我们可以在其中处理电源键事件。另请查看已处理电源按钮按下事件的此LINK 。

于 2012-04-15T11:20:44.703 回答
2

我知道为时已晚,但将来可能对其他开发人员有所帮助。通过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);
        }
    }
于 2017-05-03T06:41:33.200 回答
0

如果有人正在寻找将您的应用程序开发为信息亭模式/COSU(企业拥有的一次性应用程序)的解决方案,您需要禁用各种硬件按钮,请点击以下链接 -

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

于 2019-05-22T08:03:53.650 回答