辅助功能是Android系统提供的一种服务,派生自Service类。这个服务提供了增强的用户界面,目的是为了帮助残障人士。它一般提供了页面元素查找功能和元素点击功能。

通过辅助功能,开发者可以实现一些非常丰富的功能:

抢红包
微信自动回复
检查微信好友
进程清理
判断应用当前状态
防卸载
浏览器劫持
跳过用户授权

关于更多AccessibilityService的安全信息可以查看这篇文章:
https://www.freebuf.com/articles/terminal/114045.html

AccessibilityService(辅助功能类)派生自Service,它是一个服务类。AccessibilityService是一个抽象类,所以要使用辅助功能的话,就要从AccessibilityService类派生一个实例类,完成配置、监听,再根据监听到的元素完成各种动作。

例如,下面这个案例:

MainActivity.java

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import com.example.accessibilityservicetest.R; public class MainActivity extends Activity {
private static String TAG="test"; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); //如果没开启,就提醒开启辅助功能
if(!isAccessibilitySettingsOn(this)){
Intent intent=new Intent(android.provider.Settings.ACTION_ACCESSIBILITY_SETTINGS);
startActivity(intent);
}
} //判断是否开启辅助功能
private boolean isAccessibilitySettingsOn(Context mContext) {
int accessibilityEnabled = 0;
final String service = getPackageName() + "/" + MyCustomAccessibilityService.class.getCanonicalName();
try {
accessibilityEnabled = Settings.Secure.getInt(
mContext.getApplicationContext().getContentResolver(),
android.provider.Settings.Secure.ACCESSIBILITY_ENABLED);
Log.v(TAG, "accessibilityEnabled = " + accessibilityEnabled);
} catch (Settings.SettingNotFoundException e) {
Log.e(TAG, "Error finding setting, default accessibility to not found: "
+ e.getMessage());
}
TextUtils.SimpleStringSplitter mStringColonSplitter = new TextUtils.SimpleStringSplitter(':'); if (accessibilityEnabled == 1) {
Log.v(TAG, "***ACCESSIBILITY IS ENABLED*** -----------------");
String settingValue = Settings.Secure.getString(
mContext.getApplicationContext().getContentResolver(),
Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
if (settingValue != null) {
mStringColonSplitter.setString(settingValue);
while (mStringColonSplitter.hasNext()) {
String accessibilityService = mStringColonSplitter.next(); Log.v(TAG, "-------------- > accessibilityService :: " + accessibilityService + " " + service);
if (accessibilityService.equalsIgnoreCase(service)) {
Log.v(TAG, "We've found the correct setting - accessibility is switched on!");
return true;
}
}
}
} else {
Log.v(TAG, "***ACCESSIBILITY IS DISABLED***");
} return false;
}
}

MainActivity.java

MyCustomAccessibilityService.java

