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

能否通过Accessibility Service程序化点击蓝牙配对的Pair/Pair&Connect按钮?

解决Accessibility Service无法检测蓝牙配对对话框的问题

问题分析

你的代码无法检测到系统蓝牙配对对话框,主要原因包括:

  • Accessibility Service权限配置未覆盖系统蓝牙相关应用
  • 节点遍历仅检查一级子节点,未递归查找深层嵌套的按钮
  • 事件监听逻辑未针对性处理系统配对通知和对话框

1. 修正Accessibility Service配置

首先确保服务能访问系统蓝牙相关应用,创建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="typeWindowStateChanged|typeNotificationStateChanged"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:accessibilityFlags="flagDefault|flagIncludeNotImportantViews"
    android:canRetrieveWindowContent="true"
    android:description="@string/accessibility_service_desc"
    android:packageNames="com.android.settings,com.android.bluetooth,com.android.systemui" />

在AndroidManifest.xml中正确声明服务:

<service
    android:name=".MyAccessibilityService"
    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>

2. 修正Accessibility Service代码

以下是优化后的代码,解决节点遍历、事件过滤和按钮匹配问题:

class MyAccessibilityService : AccessibilityService() {
    companion object {
        const val TAG = "MyAccessibilityService"
        // 覆盖常见配对按钮文本(含中英文)
        private val PAIR_TRIGGERS = listOf("PAIR", "PAIR & CONNECT", "配对", "配对并连接")
    }

    override fun onAccessibilityEvent(event: AccessibilityEvent?) {
        event ?: return
        val packageName = event.packageName?.toString() ?: ""

        when (event.eventType) {
            // 处理配对对话框弹出事件
            AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED -> {
                if (packageName in listOf("com.android.settings", "com.android.bluetooth")) {
                    findAndClickPairButton(rootInActiveWindow)
                }
            }
            // 处理配对通知点击
            AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED -> {
                val notificationContent = event.text.joinToString(" ")
                if (PAIR_TRIGGERS.any { notificationContent.contains(it, ignoreCase = true) }) {
                    event.source?.performAction(AccessibilityNodeInfo.ACTION_CLICK)
                }
            }
        }
    }

    // 递归遍历所有节点查找配对按钮
    private fun findAndClickPairButton(node: AccessibilityNodeInfo?) {
        node ?: return

        // 检查当前节点是否为目标按钮
        if (node.className == "android.widget.Button" && node.isClickable && node.isEnabled) {
            val buttonText = node.text?.toString() ?: ""
            val contentDesc = node.contentDescription?.toString() ?: ""
            if (PAIR_TRIGGERS.any { 
                buttonText.equals(it, ignoreCase = true) || contentDesc.equals(it, ignoreCase = true) 
            }) {
                node.performAction(AccessibilityNodeInfo.ACTION_CLICK)
                Log.e(TAG, "已自动点击配对按钮: $buttonText")
                return
            }
        }

        // 递归遍历子节点,用完后回收避免内存泄漏
        for (i in 0 until node.childCount) {
            val childNode = node.getChild(i) ?: continue
            findAndClickPairButton(childNode)
            childNode.recycle()
        }
    }

    override fun onInterrupt() {
        Log.i(TAG, "Accessibility服务被中断")
    }
}

关键优化点

  • 递归节点遍历:覆盖深层嵌套的系统对话框按钮
  • 多包名过滤:仅处理蓝牙相关系统应用的事件,减少无效检测
  • 多文本匹配:支持中英文配对按钮文本,适配不同系统语言
  • 通知处理:自动点击配对通知,触发对话框弹出后再点击配对按钮

注意事项

  • 必须引导用户在系统设置中手动开启你的Accessibility Service权限(敏感权限无法自动授予)
  • 不同厂商的系统配对对话框布局可能存在差异,需针对性测试适配
  • 遍历节点后必须调用recycle()回收资源,避免内存泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 12:41:13