【Android】解析AccessibilityService(辅助服务)的使用
辅助功能是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(辅助服务)的使用的更多相关文章
- Android AccessibilityService(辅助服务) 使用示例
1.前言 网上关于Android辅助服务的使用方式已经非常丰富了,所以也不在乎再多我这一篇了:-D.有同学说这是重复造轮子,题主很同意,但反过来说,如果自己没有能力造出轮子,还对重复造轮子嗤之以鼻,那 ...
- Android Service完全解析,关于服务你所需知道的一切(下)
转载请注册出处:http://blog.csdn.net/guolin_blog/article/details/9797169 在上一篇文章中,我们学习了Android Service相关的许多重要 ...
- Android Service完全解析,关于服务你所需知道的一切(上)
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/11952435 相信大多数朋友对Service这个名词都不会陌生,没错,一个老练的A ...
- 【转】Android Service完全解析,关于服务你所需知道的一切(下) ---- 不错
原文网址:http://blog.csdn.net/guolin_blog/article/details/9797169 转载请注册出处:http://blog.csdn.net/guolin_bl ...
- [转]Android Service完全解析,关于服务你所需知道的一切
目录(?)[+] Android Service完全解析,关于服务你所需知道的一切(上) 分类: Android疑难解析2013-10-31 08:10 6451人阅读 评论(39) 收藏 举报 ...
- (转) Android Service完全解析,关于服务你所需知道的一切(上)
相信大多数朋友对Service这个名词都不会陌生,没错,一个老练的Android程序员如果连Service都没听说过的话,那确实也太逊了.Service作为Android四大组件之一,在每一个应用程序 ...
- Android Service完全解析,关于服务你所需知道的一切(下) (转载)
转自:http://blog.csdn.net/guolin_blog/article/details/9797169 转载请注册出处:http://blog.csdn.net/guolin_blog ...
- Android Service完全解析,关于服务你所需知道的一切(上) (转载)
转自:http://blog.csdn.net/guolin_blog/article/details/11952435 转载请注明出处:http://blog.csdn.net/guolin_blo ...
- 注意android辅助服务事件不能用于保存
本来希望把来自辅助服务的事件,像epoll那样暂存在队列进行调度,或者做成事件堆栈,从而将辅助服务事件加入到容器.但是一直不能达到预期的后果.最后才发现一个坑人的事实,辅助服务事件被释放(或者说重置) ...
随机推荐
- DDoS攻击与防御(1)
分布式拒绝服务攻击的精髓是,利用分布式的客户端,向服务提供者发起大量看似合法的请求,消耗或长期占用大量资源,从而达到拒绝服务的目的.从不同的角度看,分布式拒绝服务攻击的方法有不同的分类标准.依据消耗目 ...
- python数据结构之插入排序
插入排序(英语:Insertion Sort)是一种简单直观的排序算法.它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入.插入排序在实现上,在从后向前扫描 ...
- Newtonsoft.Json日期转换
在使用EasyUI做后台时,使用表格datagrid,用Newtonsoft.Json转换为Json格式后,时间显示为2013-06-15 T00:00:00形式. 后来研究了一下Newtonsoft ...
- SpringBoot+Mybatis+MySql学习
介绍一下SpringBoot整合mybatis,数据库选用的是mysql. 首先创建数据库 CREATE DATABASE test; 建表以及插入初始数据(sql是从navicat中导出的) SET ...
- Xamarin Essentials教程发送邮件Email
Xamarin Essentials教程发送邮件Email 邮件是一种更为灵活的数据分享方式.它可以帮助用户将一个应用程序的数据分享给其他用户,而其他用户不需要安装特定的应用程序,就可以在任意时间 ...
- 在Windows系统下安装Beautiful Soup4的步骤和方法
1.到http://www.crummy.com/software/BeautifulSoup/网站上上下载,最新版本是4.3.2. 2.下载完成之后需要解压缩,假设放到D:/python下. 3.运 ...
- Vue子页面给父页面传递数据
子页面: <template> <div> <p>子组件</p> <button @click="sendMsg">传递 ...
- 护眼党必备良心app
这几天用电脑用得厉害,眼睛经常感到疲劳,寻思着买个好点的蓝光眼镜.本来已经看上一个100+RMB的“高端”防蓝光眼镜,结果逛知乎发现了这两个app,能直接让电脑和手机屏幕过滤掉蓝光从而有效缓解视觉疲劳 ...
- FPGA - 认识FPGA
一.何为FPGA? FPGA,英文全拼:Field-Programmable Gate Array 现场可编程门阵列,它是在PAL.GAL.CPLD等可编程器件的基础上进一步发展的产物.它是作为专用集 ...
- BZOJ3324 : [Scoi2013]火柴棍数字
为了使数字最大,首先要最大化其位数. 设$f[i][j][k]$表示从低到高考虑了$i$位,手头火柴棍个数为$j$,第$i$位是不是$0$时,最少移动多少根火柴. 若$f[i][0][非0]\leq ...