浅谈辅助功能 AccessibilityService

来源:互联网 发布:linux 该文件夹名字 编辑:程序博客网 时间:2024/04/28 03:38

辅助功能定义

对于那些由于视力、听力或其它身体原因导致不能方便使用Android智能手机的用户,Android提供了Accessibility功能和服务帮助这些用户更加简单地操作设备,包括文字转语音(不支持中文)、触觉反馈、手势操作、轨迹球和手柄操作。开发者可以搭建自己的Accessibility服务,这可以加强可用性,例如声音提示,物理反馈,和其他可选的操作模式。

 随着Android版本的不断升级,AndroidAccessibility功能也越来越强大,Android 4.0版本以前,系统辅助服务功能比较单一,仅仅能过单向获取窗口元素信息,比如获取输入框用户输入内容。到Android 4.1版本以后,系统辅助服务增加了与窗口元素的双向交互,此时可以通过辅助功能服务操作窗口元素,比如点击按钮等。

现实辅助功能准备工作

1、新建自己的AccessibilityService类

想要让自己程序实辅助功能,首先第一步就是要新建类并继承AccessibilityService类。继承自AccessibilityService的子类里实现几个重要的重载方法:

方法

描述

onAccessibilityEvent()

必须。通过这个函数可以接收系统发送来的AccessibilityEvent,接收来的AccessibilityEvent是经过过滤的,过滤是在配置工作时设置的。

onInterrupt()

必须。这个在系统想要中断AccessibilityService返给的响应时会调用。在整个生命周期里会被调用多次。

onServiceConnected()

可选。在系统成功连接上这个AccessibilityService会调用。在这个方法里你可以做一下初始化工作。

onUnbind()

可选。在系统将要关闭这个AccessibilityService会被调用。在这个方法中进行一些释放资源的工作。

2、新建AccessibilityService配置文件

<?xml version="1.0" encoding="utf-8"?><accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"    android:description="@string/XXXXX"    android:accessibilityEventTypes="typeAllMask"    android:accessibilityFeedbackType="feedbackGeneric"    android:notificationTimeout="100"    android:accessibilityFlags="flagDefault"    android:packageNames="XXXXX"    android:canRetrieveWindowContent="true"    android:settingsActivity = "XXXXX"/>

属性分别代表意义:

属性

描述

description

就是设置里辅助功能项的备注说明(不可在运行时修改)。

accessibilityEventTypes

设置响应事件的类型,typeAllMask当然就是响应所有类型的事件了。当然还有单击、长按、滑动等(多个值由“|”分隔)(可在运行时修改)。

值有:

说明

typeViewClicked

Receives TYPE_VIEW_CLICKED events.

typeViewLongClicked

Receives TYPE_VIEW_LONG_CLICKED events.

typeViewSelected

Receives TYPE_VIEW_SELECTED events.

typeViewFocused

Receives TYPE_VIEW_FOCUSED events.

typeViewTextChanged

Receives TYPE_VIEW_TEXT_CHANGED events.

typeWindowStateChanged

Receives TYPE_WINDOW_STATE_CHANGED events.

typeNotificationStateChanged

Receives TYPE_NOTIFICATION_STATE_CHANGED events.

typeViewHoverEnter

Receives TYPE_VIEW_HOVER_ENTER events.

typeViewHoverExit

Receives TYPE_VIEW_HOVER_EXIT events.

typeTouchExplorationGestureStart

Receives TYPE_TOUCH_EXPLORATION_GESTURE_START events.

typeTouchExplorationGestureEnd

Receives TYPE_TOUCH_EXPLORATION_GESTURE_END events.

typeWindowContentChanged

Receives TYPE_WINDOW_CONTENT_CHANGED events.

typeViewScrolled

Receives TYPE_VIEW_SCROLLED events.

typeViewTextSelectionChanged

Receives TYPE_VIEW_TEXT_SELECTION_CHANGED events.

typeAnnouncement

Receives TYPE_ANNOUNCEMENT events. 

typeViewAccessibilityFocused

Receives TYPE_VIEW_ACCESSIBILITY_FOCUSED events.

typeViewAccessibilityFocusCleared

