利用AccessibilityService自动获取微信号(Android)
前言:
最近遇到一个需求,要求写一个小插件,能够自动在微信的页面弹出一个窗口,展示用户的相关信息(与我们公司有关的信息,方便运营快速了解用户信息)。
当时我第一反应是不可能,如果能够在别的app中获取对应的信息,那岂不是太不安全了。直到我知道了AccessibilityService这个东西。
基本思路:
利用AccessibilityService服务来获取到微信页面的页面信息,并获取到用户的微信号,有了微信号一切都好办了。
由于获取用户好友微信号和获取本人微信号的方法相同,因此此篇文章主要介绍的是如何通过AccessibilityService来获取本人的微信号。
过程:
AccessibilityService是什么?
在你的手机更多设置或者高级设置中,我们会发现有个无障碍的功能,很多人不知道这个功能具体是干嘛的,其实这个功能是为了增强用户界面以帮助残障人士,或者可能暂时无法与设备充分交互的人们。
它的具体实现是通过AccessibilityService服务运行在后台中,通过AccessibilityEvent接收指定事件的回调。这样的事件表示用户在界面中的一些状态转换,例如:焦点改变了,一个按钮被点击,等等。这样的服务可以选择请求活动窗口的内容的能力。简单的说AccessibilityService就是一个后台监控
服务,当你监控的内容发生改变时,就会调用后台服务的回调方法。
如何创建一个AccessibilityService?
实现一个自己的AccessibilityService,需要继承AccessibilityService类,并至少实现onAccessibilityEvent和onInterrupt方法:
public class MyAccessibilityService extends AccessibilityService {
final String TAG = "MyAccessibilityService";
/**
* 当服务启动的时候会被调用
*/
@Override
protected void onServiceConnected() {
super.onServiceConnected();
Log.d(TAG, "connected");
}
/**
* 监听窗口变化的回调
*/
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
Log.d(TAG, event.getPackageName() + "");
}
/**
* 中断服务的回调
*/
@Override
public void onInterrupt() {
Log.d(TAG, "onInterrupt");
}
}
AccessibilityService中的一些常用方法:
- disableSelf():禁用当前服务,服务可以通过该方法停止运行;
- findFocus(int focus):查找拥有特定焦点类型的控件;
- getRootInActiveWindow():如果配置能够获取窗口内容,则会返回当前活动窗口的根结点;
- getServiceInfo():获取当前服务的配置信息;
- onAccessibilityEvent(AccessibilityEvent event):有关AccessibilityEvent事件的回调函数,系统通过sendAccessibiliyEvent()不断的发送AccessibilityEvent到此处;
- performGlobalAction(int action):执行全局操作,比如返回,回到主页,打开最近等操作;
- setServiceInfo(AccessibilityServiceInfo info):设置当前服务的配置信息;
- onServiceConnected():系统成功绑定该服务时被触发,也就是当你在设置中开启相应的服务,系统成功的绑定了该服务时会触发,通常我们可以在这里做一些初始化操作;
- onInterrupt():服务中断时的回调。
声明该服务:
<service
android:name=".MyAccessibilityService"
android:enabled="true"
android:exported="true"
android:label="这是一个用户测试的无障碍服务"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
</service>
配置服务参数:
主要是用于声明该服务的一些配置参数,现在有两种配置服务参数的方法:在安卓4.0之后可以通过meta-data标签来在xml中配置,也可以通过动态代码直接配置。这里我们通过xml进行配置。
首先在res下的xml文件夹下创建配置文件,
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackAllMask"
android:canRetrieveWindowContent="true"
android:notificationTimeout="100"
android:packageNames="com.tencent.mm"
android:description="@string/description" />
然后将配置文件添加到清单文件中,
<service
android:name=".MyAccessibilityService"
android:enabled="true"
android:exported="true"
android:label="这是一个用户测试的无障碍服务"
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/config_accessibility" />
</service>
下面对xml中的一些参数进行介绍:
- accessibilityEventTypes:表示该服务对界面中的哪些变化感兴趣,即哪些事件通知,比如窗口打开,滑动,焦点变化,长按等。具体的值可以在AccessibilityEvent类中查到,如typeAllMask表示接受所有的事件通知;
- accessibilityFeedbackType:表示反馈方式,比如是语音播放,还是震动(此参数是必须的,不写的话不会走回调方法);
- canRetrieveWindowContent:表示该服务能否访问活动窗口中的内容.也就是如果你希望在服务中获取窗体内容的化,则需要设置其值为true;
- notificationTimeout:接受事件的时间间隔,通常将其设置为100即可;
- packageNames:表示对该服务是用来监听哪个包的产生的事件,这里以微信的包名为例(如果要监听的包有多个,则可以在代码中设置;如若不写,则监控的是所有的包);
- description:对该服务的无障碍描述。
如何开启AccessibilityService呢?
以小米手机为例,在设置中打开更多设置,进入无障碍。然后打开之前声明的服务即可。

