无障碍服务是一个应用程序,它给有残疾的用户或暂时无法与设备完全交互的用户提供了更好的无障碍用户交互功能。比如驾驶、照顾小孩或者在吵闹的派对上可能需要额外或者替代的交互反馈。

Android提供了标准的无障碍服务,包括TalkBack,开发人员可以创建和发布自己的无障碍服务。

Android从1.6(API 4)开始引入了构建和部署无障碍服务的能力,并在Android 4.0(API 14)进行了重大改进。Android Support Library在Android 4.0版本上增加了支持增强无障碍服务功能,这样就能够兼容到Android 1.6。Android鼓励开发者使用Support Library来广泛兼容无障碍服务,并针对Android 4.0中引入的更高级的无障碍服务功能进行开发。

清单声明和权限

提供无障碍服务的应用程序必须在其应用程序清单中包含特定声明,以便被Android系统视为无障碍服务。

无障碍服务声明

为了是应用程序的无障碍服务能够正常使用,必须在应用程序清单中application元素中包含一个service元素。另外,在service元素中,还必须包含无障碍服务的intent filter。为了兼容Android 4.1及以上版本,service元素还必须添加BIND_ACCESSIBILITY_SERVICE权限,来确保只有系统可以绑定无障碍服务。代码示例:

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

无障碍服务配置

无障碍服务还必须提供相关配置,来指定服务处理的无障碍功能事件的类型以及有关该服务的其他信息。无障碍服务的配置信息包含在AccessibilityServiceInfo 类中,无障碍服务可以在运行时使用该类实例和setServiceInfo()方法来构建和设置配置。但是,不是所有配置选项都可以使用用此方法。

从Android 4.0开始,可以在清单service元素中包含<meta-data>元素来引用一个xml无障碍配置文件,该配置文件可以设置无障碍服务的所有配置选项。代码示例:

<service android:name=".MyAccessibilityService">...<meta-dataandroid: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"
/>

在运行时配置无障碍服务配置信息可以参考AccessibilityServiceInfo 类。

无障碍服务方法

无障碍服务必须继承AccessibilityService类并重写它的方法。这些方法按照Android系统调用的顺序,从服务启动调用(onServiceConnected()),运行时调用(onAccessibilityEvent(),onInterupt())到关闭服务调用(onUnbind())。

  • onServiceConnected():可选方法。该方法在系统成功连接到无障碍服务时调用。可以在该方法中为无障碍服务做一次性设置操作,包括连接到用户反馈系统服务,比如音频管理器或设备振动器。该方法还可以在运行时设置无障碍服务配置或一次性调整操作,调用setServiceInfo()方法进行设置。
  • onAccessibilityEvent():必选方法。当系统检测到与无障碍服务配置中指定事件帅选参数相匹配的AccessibilityEvent时会回调该方法。比如,当用户单击某个按钮或某个用户界面控件获得焦点时,系统会回调该方法,并传递关联的AccessibilityEvent,然后无障碍服务可以解释并向用户提供反馈。此方法可以在服务的生命周期中多次调用。
  • onInterupt():必选方法。当系统想要中断服务提供的反馈时调用此方法,通常是响应用户操作。此方法可以在服务的生命周期中多次调用。
  • onUnbind():可选方法。当系统即将关闭无障碍服务时调用此方法。使用此方法可执行任何一次性关闭程序,包括取消分配用户反馈系统服务,比如音频管理器或设备振动器。

注册无障碍事件(Event)

无障碍服务功能配置参数最重要的功能之一是允许指定服务可以处理某一类型的无障碍事件。能够指定处理某类型无障碍事件可以使无障碍功能相互协作,并使开发人员能够灵活地处理特定事件类型。事件过滤包含以下标准:

  • 包名(package name):指定无障碍服务处理哪个应用程序的无障碍事件。如果缺省此参数,则默认无障碍服务可以处理所有应用程序的事件。此参数可以在无障碍服务配置文件中设置,使用android:packageNames属性且以逗号(,)分隔列表,或者使用AccessibilityServiceInfo.packageNames成员变量进行设置。
  • 事件类型(Event Types):指定无障碍服务想要处理的事件类型。该参数可以在无障碍服务配置文件中设置,使用android:accessibilityEventTypes属性且以竖线(|)分隔列表(比如,accessibilityEventTypes="typeViewClicked|typeViewFocused"),或者使用AccessibilityServiceInfo.eventTypes成员变量进行设置。

设置无障碍服务时,请仔细考虑服务能够处理哪些事件,并只注册这些事件。由于用户一次可以激活多个无障碍服务,因此自己无障碍服务不得使用无法处理的事件。

示例代码

清单配置代码:

<service android:name=".accessibility.TaskBackService"android:label="@string/accessibility_query_window_label"android:enabled="@bool/atLeastIceCreamSandwich"android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"><intent-filter><action android:name="android.accessibilityservice.AccessibilityService" /></intent-filter><meta-dataandroid:name="android.accessibilityservice"android:resource="@xml/taskbackconfig" />
</service>

