好吧,我正在做一些我想要禁用设备的所有硬按钮的事情。
电源,家庭,音量增大,音量减小,搜索,返回等硬按钮。
我已成功覆盖除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;
}
}
}
答案 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/