public class MyCustomAccessibilityService extends AccessibilityService {
//该方法在初始化辅助功能时调用
@Override
protected void onServiceConnected() {
super.onServiceConnected();
}
//获取到指定的监听事件
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
//辅助功能的时间类型
int eventType=event.getEventType();
//输出事件的字符串type
String typeStr=event.eventTypeToString(eventType);
//根据事件类型来分发我们需要的操作,这里以窗口变化为例
if(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED==eventType){
//判断我们的辅助功能,是否在约定的界面执行,以设置界面为例
if("com.android.settings".equals(event.getPackageName())){
//doSometing
}
}else if(AccessibilityEvent.TYPE_GESTURE_DETECTION_START==eventType){ }else{
//在完成自己的操作时候,可以关闭自己的服务,下次使用再开启
//API>=24
//disableSelf()
}
//通过event遍历nodeInfo
AccessibilityNodeInfo info= event.getSource();
//findFocus(int)
//getWindows()
//getRootInActiveWindow() //遍历节点
for(int i=0;i<info.getChildCount();i++){
AccessibilityNodeInfo childNode= info.getChild(i);
//获取子节点中的某个特定node,一下通过id查找
List<AccessibilityNodeInfo> list = childNode.findAccessibilityNodeInfosByViewId("com.android" +".settings:id/xxxx");
// 通过text查找
//List<AccessibilityNodeInfo> list = info.findAccessibilityNodeInfosByText("xxxx");
Log.i("InfoType",childNode.getClassName().toString());
Log.i("InfoText", childNode.getText().toString());
Log.i("InfoPkgName",childNode.getPackageName().toString());
Log.i("InfoViewId", childNode.getViewIdResourceName()); //进行点击操作
for(AccessibilityNodeInfo anodeinfo : list){
if(anodeinfo.isClickable()){
anodeinfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
}
}
//辅助功能被中断时候调用该方法
@Override
public void onInterrupt() {
}
}

MyCustomAccessibilityService.java

acessibilityserviceconfig.xml

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

acessibilityserviceconfig.xml

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.accessibilityservicetest"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.accessibilityservicetest.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name="com.example.accessibilityservicetest.MyCustomAccessibilityService"
android:label="@string/app_name"
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/acessibilityserviceconfig"/>
</service>
</application>
</manifest>

AndroidManifest.xml

上面的acessibilityserviceconfig.xml文件是关于这次辅助功能的配置信息,在下面做出如下说明:
AccessibilityEventTypes 此服务希望接收的事件类型
constant     value     描述
typeAllMask     ffffffff     所有类型的事件
typeAnnouncement     4000     一个应用产生一个通知事件
typeAssistReadingContext     1000000     辅助用户读取当前屏幕事件
typeContextClicked     800000     view中上下文点击事件
typeGestureDetectionEnd     80000     监测到的手势事件完成
typeGestureDetectionStart     40000     开始手势监测事件
typeNotificationStateChanged     40     收到notification弹出消息事件
typeTouchExplorationGestureEnd     400     触摸浏览事件完成
typeTouchExplorationGestureStart     200     触摸浏览事件开始
typeTouchInteractionEnd     200000     用户触屏事件结束
typeTouchInteractionStart     100000     触摸屏幕事件开始
typeViewAccessibilityFocusCleared     10000     无障碍焦点事件清除
typeViewAccessibilityFocused     8000     获得无障碍的焦点事件
typeViewClicked     1     点击事件
typeViewFocused     8     view获取到焦点事件
typeViewHoverEnter     80     一个view的悬停事件
typeViewHoverExit     100     一个view的悬停事件结束,悬停离开该view
typeViewLongClicked     2     view的长按事件
typeViewScrolled     1000     view的滚动事件,adapterview、scrollview
typeViewSelected     4     view选中,一般是具有选中属性的view,例如adapter
typeViewTextChanged     10     edittext中文字发生改变的事件
typeViewTextSelectionChanged     2000     edittext文字选中发生改变事件
typeViewTextTraversedAtMovementGranularity     20000     UIanimator中在一个视图文本中进行遍历会产生这个事件,多个粒度遍历文本。一般用于语音阅读context
typeWindowContentChanged     800     窗口的内容发生变化,或者更具体的子树根布局变化事件
typeWindowStateChanged     20     新的弹出层导致的窗口变化(dialog、menu、popupwindow)
typeWindowsChanged     400000     屏幕上的窗口变化事件,需要API 21+

accessibilityFeedbackType 此服务提供的反馈类型
constant     value     描述
feedbackAllMask     ffffffff     取消所有的可用反馈方式
feedbackAudible     4     可听见的(非语音反馈)
feedbackGeneric     10     通用反馈
feedbackHaptic     2     触觉反馈(震动)
feedbackSpoken     1     语音反馈
feedbackVisual     8     视觉反馈

accessibilityFlags 辅助功能附加的标志,多个使用 ' | '分隔
constant     value     描述
flagDefault     1     默认的配置
flagEnableAccessibilityVolume     80     这个标志要求系统内所有的音频通道,使用由STREAM_ACCESSIBILTY音量控制USAGE_ASSISTANCE_ACCESSIBILITY
flagIncludeNotImportantViews     2     表示可获取到一些被表示为辅助功能无权获取到的view
flagReportViewIds     10     使用该flag表示可获取到view的ID
flagRequestAccessibilityButton     100     如果辅助功能可用,提供一个辅助功能按钮在系统的导航栏 API 26+
flagRequestEnhancedWebAccessibility     8     此类扩展的目的是为WebView中呈现的内容提供更好的辅助功能支持。这种扩展的一个例子是从一个安全的来源注入JavaScript。如果至少有一个具有此标志的辅助功能服务, 则系统将使能增强的web辅助功能。因此, 清除此标志并不保证该设备不会使能增强的web辅助功能, 因为可能有另一个使能的服务在使用它。
flagRequestFilterKeyEvents     20     能够监听到系统的物理按键
flagRequestFingerprintGestures     200     监听系统的指纹手势 API 26+
flagRequestTouchExplorationMode     4     系统进入触控探索模式。出现一个鼠标在用户的界面
flagRetrieveInteractiveWindows     40     该标志知识的辅助服务要访问所有交互式窗口内容的系统,这个标志没有被设置时,服务不会收到TYPE_WINDOWS_CHANGE事件。

canRequestEnhancedWebAccessibility(boolean)
辅助功能服务是否能够请求WEB辅助增强的属性。例如: 安装脚本以使应用程序内容更易于访问。

canRequestFilterKeyEvents(boolean)
辅助功能服务是否能够请求过滤KeyEvent的属性,是否可以请求KeyEvent事件流。flagRequestFilterKeyEvents搭配使用

canRequestTouchExplorationMode (boolean)
此属性用于,能够让辅助功能服务通过手势,来请求触摸浏览模式,其被触摸的项,将被朗读出来,flagRequestTouchExplorationMode搭配使用

canRetrieveWindowContent (boolean)
辅助功能服务是否能够取回活动窗口内容的属性。 与上边的flagRetrieveInteractiveWindows搭配使用,无法在运行时更改此设置。

description
辅助功能服务目的或行为的简短描述。

notificationTimeout
同一类型的两个辅助功能事件发送到服务的最短间隔(毫秒,两个辅助功能事件之间的最小周期)

packageNames
从此服务能接收到事件的软件包名称 (不适合所有软件包)(多个软件包用逗号分隔)。

settingsActivity
允许用户修改辅助功能的activity组件名称

summary
同description

可以通过DDMS来查看手机界面的节点元素的各种信息:

原文链接:https://www.jianshu.com/p/ef01ce654302

【Android】解析AccessibilityService(辅助服务)的使用的更多相关文章

