You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用厂商签名系统应用在非Root设备禁用关机重启及关机弹窗?

拦截长按电源键关机对话框的实现方案(系统签名App专属)

作为资深Android系统开发者,我很清楚你这个需求的可行性——因为你的App是厂商密钥签名的系统级应用,这就拥有了普通第三方App没有的权限和系统API访问能力,完全能实现拦截长按电源键弹出的关机对话框,甚至按需限制电源键功能。下面给你两种靠谱的实现思路:

方案一:从源头拦截电源键长按事件,直接阻止对话框弹出

这种方式是最彻底的,直接把电源键长按的动作拦截下来,不让系统触发关机对话框:

  1. 先声明必要的系统权限
    这些权限只有系统签名的App才能申请通过,放心加在AndroidManifest.xml里:
<uses-permission android:name="android.permission.INJECT_EVENTS" />
<uses-permission android:name="android.permission.DEVICE_POWER" />
  1. 写个后台服务监听按键事件
    实现一个后台服务,通过系统的InputManager注册输入事件监听器,专门拦截电源键的长按动作:
public class PowerKeyInterceptorService extends Service {
    private InputManager mInputManager;
    private InputEventListener mInputEventListener;

    @Override
    public void onCreate() {
        super.onCreate();
        mInputManager = (InputManager) getSystemService(INPUT_SERVICE);
        mInputEventListener = new InputEventListener();
        // 把监听器优先级设到最高,确保咱的代码先于系统处理事件
        mInputManager.registerInputEventListener(mInputEventListener, InputManager.INPUT_EVENT_MODE_WAIT_FOR_FINISH);
    }

    private class InputEventListener implements InputManager.InputEventListener {
        @Override
        public void onInputEvent(InputEvent event) {
            if (event instanceof KeyEvent) {
                KeyEvent keyEvent = (KeyEvent) event;
                // 精准拦截电源键的长按事件
                if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_POWER && keyEvent.getAction() == KeyEvent.ACTION_LONG_PRESS) {
                    // 把这个事件标记为已消费,系统就不会继续处理了
                    event.setFlags(event.getFlags() | InputEvent.FLAG_CONSUMED);
                }
            }
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // 记得注销监听器,避免内存泄漏
        if (mInputManager != null && mInputEventListener != null) {
            mInputManager.unregisterInputEventListener(mInputEventListener);
        }
    }
}
  1. 启动这个后台服务
    在App启动的时候把服务拉起来,确保一直监听:
startService(new Intent(this, PowerKeyInterceptorService.class));

方案二:等对话框弹出后,直接强制关闭它

如果你不想完全拦截电源键长按,只是不想让关机对话框显示出来,也可以用这种方式:

  1. 声明权限并注册广播接收器
    同样在AndroidManifest.xml里加权限和接收器,把优先级设到最高,确保咱的接收器先收到广播:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<receiver android:name=".ShutdownDialogReceiver" android:enabled="true" android:exported="true">
    <intent-filter android:priority="1000">
        <action android:name="android.intent.action.CLOSE_SYSTEM_DIALOGS" />
        <action android:name="android.intent.action.ACTION_SHUTDOWN" />
    </intent-filter>
</receiver>
  1. 实现广播接收器的逻辑
    收到广播后,直接通过系统窗口管理器找到关机对话框并关闭:
public class ShutdownDialogReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action) || Intent.ACTION_SHUTDOWN.equals(action)) {
            // 作为系统App,咱能直接拿到系统窗口管理器
            WindowManager windowManager = (WindowManager) context.getSystemService(WINDOW_SERVICE);
            // 遍历系统窗口,找到关机对话框并移除
            for (WindowManager.LayoutParams params : windowManager.getWindowLayoutParams()) {
                if (params.type == WindowManager.LayoutParams.TYPE_SYSTEM_ALERT) {
                    windowManager.removeViewImmediate(params.getView());
                }
            }
            // 把广播拦截下来,不让系统继续处理
            abortBroadcast();
        }
    }
}

几个要注意的点

  • 以上方案只适用于厂商密钥签名的系统级App,普通第三方App拿不到这些权限,也碰不到系统级的事件。
  • 如果想完全禁用电源键,只要在方案一里把电源键的所有事件(短按+长按)都拦截就行。
  • 不同Android版本的系统窗口类型或者广播行为可能有点差异,建议针对你的目标版本做下适配测试。

内容的提问来源于stack exchange,提问作者fadedbee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:14:14