ADB 辅助功能焦点变化

5

我想知道如何在Talkback打开时让ADB调整可访问性焦点。我已经尝试过:

adb shell input trackball roll 0 1
adb shell input [stylusdpad|keyboard|mouse|touchpad|gamepad|touchnavigation|joystick|touchscreen|stylus|trackball] swipe 180 780 540 780
adb shell input keyboard keyevent KEYCODE_TAB
adb shell input keyevent KEYCODE_NAVIGATE_NEXT
adb shell "input keyevent KEYCODE_ALT_LEFT & input keyevent KEYCODE_DPAD_LEFT"

我还尝试使用adb shell getevent录制事件,但未能成功回放。

但我总是必须手动滑动屏幕(即ADB滑动不起作用)才能改变无障碍焦点。是否有一种方法可以通过无障碍性来实现此功能,只需进行下一个和上一个移动?

我在Google的文章中找到了这个:

导航

  • 移动到下一项:Alt + 右箭头 注意:在连续阅读模式下,此快捷键会快速前进文本。
  • 移动到上一项:Alt + 左箭头 注意:在连续阅读模式下,此快捷键将倒带文本。

这意味着我只需要同时发送多个按键,对吗?我尝试了这个,基于另一个SO答案

device="/dev/input/event3"
ALT_KEY=57#18 #KEYCODE_ALT_LEFT
LEFT_KEY=21#37 #KEYCODE_DPAD_RIGHT
RIGHT_KEY=22#39 #KEYCODE_DPAD_RIGHT

device="/dev/input/event0"
adb shell "sendevent $device 1 $ALT_KEY 1 & sendevent $device 0 0 0 & sendevent $device 1 $RIGHT_KEY 1 & sendevent $device 0 0 0"
device="/dev/input/event1"
adb shell "sendevent $device 1 $ALT_KEY 1 & sendevent $device 0 0 0 & sendevent $device 1 $RIGHT_KEY 1 & sendevent $device 0 0 0"
device="/dev/input/event2"
adb shell "sendevent $device 1 $ALT_KEY 1 & sendevent $device 0 0 0 & sendevent $device 1 $RIGHT_KEY 1 & sendevent $device 0 0 0"
device="/dev/input/event3"
adb shell "sendevent $device 1 $ALT_KEY 1 & sendevent $device 0 0 0 & sendevent $device 1 $RIGHT_KEY 1 & sendevent $device 0 0 0"

device="/dev/input/event0"
adb shell "sendevent $device 1 $ALT_KEY 1 && sendevent $device 0 0 0 && sendevent $device 1 $RIGHT_KEY 1 && sendevent $device 0 0 0"
device="/dev/input/event1"
adb shell "sendevent $device 1 $ALT_KEY 1 && sendevent $device 0 0 0 && sendevent $device 1 $RIGHT_KEY 1 && sendevent $device 0 0 0"
device="/dev/input/event2"
adb shell "sendevent $device 1 $ALT_KEY 1 && sendevent $device 0 0 0 && sendevent $device 1 $RIGHT_KEY 1 && sendevent $device 0 0 0"
device="/dev/input/event3"
adb shell "sendevent $device 1 $ALT_KEY 1 && sendevent $device 0 0 0 && sendevent $device 1 $RIGHT_KEY 1 && sendevent $device 0 0 0"

device="/dev/input/event0"
adb shell "sendevent $device 1 $ALT_KEY 1 && sendevent $device 1 $RIGHT_KEY 1 && sendevent $device 0 0 0"
device="/dev/input/event1"
adb shell "sendevent $device 1 $ALT_KEY 1 && sendevent $device 1 $RIGHT_KEY 1 && sendevent $device 0 0 0"
device="/dev/input/event2"
adb shell "sendevent $device 1 $ALT_KEY 1 && sendevent $device 1 $RIGHT_KEY 1 && sendevent $device 0 0 0"
device="/dev/input/event3"
adb shell "sendevent $device 1 $ALT_KEY 1 && sendevent $device 1 $RIGHT_KEY 1 && sendevent $device 0 0 0"

(尽管我知道 device0 实际上是键盘设备,但我想尝试它们全部)
1个回答

