Android AccessibilityService实现第三方APP行为捕获

AccessibilityService实现行为捕获

语音:Kotlin            版本:1.2.41
最近接到一个很奇葩的需求:捕获系统语音通话聊天(包括微信、电话、QQ),把通话内容记录成音频文件上传到服务端。
接到需求的第一时间当然是度娘谷歌一阵,一顿乱搜之后发现并没有太多能够用来参考的文献。
没有现成的轮子可用,只能撸起袖子,自己动手丰衣足食。

AccessibilityService简介

AccessibilityService中文翻译为辅助服务,它能够帮助我们获取第三方应用的操作信息。
AccessibilityService的所带来的安全隐患在这里不多赘述,主要介绍一些关于它的特性和用法。
本文章将用大家常用的微信来举例,获取微信语音通话界面的控件布局,提取到关键常量之后,用AccessibilityService来捕获。
先来看一段官方对AccessibilityService的描述:

Accessibility services should only be used to assist users with disabilities in using Android devices and apps. They run in the background and receive callbacks by the system when AccessibilityEvents are fired. Such events denote some state transition in the user interface, for example, the focus has changed, a button has been clicked, etc. Such a service can optionally request the capability for querying the content of the active window. Development of an accessibility service requires extending this class and implementing its abstract methods.

Lifecycle

The lifecycle of an accessibility service is managed exclusively by the system and follows the established service life cycle. Starting an accessibility service is triggered exclusively by the user explicitly turning the service on in device settings. After the system binds to a service, it calls onServiceConnected(). This method can be overridden by clients that want to perform post binding setup.

An accessibility service stops either when the user turns it off in device settings or when it calls disableSelf().

从描述中我们可以得到如下几个信息:

1.AccessibilityService只能用于帮助残障人士使用Android设备和应用;

2.运行在后台,可以实现无感知运作;

3.能够监测焦点的切换、点击等事件;

4.APP只能对其进行注册,无法自动开启;

5.启动AccessibilityService需要用户进入“设置-无障碍”手动开启,关闭亦是如此。

放上官方文档的链接(需爬梯):
https://developer.android.com/reference/android/accessibilityservice/AccessibilityService


AccessibilityService基本配置方式

创建MyAccessibilityService继承AccessibilityService

覆写onServiceConnected、onAccessibilityEvent、onInterrupt方法。

三个方法分别为AccessibilityService的三个生命周期。

可以大致理解为“服务启动时”、“服务监听中”、“断开服务”

/*
 * Create by parker
 * Author: parker
 * Create: 2018/12/7 10:48 AM
 *
 */
class MyAccessibilityService : AccessibilityService() {

    override fun onServiceConnected() {
        super.onServiceConnected()
    }

    override fun onAccessibilityEvent(event: AccessibilityEvent) {

    }

    override fun onInterrupt() {

    }
}
在AndroidManifest.xml中注册:
    <service
        android:name=".MyAccessibilityService"
        android:enabled="true"
        android:exported="false"
        android:label="@string/my_as"
        android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
        android:process=":BackgroundService">
        <intent-filter>
            <action android:name="android.accessibilityservice.AccessibilityService" />
        </intent-filter>
        <meta-data
            android:name="android.accessibilityservice"
            android:resource="@xml/accessibility_config" />
    </service>
在res下新建accessibility_config.xml文件:
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeAllMask"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:canRetrieveWindowContent="true"
    android:notificationTimeout="100"
    android:description="@string/description"
    android:packageNames="com.tencent.mm" />
属性作用如下:

android:description :辅助功能描述,描述该辅助功能用来干嘛的
android:packageNames :指定辅助功能监听的包名,不指定表示监听所有应用
android:accessibilityEventTypes:辅助功能处理事件类型,一般配置为typeAllMask表示接收所有事件
android:accessibilityFlags:辅助功能查找截点方式,一般配置为flagDefault默认方式。
android:accessibilityFeedbackType:操作相应按钮以后辅助功能给用户的反馈类型,包括声音,震动等。
android:notificationTimeout:相应时间设置
android:canRetrieveWindowContent:是否允许辅助功能获得窗口的节点信息,为了能正常实用辅助功能,请务必保持该项配置为true

配置完成后将demo跑进测试机器

进入 设置→辅助服务→无障碍

如果在“无障碍”下出现我们配置的服务,表示配置成功


实现微信语音电话状态监听

监听工作流程如下:
·捕获微信进入聊天状态
·启动语音录制服务
·捕获微信退出聊天状态
·退出语音录制服务

首先需要借助工具来分析微信的布局。通过捕获微信布局中的关键常量,来判断微信当前的状态。

布局分析工具

谷歌在AS 3.0之后,取消老旧的DDMS,为我们提供了界面更为友好的全新工具:LayoutInspector

打开方式:Tools → Lyaout Inspector 如图:

屏幕快照 2018-12-07 上午11.37.37.png

点击之后,系统弹出Choose Porcess提示我们选择需要监听的进程,这里我们选择微信,先不要点“OK”:

屏幕快照 2018-12-07 下午1.28.41.png

在微信上启动语音聊天,然后点击Choose Process的OK,选择VideoActivity,如图:

屏幕快照 2018-12-07 下午1.30.13.png

捕获到的微信聊天界面的布局如图所示:

屏幕快照 2018-12-07 下午1.33.05.png

通过分析左边的View Tree我们发现,微信中提示已接通、通话结束等状态的控件id为eg7.
这是一个很有用的发现,它的文本内容可以直接作为判断微信通话是否连接或者断开的依据。


ok 知道了微信语音聊天了开始和结束的状态判定依据,接下来就是用代码来实现监听的过程。

核心代码如下:

override fun onAccessibilityEvent(event: AccessibilityEvent){
    //获取当前界面的布局信息
    val noteInfo: AccessibilityNodeInfo = when {
        rootInActiveWindow != null -> rootInActiveWindow
        event.source != null -> event.source
        else -> return
    }

    //获取id为eg7的控件  并根据内容执行相应的操作
    val wechatToast = noteInfo.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/eg7")
    //如果id为eg7的控件存在
    if (wechatToast.size>0){
        //判断这个控件的内容
        if (wechatToast[0].text.toString() == "已接通"){
            //此时语音聊天已经接通
            //TODO:do something you want
        }else if (wechatToast[0].text.toString().contains("聊天结束")){
            //此时语音聊天已经结束
            //TODO:do something you want
        }
    }
}

至此,微信聊天状态已经捕获完成,TODO处可实现语音录制相关代码。
语音录制过程会在下一篇文章中详细介绍。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,802评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,109评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,683评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,458评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,452评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,505评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,901评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,550评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,763评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,556评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,629评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,330评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,898评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,897评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,140评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,807评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,339评论 2 342

推荐阅读更多精彩内容

  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,680评论 2 59
  • afinalAfinal是一个android的ioc,orm框架 https://github.com/yangf...
    wgl0419阅读 6,263评论 1 9
  • 1、 github排名 https://github.com/trending,github搜索:https://...
    GB_speak阅读 9,730评论 2 118
  • 迎合规后,投之人会走的更远 网贷职业自2007年进入我国以来...
    kenan806阅读 173评论 0 0
  • 连续几天自己没有能够坚持打坐,反而是在浪费时间在无意义的网络上面,也是没有打坐的几天自己感觉到内心不平静,好像是一...
    吾宗老孙子阅读 297评论 0 1