xml配置代码:

<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"android:accessibilityEventTypes="typeAllMask"android:packageNames="com.example.android.apis"android:accessibilityFeedbackType="feedbackSpoken"android:notificationTimeout="100"android:canRetrieveWindowContent="true"android:description="@string/accessibility_query_window_description" />

无障碍服务代码:

package com.example.android.apis.accessibility;import com.example.android.apis.R;import android.accessibilityservice.AccessibilityService;
import android.text.TextUtils;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityRecord;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;import java.util.Locale;/*** This class demonstrates how an accessibility service can query* window content to improve the feedback given to the user.*/
public class TaskBackService extends AccessibilityService implements OnInitListener {/** Tag for logging. */private static final String LOG_TAG = "TaskBackService/onAccessibilityEvent";/** Comma separator. */private static final String SEPARATOR = ", ";/** The class name of TaskListView - for simplicity we speak only its items. */private static final String TASK_LIST_VIEW_CLASS_NAME ="com.example.android.apis.accessibility.TaskListView";/** Flag whether Text-To-Speech is initialized. */private boolean mTextToSpeechInitialized;/** Handle to the Text-To-Speech engine. */private TextToSpeech mTts;/*** {@inheritDoc}*/@Overridepublic void onServiceConnected() {// Initializes the Text-To-Speech engine as soon as the service is connected.mTts = new TextToSpeech(getApplicationContext(), this);}/*** Processes an AccessibilityEvent, by traversing the View's tree and* putting together a message to speak to the user.*/@Overridepublic void onAccessibilityEvent(AccessibilityEvent event) {if (!mTextToSpeechInitialized) {Log.e(LOG_TAG, "Text-To-Speech engine not ready.  Bailing out.");return;}// This AccessibilityNodeInfo represents the view that fired the// AccessibilityEvent. The following code will use it to traverse the// view hierarchy, using this node as a starting point.//// NOTE: Every method that returns an AccessibilityNodeInfo may return null,// because the explored window is in another process and the// corresponding View might be gone by the time your request reaches the// view hierarchy.AccessibilityNodeInfo source = event.getSource();if (source == null) {return;}// Grab the parent of the view that fired the event.AccessibilityNodeInfo rowNode = getListItemNodeInfo(source);if (rowNode == null) {return;}// Using this parent, get references to both child nodes, the label and the checkbox.AccessibilityNodeInfo labelNode = rowNode.getChild(0);if (labelNode == null) {rowNode.recycle();return;}AccessibilityNodeInfo completeNode = rowNode.getChild(1);if (completeNode == null) {rowNode.recycle();return;}// Determine what the task is and whether or not it's complete, based on// the text inside the label, and the state of the check-box.if (rowNode.getChildCount() < 2 || !rowNode.getChild(1).isCheckable()) {rowNode.recycle();return;}CharSequence taskLabel = labelNode.getText();final boolean isComplete = completeNode.isChecked();String completeStr = null;if (isComplete) {completeStr = getString(R.string.task_complete);} else {completeStr = getString(R.string.task_not_complete);}String taskStr = getString(R.string.task_complete_template, taskLabel, completeStr);StringBuilder utterance = new StringBuilder(taskStr);// The custom ListView added extra context to the event by adding an// AccessibilityRecord to it. Extract that from the event and read it.final int records = event.getRecordCount();for (int i = 0; i < records; i++) {AccessibilityRecord record = event.getRecord(i);CharSequence contentDescription = record.getContentDescription();if (!TextUtils.isEmpty(contentDescription )) {utterance.append(SEPARATOR);utterance.append(contentDescription);}}// Announce the utterance.mTts.speak(utterance.toString(), TextToSpeech.QUEUE_FLUSH, null);Log.d(LOG_TAG, utterance.toString());}private AccessibilityNodeInfo getListItemNodeInfo(AccessibilityNodeInfo source) {AccessibilityNodeInfo current = source;while (true) {AccessibilityNodeInfo parent = current.getParent();if (parent == null) {return null;}if (TASK_LIST_VIEW_CLASS_NAME.equals(parent.getClassName())) {return current;}// NOTE: Recycle the infos.AccessibilityNodeInfo oldCurrent = current;current = parent;oldCurrent.recycle();}}/*** {@inheritDoc}*/@Overridepublic void onInterrupt() {/* do nothing */}/*** {@inheritDoc}*/@Overridepublic void onInit(int status) {// Set a flag so that the TaskBackService knows that the Text-To-Speech// engine has been initialized, and can now handle speaking requests.if (status == TextToSpeech.SUCCESS) {mTts.setLanguage(Locale.US);mTextToSpeechInitialized = true;}}/*** {@inheritDoc}*/@Overridepublic void onDestroy() {super.onDestroy();if (mTextToSpeechInitialized) {mTts.shutdown();}}
}

Android无障碍服务( Accessibility Service)应用相关推荐

