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

Flutter中点击按钮唤起安卓系统电源菜单的实现方法

在Flutter中唤起安卓电源菜单的实现方式

首先明确:安卓系统的电源菜单属于系统级控制功能,第三方应用默认无直接调用权限,可通过以下两种方式尝试实现:

方式一:调用系统Intent(需系统级权限,局限性大)

安卓原生提供了模拟按键事件的能力,但唤起电源菜单需要android.permission.SYSTEM_ALERT_WINDOW和android.permission.INJECT_EVENTS这类系统级权限,普通应用几乎无法获取,仅适用于系统应用或ROOT设备。

实现步骤:

  1. 在安卓项目的AndroidManifest.xml中添加权限声明:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.INJECT_EVENTS" />
  1. 通过Flutter的MethodChannel调用原生代码:
    Flutter端代码:
import 'package:flutter/services.dart';

class PowerMenuHandler {
  static const _channel = MethodChannel('power_menu_channel');

  static Future<void> showPowerMenu() async {
    try {
      await _channel.invokeMethod('triggerPowerMenu');
    } on PlatformException catch (e) {
      print("唤起失败: ${e.message}");
    }
  }
}

安卓原生端(MainActivity.kt):

import android.os.SystemClock
import android.view.InputDevice
import android.view.KeyEvent
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel

class MainActivity : FlutterActivity() {
    private val CHANNEL = "power_menu_channel"

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
            if (call.method == "triggerPowerMenu") {
                // 模拟长按电源键事件
                val downEvent = KeyEvent(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(),
                    KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_POWER, 0, 0,
                    InputDevice.SOURCE_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM)
                val upEvent = KeyEvent(SystemClock.uptimeMillis() + 1000, SystemClock.uptimeMillis() + 1000,
                    KeyEvent.ACTION_UP, KeyEvent.KEYCODE_POWER, 0, 0,
                    InputDevice.SOURCE_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM)
                
                dispatchKeyEvent(downEvent)
                dispatchKeyEvent(upEvent)
                result.success(null)
            } else {
                result.notImplemented()
            }
        }
    }
}

方式二:借助安卓辅助功能(可行方案,需用户授权)

安卓辅助服务可模拟用户物理操作,是目前第三方应用唤起电源菜单的可行路径,但需要用户手动开启辅助权限。

实现步骤:

  1. 创建辅助服务类:
    在安卓项目src/main/kotlin/[你的包名]/下新建PowerMenuAccessibilityService.kt:
import android.accessibilityservice.AccessibilityService
import android.view.accessibility.AccessibilityEvent

class PowerMenuAccessibilityService : AccessibilityService() {
    override fun onAccessibilityEvent(event: AccessibilityEvent?) {}

    override fun onInterrupt() {}

    fun showPowerMenu() {
        // 调用系统全局动作唤起电源菜单
        performGlobalAction(GLOBAL_ACTION_POWER_DIALOG)
    }
}
  1. 在AndroidManifest.xml中注册辅助服务:
<service
    android:name=".PowerMenuAccessibilityService"
    android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
    <intent-filter>
        <action android:name="android.accessibilityservice.AccessibilityService" />
    </intent-filter>
    <meta-data
        android:name="android.accessibilityservice"
        android:resource="@xml/accessibility_config" />
</service>
  1. 创建辅助服务配置文件res/xml/accessibility_config.xml:
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeAllMask"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:accessibilityFlags="flagDefault"
    android:canPerformGestures="true"
    android:description="@string/accessibility_desc" />
  1. 在strings.xml中添加服务描述:
<string name="accessibility_desc">此服务用于唤起系统电源菜单</string>
  1. Flutter端交互代码:
import 'package:flutter/services.dart';
import 'package:android_intent_plus/android_intent.dart';

class PowerMenuHelper {
  static const _channel = MethodChannel('power_menu_channel');

  // 引导用户打开辅助功能设置页
  static Future<void> requestAccessibilityPerm() async {
    final intent = AndroidIntent(
      action: 'android.settings.ACCESSIBILITY_SETTINGS',
    );
    await intent.launch();
  }

  // 唤起电源菜单
  static Future<void> showPowerMenu() async {
    try {
      await _channel.invokeMethod('showPowerMenu');
    } on PlatformException catch (e) {
      print("唤起失败: ${e.message}");
    }
  }
}
  1. 安卓原生端权限校验与调用:
import android.content.ComponentName
import android.provider.Settings
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel

class MainActivity : FlutterActivity() {
    private val CHANNEL = "power_menu_channel"

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
            when (call.method) {
                "showPowerMenu" -> {
                    val serviceComponent = ComponentName(this, PowerMenuAccessibilityService::class.java)
                    val isAccessibilityEnabled = Settings.Secure.getInt(
                        contentResolver,
                        Settings.Secure.ACCESSIBILITY_ENABLED, 0
                    ) == 1
                    val enabledServices = Settings.Secure.getString(
                        contentResolver,
                        Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES
                    )
                    val isOurServiceEnabled = enabledServices?.contains(serviceComponent.flattenToString()) == true

                    if (isAccessibilityEnabled && isOurServiceEnabled) {
                        val service = PowerMenuAccessibilityService()
                        service.showPowerMenu()
                        result.success(null)
                    } else {
                        result.error("PERMISSION_DENIED", "请先开启辅助功能权限", null)
                    }
                }
                else -> result.notImplemented()
            }
        }
    }
}

总结

  • 方式一依赖系统级权限,普通应用基本无法使用,仅适合特殊场景。
  • 方式二是当前可行方案,但需要用户手动开启辅助权限,存在一定操作门槛。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 00:22:45