Receives TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED events.

typeViewTextTraversedAtMovementGranularity

Receives TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY events.

typeGestureDetectionStart

Receives TYPE_GESTURE_DETECTION_START events.

typeGestureDetectionEnd

Receives TYPE_GESTURE_DETECTION_END events.

typeTouchInteractionStart

Receives TYPE_TOUCH_INTERACTION_START events.

typeTouchInteractionEnd

Receives TYPE_TOUCH_INTERACTION_END events.

typeWindowsChanged

Receives TYPE_WINDOWS_CHANGED events.

typeContextClicked

Receives TYPE_VIEW_CONTEXT_CLICKED events.

typeAssistReadingContext

Receives TYPE_ASSIST_READING_CONTEXT events.

typeAllMask

Receives TYPES_ALL_MASK i.e. all events.

accessibilityFeedbackType

设置回馈给用户的方式,有语音播出和振动(多个值由“|”分隔)(可在运行时修改)。

值有:

说明

feedbackSpoken

Provides FEEDBACK_SPOKEN feedback.

feedbackHaptic

Provides FEEDBACK_HAPTIC feedback.

feedbackAudible

Provides FEEDBACK_AUDIBLE feedback.

feedbackVisual

Provides FEEDBACK_VISUAL feedback.

feedbackGeneric

Provides FEEDBACK_GENERIC feedback.

feedbackAllMask

Provides FEEDBACK_ALL_MASK feedback.

notificationTimeout

相同类型的两个事件之间的最小时间发送到该服务(可在运行时修改)。

accessibilityFlags

可访问性(多个值由“|”分隔)(可在运行时修改)。

值有:

说明

flagDefault

Has flag DEFAULT

flagIncludeNotImportantViews

Has flag FLAG_INCLUDE_NOT_IMPORTANT_VIEWS

flagRequestTouchExplorationMode

Has flag FLAG_REQUEST_TOUCH_EXPLORATION_MODE

flagRequestEnhancedWebAccessibility

Has flag FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY

flagReportViewIds

Has flag FLAG_REPORT_VIEW_IDS

flagRequestFilterKeyEvents

Has flag FLAG_REQUEST_FILTER_KEY_EVENTS

flagRetrieveInteractiveWindows

Has flag FLAG_RETRIEVE_INTERACTIVE_WINDOWS

packageNames

响应的程序的包名(多个值由“,”分隔)(可在运行时修改)。

canRetrieveWindowContent

是否能够检索活动窗口的内容(不可在运行时修改)。

settingsActivity

允许用户修改此服务的设置的活动组件名称,(如果不需要在运行时修改设置,可忽略该项)(不可在运行时修改)。

修改设置,可使用:android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo).

3、AndroidManifest里注册服务

AndroidManifest.XML文件添加以下配置

<service    android:label="@string/XXXXX"// XXXXX就是设置里辅助功能项的标题    android:name=".XXXXX"// XXXXX为自定义的类    android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">// 系统权限    <intent-filter>        <action android:name="android.accessibilityservice.AccessibilityService" />    </intent-filter>    <meta-data android:name="android.accessibilityservice" android:resource="@xml/XXXXX" />// XXXXX为上面新建的配置XML文件</service>

获取UI元素

在onAccessibilityEvent中,使用参数event的getSource方法获取到的AccessibilityNodeInfo实例,即为触发这次事件的UI节点。获取到当前界面UITree的根节点可以使用findAccessibilityNodeInfosByText或者findAccessibilityNodeInfosByViewId方法。需要注意findAccessibilityNodeInfosByText在获取UI元素时的判断逻辑是包含而非等于。

示例代码如:

List<AccessibilityNodeInfo>nodes = event.getSource().findAccessibilityNodeInfosByText("立即安装");List<AccessibilityNodeInfo>nodes = event.getSource().findAccessibilityNodeInfosByViewId("txt_1");

模拟用户操作

模拟点击

获取界面上UI元素之后,可根据元素是否可响应操作进行相应的处理。例如,如果UI元素是一个有效的按钮,则可以使用下面的代码来进行模拟点击:

nodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);  

