查看原文
其他

为了帮视障人士“看见”,阿里工程师做了哪些努力?

2018-01-31 朴文 阿里技术


阿里妹导读:中国拥有约1300万视障碍者,平均每100人就有1人每天生活在黑暗中。互联网覆盖方方面面的今天,借助智能设备,盲人获得了独立自主的机会:社交、网购、浏览新闻、听音乐… 互联网让他们可以接触到更多的事物,走出更远的路。互联网产品的无障碍体验将直接影响到盲人群体的生活质量。因此建设信息无障碍环境,帮助他们更好融入社会,显得尤为重要与迫切。


为了提供更好的信息无障碍体验,继钉钉iOS完成无障碍支持后,钉钉Android于2017年6月中旬启动无障碍改造工作。经过与合作方“深圳市信息无障碍研究会”两个多月的共同努力,不断沟通,测试,改进,目前钉钉Android无障碍支持已经达到了较好的可用性。


下面我们一起来回顾钉钉Android无障碍支持的项目过程。


无障碍支持简介

视觉存在障碍的用户无法真切的看到手机设备的屏幕内容, 因此需借助读屏软件,主要依赖听觉完成交互。目前Android设备多采用Talkback作为无障碍辅助服务。


Talkback是Android系统内置的无障碍服务,经过多个版本更新,目前有较好的体验效果。它主要通过语音、震动和其他的语音反馈让盲人用户知道目前屏幕上是什么、正在触摸什么、能够做什么。


Talkback开启后基本的操作方式:


1. 滚动:双指滑动。

2. 点击:选中view后在屏幕任意位置双击。

3:长按:选中view后,双击后按住。

4. 左滑右滑:前一项下一项


下面以已进行无障碍优化的钉钉为例,描述下无障碍支持要做的事情,清楚目的地才能够知道怎么做。以下为部分聊天场景。


       

              

为能够观察到朗读内容,上面示例打开了Talkback中开发者设置的“显示语音输出”选项。
       

我们要做的就是让View获得焦点后,让读屏软件读出最恰当的描述,让盲人用户清楚目前在什么位置, 能够做什么。

无障碍事件分发

我们从源码层次分析无障碍事件分发流程,帮助理解Android无障碍框架工作原理,以更好的进行无障碍支持:


sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);

sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);


在View.java中,我们可以看到很多类似上面sendAccessibilityEvent的方法调用。这里就是我们查看无障碍事件分发的起点。






最终调用继承AccessibilityService的读屏辅助APP的onAccessibilityEvent(AccessibilityEvent event)方法,完成无障碍提示。Talkback便是此类App,其onAccessibilityEvent 内对event进行内容解析并朗读等音频反馈。当然我们也可以继承AccessibilityService开发自己的无障碍辅助APP。



上图从方法调用顺序展示无障碍事件分发流程。


无障碍工作清单

1. contentDescription标记用户界面元素,最简单也是最有效的

        

这是无障碍支持中最简单的工作, 也是最主要的工作, 依赖其就能够完成90%的无障碍支持工作。



TalkBack以View组件的四个属性作为读屏内容:contentDescription、组件类型(图片、按钮等),状态(例如checkBox的选中状态),后三者由Android框架自动支持,contentDescription属性不会显示在屏幕上,当用户导航到这些控件时, 描述文本将会被读出。对于ImageView,ImageButton,CheckBox,contentDescription是必须要添加的属性。TextView,Button等含有text属性的元素,可选择不添加, Android框架将以其text属性作为读屏内容。contentDescription需保证简洁明确,切忌冗长,较长的描述文本将影响盲人用户的操作效率。

2. 启动焦点导航,启动视图焦点和控制焦点顺序


盲人用户无法准确辩知当前界面可操作元素位置,相对与触摸操作, 他们更多通过左右滑动获取可操作元素焦点。因此无障碍中的另外一个主要工作是控制元素焦点。
     

当用户界面元素的 android:focusable 属性设置为 true 时,允许用户使用定向控制聚焦元素并与之交互。 Android 框架提供的用户界面控件默认可聚焦同时Android 也提供了 API 让开发者决定用户界面控件是否可聚焦与请求给控件赋予焦点。无障碍支持中需保证每个操作做元素均是可聚焦的,同时对无障碍用户存在干扰的元素应设置为不可获取焦点。
     

 焦点顺序是以一种在某一特定方向上寻找相邻元素的算法为基础的。在某些情况下,默认的算法可能不匹配开发者定义的顺序,或可能对于用户不符合逻辑。在这些情况下,可以在布局文件中使用android:nextFocusxxx属性明确地覆盖焦点顺序。


3. 自定义视图

  

当Android框架提供的无障碍事件无法满足我们的需求时, 例如,拖动一个进度条,我们希望把当前进度反馈给盲人用户,此时便需要自定义视图。通过上面对无障碍事件的分发过程的源码分析,也可大致清楚自定义视图在无障碍支持时可以做的几个事情。此处不再深入展开,感兴趣的读者看参阅以下文档的自定义视图章节。

http://www.siaa.org.cn/androidguideline.pdf 

    

sendAccessibilityEvent() // 适当时机发送无障碍事件

onInitializeAccessibilityEvent()  // 初始化无障碍事件

dispatchPopulateAccessibilityEvent()// 对无障碍事件重写

onInitializeAccessibilityNodeInfo() //该方法填充 AccessibilityNodeInfo对象,无障碍服务该对象获得更多的上下文,为用户提供合适的反馈。

  
4. 自定义无障碍服务

     

Android提供了标准的无障碍服务,包括Talkback,开发人员也可以创建和发布自己的无障碍服务。我们甚至可以利用无障碍服务代表用户操作,完成诸多黑科技功能。我们以google提供的sample demo为例。


