Flutter中如何检测窗口浮层下方的文本?(dash bubble场景)
悬浮窗下方文本检测与操作实现指导
1. 先搞定必要权限
- 必须申请
ACCESSIBILITY_SERVICE无障碍权限,这是Android允许读取其他APP界面内容的唯一合法途径,普通APP直接读其他APP内容会被系统拦截。 - 另外确认悬浮窗权限
SYSTEM_ALERT_WINDOW已经开启(Dash Bubble一般会帮你处理,但最好在代码里做个检查)。
2. 写个无障碍服务核心逻辑
- 继承
AccessibilityService,重写onAccessibilityEvent方法,用来处理界面元素的获取。当悬浮窗移动到目标位置后,触发这个服务去抓对应坐标的文本。 - 核心代码示例(Kotlin):
override fun onAccessibilityEvent(event: AccessibilityEvent) { val rootNode = rootInActiveWindow ?: return // 拿到悬浮窗的全局坐标(假设你的悬浮窗视图是bubbleView) val rect = Rect() bubbleView.getGlobalVisibleRect(rect) // 取悬浮窗中心作为检测点,比边缘更准确 val checkX = rect.centerX() val checkY = rect.centerY() // 遍历节点树找对应位置的文本节点 val targetNode = findTextNodeAtPos(rootNode, checkX, checkY) targetNode?.text?.let { text -> // 执行复制操作,把文本存到剪贴板 val clipboard = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager val clipData = ClipData.newPlainText("CopiedText", text) clipboard.setPrimaryClip(clipData) } } // 递归遍历节点,找到坐标对应的文本节点 private fun findTextNodeAtPos(node: AccessibilityNodeInfo, x: Int, y: Int): AccessibilityNodeInfo? { if (node.contains(x, y) && node.text != null) { return node } for (i in 0 until node.childCount) { val child = node.getChild(i) ?: continue val result = findTextNodeAtPos(child, x, y) if (result != null) return result } return null }
3. 把悬浮窗移动和检测绑定起来
- 监听Dash Bubble的拖动事件,比如在悬浮窗的
OnTouchListener里,当用户抬手(ACTION_UP)时,通知无障碍服务去执行检测逻辑。 - 如果Dash Bubble有自带的移动完成回调,直接在回调里触发检测就行,不用自己写触摸监听。
4. 适配WhatsApp这类特定APP
- 不同APP的UI结构不一样,比如WhatsApp的聊天文本有特定的视图ID,你可以通过这个ID精准定位,避免抓到无关文本。
- 比如WhatsApp的聊天消息文本ID是
com.whatsapp:id/message_text,可以修改遍历逻辑:
private fun findTextNodeAtPos(node: AccessibilityNodeInfo, x: Int, y: Int): AccessibilityNodeInfo? { // 优先匹配WhatsApp的文本节点 if (node.viewIdResourceName == "com.whatsapp:id/message_text" && node.contains(x, y)) { return node } // 通用匹配逻辑 if (node.contains(x, y) && node.text != null) { return node } for (i in 0 until node.childCount) { val child = node.getChild(i) ?: continue val result = findTextNodeAtPos(child, x, y) if (result != null) return result } return null }
5. 优化用户体验
- 第一次启动时,引导用户去系统设置开启无障碍权限,这个权限必须手动开,没法代码自动申请。
- 悬浮窗拖动停止后,可以加个短暂的Toast提示,比如“已复制文本”,让用户知道操作成功。
内容的提问来源于stack exchange,提问作者Faizan Abbas
相关产品推荐
相关产品推荐