2
我的回答会尽可能简洁。完整的代码可以在 GitHub 上找到。
据我所知,开发者无法通过 ADB 执行辅助功能操作,他们必须创建一个 辅助服务 以代表辅助用户进行操作,并创建一个 广播接收器 以使其能够通过 ADB 接收输入。这是三分之二的答案,需要一个更多的组件,因为开发者 无法通过 ADB 激活辅助服务!这必须手动完成每次切换辅助功能或通过 辅助快捷方式 - 其中只能有一个。 编辑 我也搞清楚了这一点 :)

辅助功能服务

开发者文档提供了一种辅助功能服务的机制:

辅助功能服务是一种应用程序,为残疾人或暂时无法完全与设备交互的用户提供用户界面增强功能。例如,正在驾驶、照顾幼儿或参加非常嘈杂的派对的用户可能需要额外或替代的界面反馈。

我按照Google Codelab的指导构建了一个可以代表用户执行操作的服务。以下是该服务的一部分代码,用于左右滑动(用户导航):

    fun swipeHorizontal(leftToRight: Boolean) {
        val swipePath = Path()
        if (leftToRight) {
            swipePath.moveTo(halfWidth - quarterWidth, halfHeight)
            swipePath.lineTo(halfWidth + quarterWidth, halfHeight)
        } else {
            swipePath.moveTo(halfWidth + quarterWidth, halfHeight)
            swipePath.lineTo(halfWidth - quarterWidth, halfHeight)
        }
        val gestureBuilder = GestureDescription.Builder()
        gestureBuilder.addStroke(StrokeDescription(swipePath, 0, 500))
        dispatchGesture(gestureBuilder.build(), GestureResultCallback(baseContext), null)
    }

广播接收器。
需要注意的是,在启用服务时,接收器将被注册:
    override fun onServiceConnected() {
        IntentFilter().apply {
            addAction(ACCESSIBILITY_CONTROL_BROADCAST_ACTION)

            priority = 100

            registerReceiver(accessibilityActionReceiver, this)           
        }
   // REMEMBER TO DEREGISTER!

然后接收器可以响应意图并调用服务:
    override fun onReceive(context: Context?, intent: Intent?) {
        require(intent != null) { "Intent is required" }
        val serviceReference = //get a reference to the service somehow

        intent.getStringExtra(ACCESSIBILITY_ACTION)?.let {
            serviceReference.apply {
                when (it) {
                    ACTION_NEXT -> swipeHorizontal(true)
                    ACTION_PREV -> swipeHorizontal(false)
                    //...

在adb上的示例用法:

adb shell am broadcast -a com.balsdon.talkback.accessibility -e ACTION "ACTION_PREV"

编辑
通过adb启动服务:
感谢这条评论
TALKBACK="com.google.android.marvin.talkback/com.google.android.marvin.talkback.TalkBackService"
ALLYDEV="com.balsdon.accessibilityBroadcastService/.AccessibilityBroadcastService"
adb shell settings put secure enabled_accessibility_services $TALKBACK:$ALLYDEV

无障碍快捷方式

**编辑:不再需要,但我还是会把它留在这里**

可能最烦人的事情是每次切换无障碍功能时,服务都会被关闭。因此,我使用音量上下键添加了我的服务作为快捷方式感谢这个问题

  INPUT_DEVICE="/dev/input/event1" # VOLUME KEYS EVENT FILE
  VOLUME_DOWN=114 #0x0072
  VOLUME_UP=115   #0x0073
  BLANK_EVENT="sendevent $INPUT_DEVICE 0 0 0"

  INST_DN="sendevent $INPUT_DEVICE 1 $VOLUME_DOWN 1 && $BLANK_EVENT && sendevent $INPUT_DEVICE 1 $VOLUME_UP 1 && $BLANK_EVENT"
  INST_UP="sendevent $INPUT_DEVICE 1 $VOLUME_DOWN 0 && $BLANK_EVENT && sendevent $INPUT_DEVICE 1 $VOLUME_UP 0 && $BLANK_EVENT"
  adb shell "$INST_DN"
  sleep 3
  adb shell "$INST_UP"

我已经有一个用于打开/关闭辅助功能的脚本,所以我只需在其顶部添加这个,每次都能运行我的服务。 编辑2 我在AOSP上提出了一个问题,即开发人员需要编写一个“滑动服务”,而不是“导航服务”。这是有问题的,因为手势可以被修改,那么我的系统就无法按预期工作。相反,我应该能够调用我想要执行的特定操作,如“导航到下一个元素”或“导航到上一个元素”,而不是“向右滑动”和“向左滑动”——阅读WCAG指南后,我不认为这违反了原则。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接