如何获取微信“我的”页面的微信号呢?
这里主要利用AccessibilityNodeInfo的findAccessibilityNodeInfosByViewId(String viewId)方法,该方法用于根据控件标识来获取到整个控件。
那么问题来了,如何知道微信该控件的标识呢?这里可以通过SDK的工具DDMS工具。
进入SDK目录的tools目录,找到monitor.bat文件,双击即可。

进入DDMS界面后,选中微信的包名,并点击如下所示按钮即可分析当前微信页面的布局信息:

如下图,可以发现该控件的标识为:com.tencent.mm:id/czz

因此,即可通过如下方法获取到该控件的值:
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
Log.d(TAG, event.getPackageName() + ""); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
// 通过id获取到微信号的View
List<AccessibilityNodeInfo> nodeInfoList = getRootInActiveWindow().findAccessibilityNodeInfosByViewId("com.tencent.mm:id/czz");
String wxCode;
if (nodeInfoList != null && nodeInfoList.size() > 0) {
wxCode = nodeInfoList.get(0).getText().toString();
Log.d(TAG, wxCode);
}
} }
运行结果如下:

总结:
- 在过程中遇到了两个问题:第一个问题是运行完了之后服务已经开启,但是一直不走回调,经查是由于没有写accessibilityFeedbackType参数的原因;
- 第二个问题是,一开始通过Android Studio自带的Layout Inspector来获取控件的标识,当时获取的标识是czz,并不全,导致一直获取不到相应的微信号;
- 无障碍服务是一个很便携但是也很危险的服务,所以轻易不要给别人无障碍服务的权限;
- 不要轻易对一件事进行判断,需要进行了解之后才进行判断(在此之前我一直觉得该功能是无法实现的);
- 对于一个功能,第一反应应该是如何实现而不是如何推脱。
参考博客:
大家如果有什么疑问或者建议可以通过评论或者邮件的方式联系我,欢迎大家的评论~
利用AccessibilityService自动获取微信号(Android)的更多相关文章
- 微信公众平台开发—利用OAuth2.0获取微信用户基本信息
在借鉴前两篇获取微信用户基本信息的基础下,本人也总结整理了一些个人笔记:如何通过OAuth2.0获取微信用户信息 1.首先在某微信平台下配置OAuth2.0授权回调页面: 2.通过appid构造url ...
- asp.net 利用HttpWebRequest自动获取网页编码并获取网页源代码
/// <summary> /// 获取源代码 /// </summary> /// <param name="url"></param& ...
- Centos7(Linux)网络配置,自动获取ip地址
Centos7.0 Vmware 网络桥接配置,利用DHCP自动获取ip地址 首先要将Vmware10.0.3设置为桥接模式. CentOS 7.0默认安装好之后是没有自动开启网络连接的! cd / ...
- 微信公众号开发系列-获取微信OpenID
在微信开发时候在做消息接口交互的时候须要使用带微信加密ID(OpenId),下面讲讲述2中类型方式获取微信OpenID.接收事件推送方式和网页授权获取用户基本信息方式获取. 1.通过接收被动消息方式获 ...
- ASP.NET Core2实现静默获取微信公众号的用户OpenId
最近在做个微信公众号的项目,需要将入口放置在公众号二级菜单内,通过点击该菜单链接后进入到该项目中去,进入到项目后程序会自动通过微信公众号的API完成用户的OpenId获取.需求很简单,实现起来也不复杂 ...
- linux(以ubuntu为例)下Android利用ant自动编译、修改配置文件、批量多渠道,打包生成apk文件
原创,转载请注明:http://www.cnblogs.com/ycxyyzw/p/4555328.html 之前写过一篇<windows下Android利用ant自动编译.修改配置文件.批量 ...
- 第五篇 :微信公众平台开发实战Java版之如何获取公众号的access_token以及缓存access_token
一.access_token简介 为了使第三方开发者能够为用户提供更多更有价值的个性化服务,微信公众平台 开放了许多接口,包括自定义菜单接口.客服接口.获取用户信息接口.用户分组接口.群发接口等, 开 ...
- 微信公众号平台接口开发:基础支持,获取微信服务器IP地址
官方说明 目前看不出来这个接口有哪些具体运用,但是既然有这个接口,那我们就试试能不能用 访问接口 修改WeCharBase.cs,新增以下2个方法 public static string Serve ...
- 微信小程序+“芝麻小客服”可设自动关注公众号,助力运营闭环
微信小程序全面上线已经接近1年的时间,从最初的"用完即走"理念到2017年总计更新开放60余次的功能创新,微信小程序不一定会爆发下一次的红利,但绝对是微信生态中重要的一环. 芝麻小 ...
随机推荐
- WebWorker 简单使用方式
WebWorker 一定程度上可以算得上是浏览器中的多线程技术了,在项目中适当使用 Worker 来做一些耗时的操作能大大提高页面整体流畅度. Worker的使用也是非常简单的,通过向 Worker ...
- 一个小实例理解js 原型和继承
导语1:一个构造函数的原型对象,其实就是这个构造函数的一个属性而已,属性名叫prototype,值是一个对象,对象中有一些属性和方法,所以每个构造函数的实例对象都拥有这些属性和方法的使用权. 导语2: ...
- eclipse中运行出错:无法初始化主类的解决办法
问题描述:eclipse中运行程序时,出现如下错误 解决办法: 出现此类:无法初始化主类有可能是因为eclipse中Java的版本与JDK的版本不匹配,我开始用的时候eclipse中用的是Java s ...
- Api管家系列(二):编辑和继承Class
上篇写了个大概,今天我详细说一下参数的编辑,废话不多说 先打开一个项目,我要特别说一下设置里的“默认参数设置” 打开默认参数设置,这里我用红色圈出的tab可以设置请求头,返回头和返回状态,这些设置会在 ...
- Python爬虫 【requests】request for humans
安装 pip install requests 源码 git clone git://github.com/kennethreitz/requests.git 导入 import requests 发 ...
- Win7 + CentOS7 双系统
记录一下更改系统启动菜单的方法. 前提: 1. 先安装 Win7 在硬盘第一分区,其它分区在 Win7 下处于未分配状态. 2. 再安装 CentOS 到上述未分配分区.(注意:手动分区时,可以留一定 ...
- Devops step by step
接着上次分享的devops历程[Followme Devops实践之路], 大家希望能够出一个step by step手册, 那今天我就来和手把手来一起搭建这么一套环境, 演示整个过程! 实验环境需要 ...
- 【RL-TCPnet网络教程】第40章 RL-TCPnet之TFTP客户端(精简版)
第40章 RL-TCPnet之TFTP客户端 本章节为大家讲解RL-TCPnet的TFTP客户端应用,学习本章节前,务必要优先学习第38章的TFTP基础知识.有了这些基础知识之后,再搞本章节 ...
- 总结Java常用到的六个加密技术和代码
加密,是以某种特殊的算法改变原有的信息数据,使得未授权的用户即使获得了已加密的信息,但因不知解密的方法,仍然无法了解信息的内容.大体上分为双向加密和单向加密,而双向加密又分为对称加密和非对称加密(有些 ...
- 最短路问题之Bellman-ford算法
题目: 最短路:给定两个顶点,在以这两个点为起点和终点的路径中,边的权值和最小的路径.考虑权值为点之间的距离. 单源最短路问题,Bellman-ford算法 思路:每次循环检查所有边,可优化. 应用于 ...