同理,如果UI元素是一个有效的列表,则可以使用下面的代码进行模拟滑动: 

nodeInfo.performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD); 

模拟物理键

也可以模拟物理键的操作,例如模拟按下返回键的代码是:

AccessibilityService.performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);

模拟打开消息通知栏

         在上面介绍accessibilityEventTypes中提到有一个事件: typeNotificationStateChanged,它便是消息通知栏状态发生改变变触发。一些红包外挂工具里头,一有红包就提醒的原理便是在onAccessibilityEvent中监听该事件,然后判断关键字并打开通知,示例关键代码如:

if(event.getEventType() != AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED){       return;}List<CharSequence>texts = event.getText();if(texts.size() <= 0 || !mAutoTrack) {    return;}for(CharSequence text : texts) {    String content = text.toString();    if(!content.contains("[微信红包]")){        continue;    }    if(event.getParcelableData() == null || !(event.getParcelableData() instanceofNotification)) {        continue;    }    Notification notification = (Notification)event.getParcelableData();    PendingIntent pendingIntent =notification.contentIntent;    try{        pendingIntent.send();    }catch (PendingIntent.CanceledException e) {        e.printStackTrace();    }}

语音播放

 首先,定义一个TextToSpeech对象,并在服务连上后进行初始化,示例代码如:

private TextToSpeech mTts;    ……mTts = newTextToSpeech(getApplicationContext(), new TextToSpeech.OnInitListener() {    @Override    public void onInit(int status) {        if (status == TextToSpeech.SUCCESS) {            mTts.setLanguage(Locale.US);        }    }});

执行语音播放代码:

mTts.speak("hello",TextToSpeech.QUEUE_FLUSH, null);

最后别忘记释放资源:

mTts.shutdown();

建议:

    在开发APP想支持语音播功能时,建议在用户界面控件中,通过使用android:contentDescription属性来描控件特性。

    对于EditText控件,提供了一个android:hint属性代替了contentDescription属性

判断是否开启辅助功能

intaccessibilityEnabled =Settings.Secure.getInt(context.getApplicationContext().getContentResolver(),android.provider.Settings.Secure.ACCESSIBILITY_ENABLED);if(accessibilityEnabled == 1) {    String settingValue =Settings.Secure.getString(context.getApplicationContext().getContentResolver(),Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);}

如果手机中开启了一些APP的辅助功能,settingValue的值为:APP1包名/APP1继承AccessibilityService类全名: APP2包名/APP2继承AccessibilityService类全名

使用Dump View Hierarchy for UI Automator解析UI界面视图帮助查找节点对象

一、


二、

三、

 

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 燕郊房子卖了户口怎么办 强制险单子丢了怎么办 车辆保险贴丢了怎么办 车险原单子丢了怎么办 车险保单丢了该怎么办? 审车保险单丢了怎么办 湖州公积金贷款买房具体信用怎么办 驾驶本扣分满了怎么办 摩托车被扣12分怎么办 驾照被扣12分怎么办 骑摩托被扣12分怎么办 摩托车没有驾照违章被扣分怎么办 高考登录密码丢了怎么办 高中档案遗失里面体检表怎么办 驾校不给补科一成绩单怎么办 外地驾照转广州体检表怎么办 驾照体检表签名签错怎么办 改完名字后护照怎么办 办健康证没有身份证怎么办 身份证掉了怎么办健康证 华师附小不搬了怎么办 健康证快到期了怎么办 老公想去日本打工怎么办 学生没有资产证明怎么办日本签证 在读证明学校不按模版怎么办 办日本签证没有户口本怎么办 日本大学留级续签失败怎么办 法国签证递交时间太晚怎么办 日本留学生签证更新拒签怎么办 永驻拒签了我该怎么办 越南签证拒签了怎么办 l1签证续签被拒怎么办 去日本跟团签证怎么办 手表里指针掉了怎么办 北京居住证过期半年了怎么办 居住证明居委会不盖章怎么办 小孩感冒鼻子不通气怎么办 1岁宝宝喉咙痰多怎么办 两个月喉咙有痰怎么办 10个月咳嗽有痰怎么办 昆山初级会计审核没有居住证怎么办