  1. Android 无障碍服务自动点击

    业余时间了解了Android无障碍服务的一些有趣功能,比如微信自动抢红包.应用宝的一键安装功能等.大致原理是监听手机窗体内容变化,拿到对应的View,进行点击.长按等Touch操作,下面我们就借助 A ...

  2. Android无障碍服务开发

    https://actionwind.wordpress.com/2022/04/17/android%e6%97%a0%e9%9a%9c%e7%a2%8d%e6%9c%8d%e5%8a%a1%e5% ...

  3. Android无障碍检测,Android无障碍服务检测通知

    我试图让我的应用在显示通知时进行检测.我已经在设置应用程序中启用它,并且onServiceConnected确实被调用,但是当我通过Gmail应用程序创建通知或接收电子邮件时,什么也没有发生,onAc ...

  4. 从零开始安卓无障碍服务Accessibility

    从零开始无障碍服务 文章目录 从零开始无障碍服务 前言 一.新建项目-选择Empty Activity 二.新建BaseService类和AccessService类 1. BaseService类 ...

  5. Android 无障碍服务设置

    项目中遇到需要将客户的无障碍服务设置为默认开启,无障碍服务,是可以监听界面的操作,比如:点击.拖动.界面更新等信息的,更为强大的是可以获取屏幕信息,同时具备普通Service的能力. 具体如何设置呢? ...

  6. android无障碍服务网页,android无障碍

    安卓手机无障碍服务指的是什么 许多Android用户有不同的能力(限制),这要CSS布局HTML小编今天和大家分享他们以不同的方式使用他们的Android设备.这些限制包括视力,肢体或与年龄有关,这些 ...

  7. Android的服务(Service)(三)Service客户端的绑定与跨进程

    继续上篇的分析,接下来是第三个问题"Service与其客户端的绑定如何实现,即跨进程调用问题" (一).Service的生命周期 (二).Service的自动重启问题 (三).Se ...

  8. Android的服务(Service)(一)生命周期

    本篇和接下来的几篇我们来浅析一下Android的另外一个非常重要的组件:Service,看到这里我们的脑海里都会涌现出什么词语呢?诸如:无用户交互界面,耗时后台操作,服务(级别)进程,远程调用. 1. ...

  9. android exchange服务,带有“ Service com.android.exchange.ExchangeService

    我正在用Android开发一个非常简单的应用程序.我制作了一个启动屏幕,主菜单以及一个带有单选按钮和一个按钮的页面(该按钮会根据选中的单选按钮播放声音).该应用程序运行正常(不会崩溃),但是我一直在l ...

最新文章

  1. MindSpore模型精度调优实践
  2. caffe调用的一个例子
  3. python 编程算法_python语言编程算法
  4. 基本农田卫星地图查询_如何基于西安80坐标查询定位
  5. 生成技术在人工智能平台中的应用探索
  6. 介绍当前流行的一些开源Flash视频播放器
  7. 构建springmvc+dubbo分布式平台-dubbo简介
  8. 查看详细_教师资格准考证开始打印!点击查看详细流程!
  9. Xcode字体新宠 Monoid
  10. (原)MobileNetV1
  11. linux yum jemalloc,Redis安装报错error:jemalloc/jemalloc.h:No such file or directory解决方法
  12. 计算机组成原理完整学习笔记(四):输入输出系统
  13. android电视文件管理器,2018电视文件管理器排行榜(最新)
  14. 08-微信小程序商城 销售排行(微信小程序商城开发、小程序毕业设计、小程序源代码)(黄菊华-微信小程序开发教程)
  15. 高级设计总监的设计方法论——5W1H需求分析法 KANO模型分析法
  16. 惠普服务器安装系统流程,惠普服务器怎样安装系统?
  17. 小故事折射出大道理:风靡办公室的管理寓言
  18. 第四次机考(2019) C. f1二
  19. 标准日本语初级 语法整理
  20. 使用 jodd:form tag

热门文章

  1. 利用python对gif图片进行压缩处理,简单案例
  2. spyder/conda安装包报错:conda info could not be constructed. KeyError: ‘pkgs_dirs‘
  3. js/javaScript通过setTimeout做动画和需要注意的点
  4. 系统升级到iOS9,真机运行报“was compiled with optimization - stepping may behave oddly...”,闪退
  5. ieltsListen was compiled with optimization - stepping may behave oddly; variables may not be availab
  6. 测试窗体的FormBorderStyle属性,不同属性所对应的窗体边框显示情况
  7. 做python的心得体会_实训python的心得体会
  8. python 抓取猫眼电影评分
  9. AD7606 SPI模式 网上问题汇总
  10. 进制转换【最全进制转换汇总】(整数_小数_正数_负数)正负数整数小数十进制转任意进制-正负数整数小数任意进制转十进制-正负数低进制转高进制-正负数高进制转低进制