1)无障碍服务声明,像其他Service服务一样,需要在AndroidManifest.xml中声明该服务。



2)无障碍服务参数配置,可以采用代码动态设置,同时android4.0后可采用<meta-data>标签完成。


accessibilityEventTypes // 指定监
听的时间类型,例如点击,窗口变化等 packageNames // 指定该无障碍
服务可以处理的应用包名, 多个应用可用“,
”分隔 canRetrieveWindowContent // 是否可以
获取到窗口内容



3)无障碍服务方法,自定义无障碍服务需要继承自AccessibilityService,并重写该类onAccessibilityEvent, onInterrupt等方法。通过AccessibilityEvent可获得View上下文等信息, 甚至可代表用户操作。 “抢红包插件”等多是基于无障碍服务。



4)对获取到的AccessibilityEvent做音频或者震动反馈, 提供无障碍服务



5. 测试
      

无障碍优化非一蹴而就的事情, 特别是对如钉钉此类功能较多的应用, 会有遗漏以及处理不当的地方,同时需防止增加contentDescription属性时引进的NPE异常。因此无障碍优化过程中, 测试与回归是必须的环节,也可以借助Espresso或Robolectric实现自动化测试。测试方法与测试内容参照:


https://developer.android.com/training/accessibility/testing.html


另外,我们也可以联系专业的无障碍团队, 帮助验收测试, 钉钉无障碍优化过程中, 深圳无障碍信息研究会给予了巨大的帮助和支持,非常感谢。


PS:如果你希望了解盲人工程师的工作,可阅读这篇历史文章:

对着黑屏,背代码编程,他的终极目标是让自己失业


特殊情况和注意事项

  • 条件允许的情况下, 使用Android内置的界面控件,这些控件默认提供了无障碍支持。钉钉存在部分以ImageView代替CheckBox的使用方式,该方式在UI上无区别,但是在无障碍交互方式下,盲人将无法正确获知当前View的操作方式和选中状态。不应直接采用ImageView完成CheckBox的功能。

  • EditView,因该使用hint代替contentDescription。文本框为空时,hint能提示盲人用户输入什么内容, 当文本框非空时,talkback将会读出当前输入文本的内容,而非hint。如设置了contentDescription,将会失去此体验。

  • 小控件组,如果控件比推荐的触摸尺寸小,可以考虑使用ViewGroup将这些控件组合起来,并使用 android:contentDescription为该组合提供内容描述。以增大可点击区域,减少无效焦点。

  • 有功能改变的控件,如果用户在正常使用应用的过程中,应用中的按钮或其他控件的功能会发生改变(例如,一个按钮从播放变为暂停),需对按钮的 android:contentDescription 做出相应改变。

  • 相关联控件,提供独立功能的一组控件,例如日期选择器 (DatePicker),当用户与相关联控件中的个别控件交互的时候,提供有效的音频反馈。

  • 补充无障碍音频反馈,例如,开发者想要把应用程序执行的操作告知用户,如书籍自动翻页功能,需使用announceForAccessibility(CharSequence)方法让无障碍服务为用户读出该信息。

  • 无障碍中contentDescription属性是最简单而有效的, 务须保证简介准确。

  • 在创建布局前,复查和遵守设计指南中提供的无障碍方案。https://material.io/guidelines/usability/accessibility.html#accessibility-principles


钉钉Android无障碍进展

       

为提供更好的信息无障碍体验,让视障用户能够尽可能的像正常用户一样使用钉钉,继钉钉iOS完成无障碍支持,钉钉Android于2017年6月中旬启动无障碍改造工作。经过与合作方“深圳市信息无障碍研究会”两个多月的共同努力,不断沟通,测试,改进,目前钉钉Android无障碍支持已经达到了较好的可用性。目前浙江盲人学校等组织已在使用。我们也建立了无障碍绿色通道,以第一时间收到用户反馈的无障碍问题,并及时作出处理。
   

“在移动互联网时代,我们已经很难想象离开网络该如何生活,对于视障者来说,无障碍化程序能够帮助他们打开一个全新的世界”。钉钉正在推进国际化,无障碍支持将帮助更多的国内外视障用户,让钉钉国际化版本呈现出更高的质量。


钉钉将持续推进无障碍工作,目前PC端的无障碍改造已在开发中,钉钉Android与钉钉iOS也在后续的迭代中将无障碍支持常态化,不断优化无障碍体验,带给视障用户更易用,更好用的上手体验,让钉钉帮助到越来越多的人... ...

后记


无障碍优化是需要坚持做的事情,希望大家一起努力,帮助视障群体通过互联网更好的融入社会。如果你有更好的无障碍优化方案,欢迎在留言区一起交流讨论。


如果对钉钉团队感兴趣,也可以发送简历给我们:dujie.dj@alibaba-inc.com, 期待你的加入~


参考资料

http://www.siaa.org.cn/androidguideline.pdf
http://informationaccessibilityassociation.github.io/androidAccessibility/services.htm
http://www.jianshu.com/p/4cd8c109cdfb
https://github.com/appium/android-apidemos/blob/master/src/io/appium/android/apis/accessibility/ClockBackService.java
https://darkness463.github.io/2017/04/17/accessibility-event 
http://informationaccessibilityassociation.github.io/androidAccessibility/checklist.htm




你可能还喜欢

点击下方图片即可阅读



免费下载!

《九年双11:互联网技术超级工程》



AI小编问世:

阿里智能写手核心技术首次公开!



前端工程师的未来在哪里?



关注「阿里技术」

把握前沿技术脉搏

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存