Android Accessibility学习笔记
@(Android研究)[Accessibility|无障碍|辅助功能]
[TOC]
原文:
Manifest声明和权限
Accessibility服务声明
作为一个accessibility服务,你在必须在你的manifest文件的application元素中包括一个service元素。此外,在service元素中你必须也包括一个accessibility服务的intent过滤器。为了与Android 4.1及其更高版本兼容,manifest中必须请求权限,下面是一个例子:
... ... ...
Accessibility服务配置
Accessibility服务必须提供一个配置,这个配置用来指定服务处理的accessibility事件类型和关于这个服务额外的信息。accessibility服务的配置包含在一个类对象中。可以通过[setServiceInfo()](
从Android 4.0开始,你可以在你的manifest中包含一个<meta-data>
标签来引用一个配置文件,这个配置文件可以设置accessibility服务所有的可选项。下面是一个例子:
...
这个meta-data元素引用一个XML文件,这个XML文件在你的应用程序的资源目录中(<project_dir>/res/xml/accessibility_service_config.xml)。下面代码是服务配置文件的例子:
关于更多的accessibility服务配置文件的XML属性信息可以看下面链接所引用的文档:
关于在运行时动态设置配置信息请参考引用的文档。
注册Accessibility事件
有多种Accessibility事件类型,可以选择你想要处理的事件类型,如果想要处理所有的事件类型则设置"AccessibilityEvent.TYPES_ALL_MASK"标志。
事件过滤可以包含下面的标准:
- 包名:指定包名,这个包名是你想要处理哪个应用程序的accessibility事件的包名。如果不指定包名则可以处理任何应用程序的accessibility事件。这个参数可以通过设置配置文件的android:packageNames属性以逗号分隔包名或者设置AccessibilityServiceInfo.packageNames成员变量。
- 事件类型:指定你想要处理的accessibility事件的类型。这个参数可以通过设置配置文件的android:accessibilityEventTypes属性以**|**分隔类型(例如:accessibilityEventTypes="typeViewClicked|typeViewFocused"),或者设置成员变量。
当设置你的accessibility服务时,小心考虑哪个事件是你的服务能够处理,只注册那些能够处理的事件。因为用户可能同时触发超过一个accessibility服务,你的服务必须不能耗尽你不能够处理的事件。记住,其他服务可能会处理那些事件以改善用户的体验。
注意:如果多个accessibility服务提供不同的,那么Android框架会分发accessibility事件到这些accessibility服务。然而,如果两个或超过两个的服务提供同一个feedback type,则只有第一个注册的服务会接收到事件。
AccessibilityService方法
一个accessibility服务必须扩展类并且重载下面的方法。这些方法被Android系统依次调用,当服务被启动时(onServiceConnected()),在服务运行期间(onAccessibilityEvent(), onInterrupt()),到当服务关闭时(onUnbind())。
- onServiceConnected() - (可选)当成功连接到你的accessibility服务时系统调用这个方法。使用这个方法为你的服务做一次性设置,包括连接到用户反馈系统服务,如声音管理或设备振动器。如果你想在运行时设置你的服务配置或做一次性调整,可以在这个方法里调用setServiceInfo()。
- onAccessibilityEvent() - (必须)当发现一个与你的accessibility服务指定的事件过滤参数匹配的时,这个方法被系统回调。在服务的生命周期中这个方法可能会被调用多次。
- onInterrupt() - (必须)当系统想要中断你的服务提供的反馈的时这个方法被调用,通常响应用户的活动如移动焦点到一个不同的控制。在服务的生命周期中这个方法可能会被调用多次。
- onUnbind() - (可选)当系统关闭这个accessibility服务时这个方法被调用。使用这个方法做一次性的关闭操作,包括释放用户反馈服务,如声音管理或设备振动器。
关于更多如何从accessibility事件获取信息,可以参考。
获得事件详细信息
Android系统通过对象给accessibility服务提供关于用户接口交互的信息。
在Android 4.0之前和Android 4.0之后是不同的。
从Android 4.0开始你可以通过下面的调用获得事件额外的信息(对于之前的发布版本则可以通过Android支持库中的AccessibilityEventCompat获得支持):
- AccessibilityEvent.getRecordCount()和getRecord(int) - 这些方法取回对象集。
- AccessibilityEvent.getSource() - 这个方法返回对象。这个对象运行你获得引发accessibility事件的组件视图布局层级(父子组件)。这个特征运行accessibility服务调查一个事件的完整上下文。包括所有所围绕的视图和子视图的内容和状态。
重要:AccessibilityEvent调查视图层级关系的能力潜在的揭露了用户的私有信息到你的accessibility服务。由于这个原因,你的服务必须通过accessibility 文件请求访问级别,包含** canRetrieveWindowContent属性并且设置为true**。如果不在你的服务配置xml文件中包含这个设置调用getSource()会失败。
注意:Android 4.1 (API Level 16)以及更高版本中,getSource()方法以及AccessibilityNodeInfo.getChild()和getParent(),返回仅被认为对accessibility来说重要的视图对象(绘制的视图或响应用户操作)。如果你的服务需要所有的视图,可以通过设置服务的AccessibilityServiceInfo实例的flags成员变量为。
Taking Action for Users
从Android 4.0 (API Level 14)开始,accessibility服务可以代表用户行动,包括改变输入焦点,选择(启动)用户接口元素。在Android 4.1 (API Level 16)中活动范围扩大到滚动列表和与文本字段交互。Accessibility服务也可以采取全局行动,如导航到主屏幕,按返回按钮,打开通知屏幕和最近应用列表。Android 4.1也包括一个新焦点类型,Accessibilty焦点,使所有的可视元素被accessibility服务可选。
新的能力使accessibility服务的开发者能够创建非传统的导航模式如,并改善Android设备的残疾用户对他们设备的控制。
监听手势
Accessibility服务可以监听特定的手势,并代表用户的行为做出回应。这个特征在Android 4.1 (API Level 16)中添加,并且需要你的accessibility服务请求激活Explore by Touch特性。你的服务可以请求服务的AccessibilityServiceInfo实例的flags为FLAG_REQUEST_TOUCH_EXPLORATION_MODE来激活。下面是一个例子:
public class MyAccessibilityService extends AccessibilityService { @Override public void onCreate() { getServiceInfo().flags = AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE; } ...}
你请求这个特性的时候如果这个特性还没有开启,必须用户允许才能开启这个特性。当这个特性开启,你的服务通过服务的onGesture()回调方法接收accessibility手势的通知并且可以采取行动为用户作出反应。
使用accessibility行动
Accessibility可以代替用户采取行动使之与应用程序交互简单和更高效。accessibility服务执行行动的能力在Android 4.0 (API Level 14)中添加,并在Android 4.1 (API Level 16)版本中被显著的扩展。
为了代替用户采取行动,你的accessibility服务必须以接收大量应用程序的事件并且通过在中设置android:canRetrieveWindowContent为true请求权限获得应用视图的内容。当事件被你的服务接收时,它可以使用getSource()从事件中取回对象,然后你的服务可以探索视图层次,以确定发生了什么,代表用户行动使用performAction()。
public class MyAccessibilityService extends AccessibilityService { @Override public void onAccessibilityEvent(AccessibilityEvent event) { // get the source node of the event AccessibilityNodeInfo nodeInfo = event.getSource(); // Use the event and node information to determine // what action to take // take action on behalf of the user nodeInfo.performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD); // recycle the nodeInfo object nodeInfo.recycle(); } ...}
performAction()方法允许你的服务在一个应用程序中采取行动。如果你的服务需要执行一个全局的行动,如切换到主界面、按返回按钮、打开通知屏幕或最近应用列表,则使用performGlobalAction()方法。
使用焦点类型
Android 4.1 (API Level 16)引入了一个新的用户焦点接口类型叫做Accessibility焦点。这个焦点的类型可以被accessibility服务使用去选择任何可视用户接口元素并行动。这个焦点不同于许多已知的输入焦点,which determines what on-screen user interface element receives input when a user types characters, presses Enter on a keyboard or pushes the center button of a D-pad control。
Accessibility焦点与输入焦点是完全分开且独立的。事实上,可能在用户输入接口中的一个元素有输入焦点而另一个元素有Accessibility焦点。The purpose of Accessibility Focus is to provide accessibility services with a method of interacting with any visible element on a screen, regardless of whether or not the element is input-focusable from a system perspective. You can see accessibility focus in action by testing accessibility gestures. For more information about testing this feature, see .
注意:Accessibility services that use Accessibility Focus are responsible for synchronizing the current Input Focus when an element is capable of this type of focus. Services that do not synchronize Input Focus with Accessibility Focus run the risk of causing problems in applications that expect input focus to be in a specific location when certain actions are taken.
An accessibility service can determine what user interface element has Input Focus or Accessibility Focus using the AccessibilityNodeInfo.findFocus() method. You can also search for elements that can be selected with Input Focus using the focusSearch() method. Finally, your accessibility service can set Accessibility Focus using the performAction(AccessibilityNodeInfo.ACTION_SET_ACCESSIBILITY_FOCUS) method.
用例代码
API Demo项目包含两个例子用来作为编写accessibility代码的起点(<sdk>/samples/<platform>/ApiDemos/src/com/example/android/apis/accessibility):
- - 这个服务基于AccessibilityService最早的实现,可作为开发基本accessibility服务的基础,兼容Android 1.6 (API Level 4)以及更高版本。
- - 这个服务基于Android 4.0 (API Level 14)引入的增强的accessibility API。然而,你可以使用Android中等价的类(即,, )去替代后来API级别中引入类(即,, )以使这个例子兼容Android 1.6 (API Level 4)。