现在的位置: 首页 > 综合 > 正文

Android无障碍服务三 创建辅助功能服务

2014年08月29日 ⁄ 综合 ⁄ 共 7941字 ⁄ 字号 评论关闭

4.创建辅助功能服务

    一个可访问性服务是一个应用程序,这个程序提供了增强的用户界面以帮助残障人士,或者可能暂时无法与设备充分交互的人们。例如,正在驾驶的用户,正照顾小孩子或参加一个非常常闹的聚会,可能需要额外的或替代的接口反馈。
    Android提供了标准的辅助性服务,包括TalkBack,开发人员可以创建和分配自己的服务。该文档解释了创建辅助性服务的基本内容。
    对你来讲,在Android 1.6(API4)中引入构建和部署的辅助性服务在Android 4.0(API级别14)中做了显著的改善。 Android Support Library也对Android 4.0这些增强的辅助性,Android 1.6以上版本,进行了更新,提供支持。鼓励开发人员的目标是使用Support Library,在Android 4.0介绍的更先进的辅助性特性上进行兼容辅助性服务的开发。

4.1 在Manifest声明并给出权限

    提供辅助性服务的应用程序必须在其应用的manifests中当作Android系统的一个辅助性服务进行声明。本节解释了辅助性服务中必需和可选设置。

4.1.1 辅助性服务的声明

    为了被当作一个辅助性服务,在应用程序的maninfest中,必须包括服务元素(而不是活动元素)。此外,在服务元素中,必须包含辅助性服务的intent filter。为了与Android 4.1以上版本的兼容性,manifest中需要指定BIND_ACCESSIBILITY_SERVICE 权限,以下示例:
<application>
  <service android:name=".MyAccessibilityService"
      android:label="@string/accessibility_service_label">
    <intent-filter>
      <action android:name="android.accessibilityservice.AccessibilityService" />
    </intent-filter>
  </service>
  <uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />
</application>
这些声明所需的所有辅助性服务部署在Android 1.6(API级别4)以上。

4.1.2 无障碍服务配置

    辅助性性服务还必须提供一个指定辅助性服务处理事件的类型的配置和额外的信息服务。一个辅助性服务的配置是包含在AccessibilityServiceInfo类中。你的服务可以使用这个类的一个实例,在运行时setServiceInfo()来构建和设置一个配置。然而,并非所有的配置选项可以使用这种方法。从Android 4.0,您可以在你的mainifest中包含一个<meta-data>元素引用一个配置文件,它允许您为您的辅助性服务设置整个范围的选项,如下例所示:
<service android:name=".MyAccessibilityService">
  ...
  <meta-data
    android:name="android.accessibilityservice"
    android:resource="@xml/accessibility_service_config" />
</service>

  这个 meta-data元素指的是在应用程序的资源目录创建的一个XML文件。(<project_dir>/res/xml/accessibility_service_config.xml). 下面的代码显示了服务配置文件的示例内容:

<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:description="@string/accessibility_service_description"
    android:packageNames="com.example.android.apis"
    android:accessibilityEventTypes="typeAllMask"
    android:accessibilityFlags="flagDefault"
    android:accessibilityFeedbackType="feedbackSpoken"
    android:notificationTimeout="100"
    android:canRetrieveWindowContent="true"
    android:settingsActivity="com.example.android.accessibility.ServiceSettingsActivity"
/>
 更多用于无障碍服务配置文件的XML属性的信息,请按照以下链接到参考文档:
    更多可以在运行时动态地设置配置的信息,请参阅AccessibilityServiceInfo参考文档。

