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

Android Kotlin:如何在前台Service中检测电源按键按压状态

实现按住电源键+连续3次摇晃触发SMS发送的逻辑

要实现这个需求,核心分两步:实时监听电源按键的按压状态,然后修改摇晃检测逻辑,结合电源键状态判断是否触发SMS。以下是具体实现方案:


一、监听电源按键状态

Android系统没有直接提供监听电源键按下的广播,这里提供两种可行方案:

方案1:使用AccessibilityService(推荐,权限更友好)

这种方式不需要悬浮窗权限,仅需用户开启辅助功能权限。

  1. 创建辅助服务类
class PowerKeyAccessibilityService : AccessibilityService() {
    companion object {
        @Volatile
        var isPowerKeyPressed = false // 用volatile保证线程安全
    }

    override fun onAccessibilityEvent(event: AccessibilityEvent?) {
        event?.takeIf { it.eventType == AccessibilityEvent.TYPE_KEY_EVENT }?.let {
            val keyEvent = it.parcelableData as KeyEvent
            if (keyEvent.keyCode == KeyEvent.KEYCODE_POWER) {
                isPowerKeyPressed = keyEvent.action == KeyEvent.ACTION_DOWN
            }
        }
    }

    override fun onInterrupt() {}
}
  1. 在Manifest中注册服务
<service
    android:name=".PowerKeyAccessibilityService"
    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_service_config" />
</service>
  1. 创建辅助服务配置文件
    在res/xml目录下新建accessibility_service_config.xml:
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeKeyEvent"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:accessibilityFlags="flagDefault"
    android:canRetrieveWindowContent="true"
    android:description="@string/accessibility_desc" />
  1. 添加权限描述字符串
    在res/values/strings.xml中添加:
<string name="accessibility_desc">用于检测电源键按压状态,实现按住电源键摇晃触发SMS功能</string>
  1. 引导用户开启辅助功能
    首次启动时需要引导用户手动开启权限:
fun openAccessibilitySettings() {
    val intent = Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)
    intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
    startActivity(intent)
}

方案2:使用悬浮窗监听KeyEvent(适合不愿用辅助功能的场景)

这种方式需要SYSTEM_ALERT_WINDOW权限,Android 6.0+需用户手动授权。

  1. 创建监听电源键的透明View
class PowerKeyListenerView(context: Context) : View(context) {
    companion object {
        @Volatile
        var isPowerKeyPressed = false
    }

    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        if (keyCode == KeyEvent.KEYCODE_POWER) {
            isPowerKeyPressed = true
            return true
        }
        return super.onKeyDown(keyCode, event)
    }

    override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
        if (keyCode == KeyEvent.KEYCODE_POWER) {
            isPowerKeyPressed = false
            return true
        }
        return super.onKeyUp(keyCode, event)
    }
}
  1. 在Service中添加悬浮窗
private lateinit var powerKeyView: PowerKeyListenerView

override fun onCreate() {
    super.onCreate()
    powerKeyView = PowerKeyListenerView(this)
    val windowManager = getSystemService(WINDOW_SERVICE) as WindowManager
    val params = WindowManager.LayoutParams(
        WindowManager.LayoutParams.WRAP_CONTENT,
        WindowManager.LayoutParams.WRAP_CONTENT,
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
        } else {
            WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
        },
        WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
        PixelFormat.TRANSPARENT
    )
    windowManager.addView(powerKeyView, params)
}

override fun onDestroy() {
    super.onDestroy()
    (getSystemService(WINDOW_SERVICE) as WindowManager).removeView(powerKeyView)
}

二、修改摇晃检测逻辑

将原有的摇晃检测代码修改为:当连续3次摇晃后,先判断电源键是否处于按压状态,满足条件才触发SMS发送。

mShakeDetector!!.setOnShakeListener(object : ShakeDetector.OnShakeListener {
    @SuppressLint("MissingPermission")
    override fun onShake(count: Int) {
        if (count == 3) {
            // 根据你选择的方案,对应使用不同的状态变量
            if (PowerKeyAccessibilityService.isPowerKeyPressed) {
                vibrate()
                sendMessage() // 触发SMS发送
            } else {
                // 可选:添加提示,比如短震动告知未满足条件
                vibrate()
                // Toast.makeText(applicationContext, "请按住电源键再摇晃", Toast.LENGTH_SHORT).show()
            }
        }
    }
})

注意事项

  • 线程安全:用@Volatile修饰电源键状态变量,确保多线程下的状态同步。
  • 权限处理:辅助功能权限需要用户手动开启,悬浮窗权限在Android 10+有更严格的限制,需提前处理权限申请逻辑。
  • 耗电优化:AccessibilityService在后台运行时耗电较低,悬浮窗方案需注意避免不必要的资源占用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 14:13:20