本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布
前段时间看别人博客的时候偶然间看到了Android微信自动回复功能,最后的效果也很不错,博主在文中提到了AccessibilityService
,以前压根没接触过这东西,表示一脸懵逼。也是这个原因我去找了AccessibilityService相关的资料好好的看了一遍,发现这个东西真的太NB了,网上对AccessibilityService的应用还是有不少的文章的,但是详细的介绍资料还是比较少,对于刚刚学习这个的同学看完很多资料还是一脸茫然,于是才有了本文。我相信当你在看完本文之后,再去看前面的那篇文章,我相信会轻松很多。
本文学习目录
1.AccessibilityService是什么
2.AccessibilityService的创建与配置
3.怎么去使用AccessibilityService
4.一步一步构建一个apk自动安装器
1.AccessibilityService是什么
AccessibilityService是什么,官网是这样解释的
Accessibility services are intended to assist users with disabilities in using Android devices and apps. They run in the background and receive callbacks by the system whenAccessibilityEvents are fired.
也就是说这是个辅助功能,目的是辅助人们去使用Android设备和应用。它在后台运行,可以接收系统的回调。
可见AccessibilityService的出现Google的初衷是辅助人们去使用Android设备和应用,但是当你对它足够了解了之后你会发现它的作用不仅仅只是这样。对windows编程有了解的同学肯定知道hook(钩子),AccessibilityService和windows下的hook有那么一点的相似。AccessibilityService可以拦截到系统发出的一些消息(比如窗体状态的改变,通知栏状态的改变,View被点击了等等),当拦截到这些事件我们就可以去做一些我们想做的事儿了~~~
AccessibilityService能做些什么呢? 比如自动化测试、自动抢红包、自动安装等等。在带来便利的同时,也还是有需要注意的地方:当你开启了辅助功能之后会对你的隐私信息带来一些风险,所以还是需要谨慎的去开启第三方的辅助功能。当然这对于我们开发者而言都不是事,因为我们完全可以自己去开发属于我们的辅助功能。
2.AccessibilityService的创建与配置
第一步就是自己去创建一个类继承于AccessibilityService,并实现必须实现的两个方法
public class MyAccessibilityService extends AccessibilityService {
@Override
public void onAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
}
@Override
public void onInterrupt() {
}
}
随后就是在res/xml目录下新建一个xml文件(文件名随意),后面会对这个文件作详细的介绍。
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackGeneric"
android:canRetrieveWindowContent="true"
android:description="@string/my_accessibility_description"
android:notificationTimeout="100"
android:packageNames="com.tencent.mobileqq,com.android.packageinstaller" />
最后就是去配置清单文件了
<service
android:name=".service.MyAccessibilityService"
android:enabled="true"
android:exported="true"
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/my_services_config" />//在meta-data里申明配置信息
</service>
别忘记了添加权限
<uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />
到这我们就可以把应用跑到我们的手机上了,然后打开辅助功能,去开启我们刚刚创建的这个辅助功能。如下图:
当然因为什么都没做,开启了也没什么用,下面就去看看怎么使用吧!
3.怎么去使用AccessibilityService
先说说之前创建的那个xml文件中各个属性的含义吧
-
accessibilityEventTypes
: 用来设置响应事件的类型,比如typeAllMask就是响应全部事件,typeNotificationStateChanged就是响应通知状态的改变,如果需要响应多种事件类型可以以 ‘ | ’ 隔开。 -
accessibilityFeedbackType
: 给用户的反馈方式,比如语音、震动等,这里用处不大。 -
canRetrieveWindowContent
:是否可以获取活动窗体的内容,这个设置为true才可以取得窗体中的控件和事件源 -
description
:辅助功能的描述 -
notificationTimeout
:两个相同类型事件发送到服务的事件间隔,单位毫秒 -
packageNames
:指定响应某个应用的事件,取值为应用的包名,多个以‘ , ’ 隔开。没有此属性则表示响应全部应用。这里我填写的是手机qq和系统安装器的包名
然后进入到我们的MyAccessibilityService
中,定位到onAccessibilityEvent
方法编写如下代码
log("-------------------------------------------------------------");
int eventType = event.getEventType();//事件类型
log("packageName:" + event.getPackageName() + "");//响应事件的包名,也就是哪个应用才响应了这个事件
log("source:" + event.getSource() + "");//事件源信息
log("source class:" + event.getClassName() + "");//事件源的类名,比如android.widget.TextView
log("event type(int):" + eventType + "");
switch (eventType) {
case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:// 通知栏事件
log("event type:TYPE_NOTIFICATION_STATE_CHANGED");
break;
case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED://窗体状态改变
log("event type:TYPE_WINDOW_STATE_CHANGED");
break;
case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED://View获取到焦点
log("event type:TYPE_VIEW_ACCESSIBILITY_FOCUSED");
break;
case AccessibilityEvent.TYPE_GESTURE_DETECTION_START:
log("event type:TYPE_VIEW_ACCESSIBILITY_FOCUSED");
break;
case AccessibilityEvent.TYPE_GESTURE_DETECTION_END:
log("event type:TYPE_GESTURE_DETECTION_END");
break;
case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED:
log("event type:TYPE_WINDOW_CONTENT_CHANGED");
break;
case AccessibilityEvent.TYPE_VIEW_CLICKED:
log("event type:TYPE_VIEW_CLICKED");
break;
case AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED:
log("event type:TYPE_VIEW_TEXT_CHANGED");
break;
case AccessibilityEvent.TYPE_VIEW_SCROLLED:
log("event type:TYPE_VIEW_SCROLLED");
break;
case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED:
log("event type:TYPE_VIEW_TEXT_SELECTION_CHANGED");
break;
}
for (CharSequence txt : event.getText()) {
log("text:" + txt);//输出当前事件包含的文本信息
}
log("-------------------------------------------------------------");
log方法就是打印信息用的,是对Log的一个简单封装。
在运行一次程序,打开我们的手机qq可以看见输出日志如下
可以很清晰的看见当我们打开qq或触发很多的事件,第一个响应的事件是TYPE_WINDOW_STATE_CHANGED
,触发此事件的事件源是com.tencent.mobileqq.activity.SplashActivity
接着,当我点击最上面的 ‘ 电话 ’,会得到如下日志:
我就不一一截图操作的日志了,下来大家可以自行尝试。到这里你用该对onAccessibilityEvent
有了进一步的了解。
4.一步一步构建一个apk自动安装器
这一节来个实战的应用:做一个apk的自动安装器,点击apk文件即可开始自动安装。
国内的rom厂商大家都很清楚:百(sang)花(xin)齐(bing)放(kuang),已经把原生的rom改的面目全非。所以想做一个面对全部手机的apk的自动安装器还是比较麻烦的。我的手机是魅族的,下图是魅族手机apk安装的步骤(其他手机可能会略有不同,下来自己更改不同部分即可,这里主要讲解原理):
可以看见点击安装包之后会弹出一个确认框,点击继续之后会出现下一步,点击了下一步就可以点击安装了。我们要实现自动安装无非就是用程序的方式会对相关按钮的自动点击,难点就在于怎么去找到这些按钮并执行点击操作。
好了,下面我们可以来创建一个自动安装的服务了,步骤和第一节描述的一样将packageNames
指定成com.android.packageinstaller
就可以了。这里我们先别着急去实现功能(就算你想去实现,也摸不着头脑),我们还是像第二节那样去输出日志信息,查看日志输出信息(对响应事件信息的打印)是使用AccessibilityService的重点,看完日志的输出信息,然后对其分析,才会知道具体的操作。
我们来看看在安装apk文件时候输出的部分日志信息:
从日志信息中可以看出:
1.当我们点击了apk文件的时候,如果该文件已经存在,就会弹出一个对话框并且会响应TYPE_WINDOW_STATE_CHANGE
事件
2.当我们点击了继续之后就会响应TYPE_VIEW_CLICKED
事件,并且继续这个可以点击的View是个Button
3.接着点击下一步,同样也会响应TYPE_VIEW_CLICKED
事件,并且继续这个可以点击的View是个TextView。最后就可以点击安装了(安装那步忘了截图,和第3步相应的事件是一样的)
经过上面几步的分析,我想你应该对后面的逻辑还是比较清楚了,直接上代码
public class AutoInstallService extends AccessibilityService {
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
PrintUtils.printEvent(event);
findAndPerformActionButton("继续");
findAndPerformActionTextView("下一步");
findAndPerformActionTextView("安装");
}
private void findAndPerformActionButton(String text) {
if (getRootInActiveWindow() == null)//取得当前激活窗体的根节点
return;
//通过文字找到当前的节点
List<AccessibilityNodeInfo> nodes = getRootInActiveWindow().findAccessibilityNodeInfosByText(text);
for (int i = 0; i < nodes.size(); i++) {
AccessibilityNodeInfo node = nodes.get(i);
// 执行点击行为
if (node.getClassName().equals("android.widget.Button") && node.isEnabled()) {
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
}
private void findAndPerformActionTextView(String text) {
if (getRootInActiveWindow() == null)
return;
//通过文字找到当前的节点
List<AccessibilityNodeInfo> nodes = getRootInActiveWindow().findAccessibilityNodeInfosByText(text);
for (int i = 0; i < nodes.size(); i++) {
AccessibilityNodeInfo node = nodes.get(i);
// 执行按钮点击行为
if (node.getClassName().equals("android.widget.TextView") && node.isEnabled()) {
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
}
}
例子很简单,所以也没去对eventType做判断,当有其他需求的时候是需要对eventType做判断了,代码已经注释的比较详细,我就不再对代码作更多的讲解了,有疑问可以留言。
到这里你应该对AccessibilityService有了进一步的认识,会发现原来红包助手之类软件实现的原理就是利用AccessibilityService检测通知栏的状态,然后再去做一些处理。是不是有点自己去做一个红包助手的想法了?现在再去看看文章开始的那篇文章你的收获会更大:Android微信自动回复功能
补充说明
AccessibilityService中还有几个常用的方法 onServiceConnected、onInterrupt、onGesture。看名字大致也知道什么时候会被调用。
在onServiceConnected中可以去配置AccessibilityService的一些信息,也就是之前在xml文件可以在这里通过代码配置,不过这里没法配置canRetrieveWindowContent属性,刚开始也被这个坑了很久
@Override
protected void onServiceConnected() {
super.onServiceConnected();
PrintUtils.log("onServiceConnected");
// //可用代码配置当前Service的信息
// AccessibilityServiceInfo info = new AccessibilityServiceInfo();
// info.packageNames = new String[]{"com.android.packageinstaller", "com.tencent.mobileqq", "com.trs.gygdapp"}; //监听过滤的包名
// info.eventTypes = AccessibilityEvent.TYPES_ALL_MASK; //监听哪些行为
// info.feedbackType = AccessibilityServiceInfo.FEEDBACK_SPOKEN; //反馈
// info.notificationTimeout = 100; //通知的时间
// setServiceInfo(info);
}
相关推荐
为了在这个趣味的互动中抢占先机,许多开发者开始研究如何通过编程技术实现自动抢红包,于是便有了“微信抢红包插件”的诞生。本文将围绕“Codeboy微信抢红包”这一开源项目,详细讲解其核心原理与实现过程。 1. **...
为了帮助用户提高抢红包的成功率,一些开发者利用了Android系统的 AccessibilityService 技术开发了相应的辅助工具。虽然当前的微信版本已经对此进行了限制,但了解这种技术的原理仍然是有价值的。 Accessibility...
这个服务允许应用程序监听并响应用户与系统交互的各种事件,如焦点变化、窗口状态改变等,从而实现自动化操作,例如自动抢红包。以下是对实现原理的详细解析: 1. **AccessibilityService** 的使用 `Accessibility...
这款开源插件的出现,不仅方便了用户,也为开发者提供了一个学习和研究自动抢红包机制的平台。下面我们将深入探讨其主要功能、工作原理以及相关技术知识点。 1. **主要功能** - **实时监控**: 快手抢红包插件能...
本文将深入解析如何利用Android的无障碍服务(Accessibility Service)来实现自动抢红包的功能。 一、监听红包事件 抢红包的核心在于实时监听红包的到来。在Android中,这需要用到`AccessibilityService`。无障碍...
在这个应用中,开发者创建了一个AccessibilityService,该服务会监听微信的UI变化,当检测到红包相关信息时,触发相应的抢红包行为。 2. **事件监听**:无障碍服务需要能够识别屏幕上的各种事件,如按钮点击、文本...
总之,Android中的微信抢红包助手通过AccessibilityService实现了对微信应用的监控和自动化操作,使得程序能够在用户不知情的情况下自动抢红包。然而,这种技术也有其潜在问题,比如可能违反微信使用协议,因此在...
而"微信红包-5.0.1.zip"提供的是一款针对Android系统的微信自动抢红包的源码,允许用户在满足特定条件下自动化处理红包消息。这款源码的出现,为开发者提供了深入理解微信红包机制以及Android编程的机会,同时也引发...
在实现自动抢红包的过程中,插件通常会使用到以下关键技术: 1. **事件监听**:通过监听系统或微信应用的事件,如新消息通知,来判断何时有红包出现。 2. **UI自动化**:利用Android的AccessibilityService服务,...
作者:Leon这是一个自动化抢微信红包的源码,很简单的方式实现(找...当然原理很简单,过程很复杂,因为主要是用到AccessibilityService这个辅助服务,而网上关于这个用法也是很少讲解,都是靠自己一步一步研究出来。
E4A无障碍跨程序操作类库是一个专门为Android平台设计的工具包,它允许开发者在无需获取设备root权限的前提下,利用无障碍服务(Accessibility Service)来实现跨应用的操作。这个类库带有源码,提供了丰富的示例,...