android Settings之辅助功能

文章连接:http://blog.csdn.net/gulinxieying/article/details/51658837
(该文章是前些时日的总结,今日重新翻到,现贴出来分享给大家,欢迎指正~)
绪论
一般情况下,我们正常使用手机时,是涉及到不这块功能的。因为该功能主要是为了方便具有正常使用手机障碍的一类人群,例如:具有听觉障碍或视觉障碍以及体能障碍的人群,或者在特定场景下(比如:会议中)才会使用的。由于该模块需要获取系统级的事件或权限,故对于第三方开发的服务性应用,是需要在Settings—>Accessibility中进行开关设置的。只有手动打开相应应用服务的开关,该应用才可以正常运行。通过对源码的分析,以及阅读google的关于该模块的3篇主流文档:
《Making Applications Accessible》
Development practices and API features to ensure your application is accessible to users with disabilities.
《Accessibility Developer Checklist》
A checklist to help developers ensure that their applications are accessible.
《Building Accessibility Services》
How to use API features to build services that make other applications more accessible for users.

一、辅助功能模块流程
首先需要说明的是辅助共能模块是加载在一个Fragment中的,是Android Settings中的一个小模块,是其中众多Fragment中的一个。该模块的流程大致可以分为2部分,整体结构比较简单,但其中所涉及的内容细节却颇为广泛。

  • 加载并更新布局——

该部分是在Fragment生命周期中的onCreate阶段完成,对应的加载布局文件为R.xml.accessibility_settings,加载完成后并对其中各preference条目进行了初始化。

  • 加载并更新应用——

该部分放在了onResume阶段完成,干的活主要是加载服务性应用,并更新辅辅助功能涉及到的所有应用(包括系统级和服务级应用)。
下面分别进行详细分解说明:
1)、加载并跟新布局
该部分也分为两个阶段:加载和更新。
对于加载,由于所加载文件是由PreferenceScreen以及PreferenceCategory“堆砌”而成,所以,这里主要涉及到的就是Preference控件的理解。详见sdk中对应控件讲解。
更新阶段主要是findPreference的操作,唯一需要注意的是此时的服务性PreferenceCategory中还没有任何应用添加,此时对应的服务性的category为空,所更新的大部分工作是对系统性应用布局的更新。
2)、加载并更新应用
由于该内容是在onResume阶段进行,所以,该阶段完成后,正辅助功能的Fragment就处于运行状态了。
该部分同样分为两个阶段:加载和更新。
加载——此时加载的就主要是已经安装了的服务性的应用了,具体流程较为简单,大致如下:

  • 新建一个set实例installedServices,并清空,用来存储安装过的service;
  • 通过AccessibilityManager实例获取当前AccessibilityServiceList,并存于List实例installedServiceInfos中;
  • 获取installedServiceInfos长度,即当前安装service数目;
  • 遍历installedServiceInfos,并逐个将已安装的service添加到installedServices中。

更新——该部分分为对服务性应用和系统级应用的更新。
服务性应用更新:updateServicesPreferences()。
不作过多解析,流程图如下:
这里写图片描述
系统性应用更新:updateSystemPreferences()(略)
二、如何创建辅助功能应用
通常开发辅助功能的应用无需添加太多的代码,但,下面的步骤确实必须的。
1)、在AndroidManifest.xml文件中声明并给出权限:
如果希望有个服务成为辅助性服务,必须在其对应的manifest文件中进行一个服务性的声明,下面给出添加辅助性服务中的必须项和可选项设置。
a、辅助性服务的声明:
为了被当作一个辅助性服务,在应用程序的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)以上)
b、无障碍服务配置
辅助性性服务还必须提供一个指定辅助性服务处理事件的类型的配置和额外的信息服务。一个辅助性服务的配置是包含在 AccessibilityServiceInfo类中。你的服务可以使用这个类的一个实例,在运行时setServiceInfo()来构建和设置一个配置。然而,并非所有的配置选项可以使用这种方法。从Android 4.0,您可以在你的mainifest中包含一个元素引用一个配置文件,它允许您为您的辅助性服务设置整个范围的选项,如下例所示:

<service android:name=".MyAccessibilityService">
  ...
  <meta-data
    android:name="android.accessibilityservice"
    android:resource="@xml/accessibility_service_config" />
</service>