4.2 注册辅助性事件

    辅助性服务配置参数的最重要的一个功能是允许您指定哪些类型的辅助性事件你的服务可以处理。通过指定这个信息能够是辅助性服务相互配合,并让作为一个开发者的你灵活地处理特定的应用程序的特定事件类型。事件过滤包括下列标准:
    包名——指定你想要处理的辅助性服务的应用程序的包名。如果省略该参数,你的辅助性服务被认为是对于任何应用程序的辅助性的事件提供服务。这个参数可以在辅助性性服务配置文件中,android:packageNames属性来设置,这个属性用逗号分隔多个包名,或者使用AccessibilityServiceInfo.packageNames 设置。
    事件类型——指定你想要你的服务来处理的辅助性活动的类型。这个参数可以设置在辅助性服务配置文件中,使用android:accessibilityEventTypes属性,用|分隔的字符(例如accessibilityEventTypes = " typeViewClicked | typeViewFocused”),或使用AccessibilityServiceInfo.eventTypes
设置。
    当设置辅助性服务,仔细考虑哪些事件你的服务是能够处理,只注册这些事件。因为用户可以激活超过一个辅助性服务,服务必须不使用它是不能够处理事件。记住,其他服务可能会处理这些事件是为了改善用户的体验。
    注意:,如果服务提供不同的反馈类型,Android框架分派辅助性事件给多个辅助性服务。然而,如果两个或多个服务提供相同的反馈类型,那么只有第一个注册服务接收事件。

4.3 辅助性服务的方法

    一个辅助性服务必须继承AccessibilityService类,并且重写这个类中下面的方法。这些方法由Android系统按顺序调用的,当服务开启时 (onServiceConnected()),当服务运行时(onAccessibilityEvent(), onInterrupt()) ,当服务结束时 (onUnbind())。
  • onServiceConnected()-(可选)当应用成功连接到你的辅助性服务时,系统调用该方法。使用这个方法为你的辅助性服务做任何一次性设置的步骤,包括连接到用户反馈的系统服务,如音频管理器或设备振动器。如果你想在运行时或者一次性调整你服务的配置,这是一个方便的位置,这种情况时调用setServiceInfo()。
  • onAccessibilityEvent()-(必需)当系统检测到一个匹配你辅助性服务过滤器中设置参数的AccessibilityEvent时,调用该方法。例如,当用户在一个应用程序中点击一个按钮或焦点放在用户界面控件上时,,你的辅助性性服务就可以提供反馈。这种情况下,系统就通过相关连的AccessibilityEvent调用这个方法,然后服务就可以解释和使用为用户提供的反馈了。这个方法在服务的生命周期中可能会被多次调用。
  • onInterrupt()-(必需)当系统中断在你的服务中提供的反馈时调用该方法,通常是在响应用户的诸如移动焦点到不同的控件上的动作时,调用该方法。该方法在你服务的生命周期中被多次的调用。
  • onUnbind()-(可选)当系统即将关闭当前辅助性服务时,调用该方法。使用这个方法来一次性关闭任何程序,包括释放用户反馈系统服务,如音频管理器或设备振动器。
    这些回调方法为你的辅助性服务提供基本的结构框架。Android系统以AccessibilityEvent对象的形式对用户提供的返回的数据,如何处理它们由你来决定。更多关于获取信息的辅助性事件的信息,参考实现辅助性训练章节。

4.4 获得事件的细节

    Android系统通过AccessibilityEvent对象提供用户界面交互的辅助性服务的信息。Android 4.0之前,一些有效的信息是放在辅助性事件中的,同时提供了大量的用户选择用户界面控件的细节,及有限的上下文信息。在许多情况下,这种缺失的上下文信息对理解被选中的控件,可能是至关重要的。
    一个用户界面的示例,日历,还是日程计划的上下文是关键的。如果用户在周一到周五天列表选择了下午4点时间槽,辅助性服务发出“4 PM”的反馈,但是并没有发出星期的名字,这个月中的哪天,月份的名字,这个反馈的结果就是令人困惑的。在这个示例中,对于一个关心会议安排的用户,用户界面控件的上下文是至关重要的。
    Android 4.0显著扩展了信息的数量,这些信息是辅助性服务通过基于视图层的辅助性事件获取的关于用户与界面交互的信息。一个视图层是一组用户界面组件,这些组件包含其父类的组件,及其子类组件的用户界面元素。一个视图层次结构是一组用户界面组件,包含组件(父母)和用户界面元素,可以包含由该组件(孩子们)。通过这种方式,Android系统能够提供更丰富的关于辅助性性事件的细节,允许辅助性服务提供更多有用的反馈给用户。
    一个辅助性服务获取用户界面事件的信息,通过系统服务的onAccessibilityEvent()回调方法传递的AccessibilityEvent。这个对象提供关于事件的详细信息,包括对象的类型,其描述性文本和其他细节。从Android 4.0(和以前版本中通过在Support Library的AccessibilityEventCompa支持),通过下面这些方法获取额外的关于事件的信息:
  •  AccessibilityEvent.getRecordCount()和getRecord(int)——这些方法允许你检索AccessibilityRecord对象集合,这也使得你通过系统获得AccessibilityEvent。这种层次的细节为这个触发你辅助性服务的事件提供了更多的上下文。
  • AccessibilityEvent.getSource(),这个方法返回一个AccessibilityNodeInfo对象。该对象允许您请求(父母和孩子)的组件的视图布局层,源于辅助性事件。这个特性允许一个辅助性服务调查事件的整个上下文,包括内容和任何封闭视图或子视图的状态。
    重点:这种对试图层次的探查,可能通过AccessibilityEvent 为你的辅助性服务,获得潜在用户私人信息。由于这个原因,您的服务必须通过无障碍服务配置XML文件,请求这种级别的访问,包括canRetrieveWindowContent属性设置为true。如果在您的服务配置xml文件不包括此设置,调用getSource()就会失败。
    注意:在Android 4.1(API级别16)及以上,getSource()方法,以及AccessibilityNodeInfo.getChild()和getParent(),只返回视图对象,这被认为是(对绘制内容或者响应用户的操作的视图)重要的辅助性。如果你的服务要求所有视图,可以通过设置服务的AccessibilityServiceInfo实例的成员标志标记FLAG_INCLUDE_NOT_IMPORTANT_VIEWS来实现。

4.5 为用户做出动作

    从Android 4.0(API级别14)开始,辅助性服务可以代表用户,包括改变输入焦点和选择(激活)的用户界面元素。在Android 4.1(API级别16)行动的范围已经被扩大到包括滚动列表和交互文本字段。辅助性服务也可以采取全局的行动,比如导航到主屏幕,按后退按钮,打开屏幕通知栏和最近的应用程序列表。Android
4.1还包括一个新类型的焦点,Accessibilty焦点,这使得辅助性服务可以选择所有可见的元素。
    这些新功能可以让辅助性服务的开发人员去创建替代导航模式如手势导航,改进残疾人用户对他们的Android设备的控制成为可能。

4.5.1 监听手势

    辅助性服务可以侦听特定的手势,对做出这个手势的用户给予响应。这个特性,添加在Android 4.1(API级别16),要求你的辅助性服务的请求通过触摸功能来激活的。你的服务可以请求通过设置服务的AccessibilityServiceInfo实例的成员标志为FLAG_REQUEST_TOUCH_EXPLORATION_MODE来激活,如下例所示。
public class MyAccessibilityService extends AccessibilityService {
    @Override
    public void onCreate() {
        getServiceInfo().flags = AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE;
    }
    ...
}
  一旦你的服务通过触摸激活,如果这个功能没有打开,用户必须打开功能。当这个功能被激活时,你的服务接收通知的辅助性手势通过你的服务的onGesture()回调方法,就可以对用户的行为做出响应。

4.5.2 使用辅助性行为

    辅助性服务可以对用户的行为做出动作,使得与应用程序的交互更简单和更有效率。辅助性服务执行操作的能力添加于Android 4.0(API级别14),在Android 4.1(API级别16)明显的扩展了该能力。
    为了做出的动作代表用户,你的辅助性服务必须注册去接收从几个或多个应用程序接收事件,必须通过在服务配置文件设置android:canRetrieveWindowContent为true,请求允许查看应用程序的内容。当你的服务接收到事件,它可以使用getSource()从事件检索AccessibilityNodeInfo对象。通过AccessibilityNodeInfo对象,您的服务可以探索视图层来决定采取何种行动,然后使用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()方法。

4.5.3 使用焦点类型

    这种类型的焦点可以通过辅助性服务选择任何可见的用户界面元素和作用于它。这个焦点类型不同于常见的输入焦点,当一个用户键入字符时,输入焦点决定了对屏幕上的界面元素输入,在键盘按Enter键或推动中心按钮的手柄控制的接收。
    辅助性的焦点是完全的从输入焦点中独立出来。事实上,它可以让在一个用户界面的一个元素有输入焦点,而另一个元素有辅助性焦点。辅助性焦点的目的是提供辅助性服务,这个服务有与屏幕上任何可见元素进行交互的方法,无论从系统的视图元素的input-focusable是什么。你可以通过测试辅助性手势来看到在一个动作上的辅助性焦点。更多测试这个手势的信息,参考测试手势导航一节。
    注意:使用辅助性焦点的辅助性服务,当一个元素可以希艾娜关于那个输入类型的焦点时,可以对输入类型焦点进行同步处理。没有同步处理输入焦点和辅助性焦点的服务,当多出某些动作时,在某个特定的位置,在应用程序中会有出现问题的风险。
    一个辅助性服务可以使用AccessibilityNodeInfo.findFocus()方法决定哪些用户界面元素有输入焦点或辅助性焦点。你也可以使用focusSearch()方法,搜索带有输入焦点的,能被选中的元素。最后,你的辅助性服务可以使用performAction(AccessibilityNodeInfo.ACTION_SET_ACCESSIBILITY_FOCUS)方法设置辅助性焦点。

4.6 示例代码

    API演示项目包含两个例子,这两个例子可以作为生成辅助性服务的开始 (<sdk>/samples/<platform>/ApiDemos/src/com/example/android/apis/accessibility):
  • ClockBackService——这项服务是基于最初AccessibilityService的实现,可以作为开发基本的无障碍服务的基础,这些服务都是兼容Android1.6(API级别4)以上版本。
  • TaskBackService——这个服务是基于在Android 4.0(API级别14)中引入的增强了的辅助性API。然而,你可以使用Android Support Libary代替之后API中引入的类 (例如AccessibilityRecord, AccessibilityNodeInfo ) 与等效支持包类 (例如 AccessibilityRecordCompat, AccessibilityNodeInfoCompat ),使得这个例子可以使用在Android 1.6(API 4)的版本上。

抱歉!评论已关闭.