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

时间:2012-04-09 18:30:47

标签: android override home-button

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

电源,家庭,音量增大,音量减小,搜索,返回等硬按钮。

我已成功覆盖除Power之外的几乎所有按钮here

所以我只是希望你们有人看到并请分享一些想法,这样我就可以把它拿走了。

我在onDispatchKeyEvent()中获得长按电源键事件,就像我想要抓住同样的短按一样。此外,当按下电源时,我也尝试通过获取Broadcast的{​​{1}}来停止屏幕关闭,我成功接收了它,但我无法处理它。

感谢。

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

ReceiverScreen.java

SCREEN_OFF

DisableHardButton.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;
        }
    }
}

7 个答案:

答案 0 :(得分:50)

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

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

如果(并且仅当)您能够在将ACTION_SCREEN_OFF发送到系统之前捕获并处理{0}},您现在想要更加努力。这是可能的,如果是的话,怎么样?

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

据记录,Android系统将其定义为broadcast action。在publish-subscribe pattern消息传播之后,此消息将通知所有相关方此操作。因为此消息是由系统发送的,因为消息堆栈由系统管理,并且因为系统也接收消息,所以您的代码不会在正确的位置注入阻止收到这条消息。

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

如果您能够修改相关设备的物理硬件,那么您最好的办法实际上是一个更简单的方法:限制访问,修改或禁用物理电源按钮。在许多情况下,这是不可取的,但这适用于使用Android设备的情况,例如,作为销售点或公共服务机器。如果这是不可行的,则可以通过发送ACTION_SCREEN_ON来处理剩余的情况(例如,点击尝试切换屏幕),只需对物理限制就可以访问电源按钮。

请记住,这种策略并非万无一失。这样做很有效并且很好地记录了程序,以免你成为下一个2600 exposé的饲料。

祝你的申请好运。

答案 1 :(得分: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);
}

它的作用:

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

答案 2 :(得分: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);

答案 3 :(得分: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();
    }
}

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

答案 4 :(得分:2)

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

        return true;
    }

    return super.dispatchKeyEvent(event);
}

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

答案 5 :(得分:1)

我知道为时已晚,但未来可能对其他开发者有所帮助。 通过 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);
        }
    }

答案 6 :(得分:0)

如果有人正在寻找解决方案以将您的应用程序开发为 kiosk模式/ COSU(公司拥有的一次性使用应用程序),您需要在其中禁用各种硬件按钮,然后请点击以下链接-

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