这个 meta-data元素指的是在应用程序的资源目录创建的一个XML文件。(/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"
/>

其他配置信息的设置请参照AccessibilityServiceInfo类。
2)、注册辅助性事件
该环节是最重要的一个环节,主要功能是过滤特定服务性事件类型。在进行过滤时,主要通过包名和事件类型进行。
包名——指定你想要处理的辅助性服务的应用程序的包名。如果省略该参数,你的辅助性服务被认为是对于任何应用程序的辅助性的事件提供服务。这个参数可以在辅助性性服务配置文件 中,android:packageNames属性来设置,这个属性用逗号分隔多个包名,或者使用 AccessibilityServiceInfo.packageNames 设置。
事件类型——指定你想要你的服务来处理的辅助性活动的类型。这个参数可以设置在辅助性服务配置文件中,使用 android:accessibilityEventTypes属性,用|分隔的字符(例如accessibilityEventTypes = ” typeViewClicked | typeViewFocused”),或使用AccessibilityServiceInfo.eventTypes设置。
( 注意:,如果服务提供不同的反馈类型,Android框架分派辅助性事件给多个辅助性服务。然而,如果两个或多个服务提供相同的反馈类型,那么只有第一个注册服务接收事件。)
3)、实现辅助性服务的方法
一个辅助性服务必须继承自AccessibilityService类,并必须重写如下方法,也是该类的生命周期的表现方法,同时构成了辅助性服务应用的基本框架:
当服务开启时——可选
onServiceConnected():当应用成功连接到你的辅助性服务时,系统调用该方法。
当服务运行时——必须
onAccessibilityEvent():当系统检测到一个匹配你辅助性服务过滤器中设置参数的AccessibilityEvent时,调用该方法,运行时多次调用。
onInterrupt():当你的服务对系统事件的反馈被中断时,调用该方法。该方法同上面方法一样,也是被多次调用的。
当服务结束时——可选
onUnbind():在系统将要关闭这个AccessibilityService会被调用。在这个方法中可以进行一些释放资源的工作
四、Demo实例——ClockBackService
该实例是移植的Android自身的一个demo,为了进一步说明该类应用的创建步骤,下面对该demo进行解析说明。
【附件连接】accessibilitytest.zip
1)、在AndroidManifest.xml文件中声明并给出权限:
[AndroidManifest.xml]

<service android:name=".ClockBackService"
            android:label="@string/accessibility_service_label"
            android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
            <intent-filter>
              <action android:name="android.accessibilityservice.AccessibilityService" />
            </intent-filter>
        </service>

为了给读者一个可视化的界面,源代码中是带有一个Activity的,不过在实际开发中可以不加,在此也不作说明。其中BIND_ACCESSIBILITY_SERVICE权限是重点。
2)、注册辅助性事件
该实例注册事件是在onServiceConnected()阶段进行的,集中于configureForRingerMode()函数中。主要事件都可以在ringerMode中发出,该应用负责接收和接收后的处理。
[ClockBackService.java]

private void setServiceInfo(int feedbackType) {
        AccessibilityServiceInfo info = new AccessibilityServiceInfo();
        // We are interested in all types of accessibility events.
        info.eventTypes = AccessibilityEvent.TYPES_ALL_MASK;
        // We want to provide specific type of feedback.
        info.feedbackType = feedbackType;
        // We want to receive events in a certain interval.
        info.notificationTimeout = EVENT_NOTIFICATION_TIMEOUT_MILLIS;
        // We want to receive accessibility events only from certain packages.
        info.packageNames = PACKAGE_NAMES;
        setServiceInfo(info);
    }

其中包名使用PACKAGE_NAMES宏进行了自定义:
private static final String[] PACKAGE_NAMES = new String[] {“com.android.alarmclock”, “com.google.android.deskclock”, “com.android.deskclock”};即该应用只为上面3个包的应用提供辅助服务。
事件类型是AccessibilityEvent.TYPES_ALL_MASK,info.feedbackType = feedbackType;即该应用接收上面3个包的所有feedbackType类型的事件(详见AccessibilityServiceInfo类)。
3)、实现辅助性服务的方法
在该demo中,重构了如下4个方法:
onServiceConnected()——虽然在开发中该方法可以省略不写,但在这里,该方法尤其重要,因为接收处理事件之前的配置全部放在了这里。
onAccessibilityEvent()——上面配置完了后,接下来就是服务性应用开始服务的时候了。该函数是一个回调函数,每当符合上面设置条件的事件被接收到时,都会执行一次该方法。
onInterrupt()——每当上面的事件在处理过程中被打断,该方法就会被执行一次。
onUnbind()——该函数是在用户关闭“设置—>辅助功能—>ClockBack”中的开关时执行的。通过源码可以看出,在这里,停掉了TTS服务,注销了广播接收者mBroadcastReceiver,最后将初始化标志位置为false。
4)、测试运行
打开“设置—>辅助功能—>TalkBack”开关,操作时钟应用,抓取应用程序log。
对应部分log如下:
这里写图片描述
五、总结
如上主要总结了关于辅助功能的启动流程,以及辅助性应用的创建方法。在此之外还有关于该功能的测试,详见sdk中的“Accessibility Testing Checklist”片段。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值