【问题标题】:ADB Accessibility Focus Change亚行可访问性重点变更
【发布时间】:2021-06-21 16:48:47
【问题描述】:

我想知道如何在 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 滑动不起作用)才能改变可访问性焦点。有没有办法通过可访问性来做到这一点,只是下一个和上一个动作?

我找到了这个article by Google

导航

  • 移至下一项:Alt + 右箭头 注意:在连续阅读模式下,此快捷方式可快进阅读文本。
  • 移至上一项:Alt + 左箭头 注意:在连续阅读模式下,此快捷方式可以倒回文本。

这意味着我只需要一次发送多个按键,对吗?我试过了,based on another SO answer:

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实际上是键盘设备,但我还是想尝试一下)

【问题讨论】:

    标签: android accessibility talkback


    【解决方案1】:

    我在这里的回答将尽可能简洁。我的完整代码可在 GitHub 上找到。

    据我所知,开发人员无法通过 ADB 执行可访问性操作,他们必须创建一个 Accessibility service 以便 act on behalf of an Accessibility user 并创建一个 Broadcast Receiver 以便它可以通过 ADB 获取输入.这是答案的三分之二,需要多一个组件,因为开发人员无法通过 ADB 激活无障碍服务!这必须手动完成每次切换可访问性或通过accessibility shortcuts - 其中只能有一个。 编辑我认为这一点是好吧:)

    无障碍服务

    开发者文档提供了Accessibility Service 的机制:

    无障碍服务是一种应用程序,它提供用户界面增强功能以​​帮助残障用户或暂时无法与设备完全交互的用户。例如,正在开车、照顾幼儿或参加非常吵闹的聚会的用户可能需要额外的或替代的界面反馈。

    我按照Google Codelab 构建了一个可以对用户执行操作的服务。这是服务中的一个 sn-p,用于左右滑动(用户导航):

        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)
        }
    

    广播接收器。

    需要注意的是,Receiver是在服务启用时注册的:

        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 启动服务:

    感谢this comment

    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
    

    辅助功能快捷方式

    ** 编辑:不再需要,但无论如何我都会把它留在这里 **

    可能最烦人的事情是每次切换可访问性时,服务都会关闭。所以我在按下 VOLUME_UP 和 VOLUME_DOWN 键的情况下添加了我的service as a shortcutThanks to this question.

      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"
    

    我已经有一个 toggling accessibility on/off 的脚本,所以我只是在此基础上添加了这个脚本,并且每次都运行我的服务。

    编辑 2

    我在AOSP 上提出了一个问题,即开发人员需要编写“滑动服务”而不是“导航服务”。这是有问题的,因为可以修改手势,然后我的系统将无法按预期运行。相反,我应该能够调用我想要执行的特定操作NAVIGATE TO NEXT ELEMENTNAVIGATE TO PREVIOUS ELEMENT,而不是“向右滑动”和“向左滑动”——阅读了 WCAG 指南后,我不认为这违反了原则。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-17
      • 2011-04-03
      • 1970-01-01
      • 2018-03-07
      • 1970-01-01
      • 2018-11-18
      相关资源
      最近更新 更多