  1. Android AccessibilityService(辅助服务) 使用示例

    1.前言 网上关于Android辅助服务的使用方式已经非常丰富了,所以也不在乎再多我这一篇了:-D.有同学说这是重复造轮子,题主很同意,但反过来说,如果自己没有能力造出轮子,还对重复造轮子嗤之以鼻,那 ...

  2. Android Service完全解析,关于服务你所需知道的一切(下)

    转载请注册出处:http://blog.csdn.net/guolin_blog/article/details/9797169 在上一篇文章中,我们学习了Android Service相关的许多重要 ...

  3. Android Service完全解析,关于服务你所需知道的一切(上)

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/11952435 相信大多数朋友对Service这个名词都不会陌生,没错,一个老练的A ...

  4. 【转】Android Service完全解析,关于服务你所需知道的一切(下) ---- 不错

    原文网址:http://blog.csdn.net/guolin_blog/article/details/9797169 转载请注册出处:http://blog.csdn.net/guolin_bl ...

  5. [转]Android Service完全解析,关于服务你所需知道的一切

      目录(?)[+] Android Service完全解析,关于服务你所需知道的一切(上) 分类: Android疑难解析2013-10-31 08:10 6451人阅读 评论(39) 收藏 举报 ...

  6. (转) Android Service完全解析,关于服务你所需知道的一切(上)

    相信大多数朋友对Service这个名词都不会陌生,没错,一个老练的Android程序员如果连Service都没听说过的话,那确实也太逊了.Service作为Android四大组件之一,在每一个应用程序 ...

  7. Android Service完全解析,关于服务你所需知道的一切(下) (转载)

    转自:http://blog.csdn.net/guolin_blog/article/details/9797169 转载请注册出处:http://blog.csdn.net/guolin_blog ...

  8. Android Service完全解析,关于服务你所需知道的一切(上) (转载)

    转自:http://blog.csdn.net/guolin_blog/article/details/11952435 转载请注明出处:http://blog.csdn.net/guolin_blo ...

  9. 注意android辅助服务事件不能用于保存

    本来希望把来自辅助服务的事件,像epoll那样暂存在队列进行调度,或者做成事件堆栈,从而将辅助服务事件加入到容器.但是一直不能达到预期的后果.最后才发现一个坑人的事实,辅助服务事件被释放(或者说重置) ...

随机推荐

  1. spring cloud 详解

    https://www.cnblogs.com/qdhxhz/p/9601170.html SpringCloud(8)---zuul权限校验.接口限流 https://blog.csdn.net/c ...

  2. 牛客练习赛35-背单词-线性DP

    背单词 思路 :dp[ i ]  [ 0 ]表示 第i 位放的元音  dp[ i ]  [ 1 ]表示 第i 位放的辅音 ,cnt [ i ]含义是 长度为 i 的方案数. 转移  :dp[ i ]  ...

  3. asp.net core 依赖注入实现全过程粗略剖析(2)

    接着 上篇 目前也算是交代清楚了相关的类.那么框架具体是如何来实例化的呢?整个的流程是怎么样的. 我们参考源码中的Test文件夹来看看: var collection = new ServiceCol ...

  4. Java性能调优zz

    写Java也有n年了,现在还是有不少的坏的代码习惯,也通过学习别人的代码学到了不少好的习惯.这篇文章主要是整理的资料.留给自己做个警戒,提示以后写代码的时候注意!在文章的后面,会提供整理的原材料下载. ...

  5. javascript中6种基本数据类型详解

    javascript中有5中数据类型(也称为基本数据类型):Undefined.Null.Boolean.Number和String,还有一种复杂数据类型——object,object本质是由一组键值 ...

  6. BZOJ.1566.[NOI2009]管道取珠(DP 思路)

    BZOJ 洛谷 考虑\(a_i^2\)有什么意义:两个人分别操作原序列,使得得到的输出序列都为\(i\)的方案数.\(\sum a_i^2\)就是两人得到的输出序列相同的方案数. \(f[i][j][ ...

  7. phpmyadmin#1045 无法登录 MySQL 服务器

    使用lnmp安装wordpress在登录phpmyadmin数据库的时候诡异的出现了   phpmyadmin#1045 无法登录 MySQL 服务器,解决方法如下: 1 修改root的密码—不可以行 ...

  8. 潭州课堂25班:Ph201805201 django框架 第九课 模型补充 博客小案例 (课堂笔记)

    聚合查询: 分组查询: annotate() 方法 例:查询某学院学生人数,(一对多查询) 以字典的形式输出 annotate(统计 ‘关联学生字段 出现的次,).字典形式(键,值) 例:查询每项课程 ...

  9. 04 树莓派截图软件scrot的安装和使用

    2017-08-22 13:52:52 sudo apt-get install scrot 捕捉活动窗口(按下回车后,3秒之内点击要捕捉的窗口): scrot -d 3 -u 捕捉选定的区域(按下回 ...

  10. BZOJ5101 : [POI2018]Powód

    求出Kruskal重构树,那么重构树上每个点的取值范围是定的. 考虑树形DP,则对于一个点,要么所有点水位相同,要么还未发生合并. 故$dp[x]=up[x]-down[x]+1+dp[l[x]]\t ...