吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 6179|回复: 46
收起左侧

[Android 原创] 安卓自动化之无障碍模式

  [复制链接]
后脑i 发表于 2023-2-15 14:43
本帖最后由 后脑i 于 2023-2-17 09:12 编辑

预计阅读时间5分钟

MIUI14更新后,李跳跳等工具便出现问题,为了满足使用的需求,便开始研究实现过程,下面是学习记录,解决方案请直接跳至第6点。

1.AccessibilityService无障碍服务

无障碍服务主要是用来协助残障用户更好的使用手机,但是各位大佬基于无障碍服务开发了很多玩法,例如抢红包、跳广告等,接下来我们新建个项目来实现跳广告功能。

1.1 创建服务
class MyAccessibilityService : AccessibilityService() {
    private val TAG = javaClass.simpleName
    override fun onAccessibilityEvent(event: AccessibilityEvent?) {
        Log.e(TAG, "onAccessibilityEvent$event")
        if (event?.eventType == TYPE_WINDOW_CONTENT_CHANGED) {
            if (event.className == "android.widget.TextView") {
                //获取跳过按钮并点击
                try {
                    val nodeInfo = rootInActiveWindow
                    if (nodeInfo != null) {
                        skip(nodeInfo, "跳过")
                    }
                } catch (e: Error) {
                    Log.e(TAG, "$e")
                }
            }
        }
    }

    /**
     * 匹配跳过规则
     */
    private fun skip(nodeInfo: AccessibilityNodeInfo?, str: String?) {
        val nodeInfoList = nodeInfo?.findAccessibilityNodeInfosByText(str)
        if (nodeInfoList == null || nodeInfoList.isEmpty()) {
            //页面跳转过程中,有可能获取不到
            return
        }
        for (info in nodeInfoList) {
            val charSequence = info.text
            if (charSequence != null) {
                val msg = charSequence.toString()
                if (msg.contains("跳过")) {
                    info.performAction(ACTION_CLICK)
                    Toast.makeText(this, "跳过广告", Toast.LENGTH_SHORT).show()
                }
            }
        }
    }

    override fun onInterrupt() {
    }
}
1.2配置服务

res目录下新建service_config.xml文件,名称可以自定义下一步会用到

<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeAllMask"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:canRetrieveWindowContent="true"
    android:accessibilityFlags="flagDefault"
    android:canRequestTouchExplorationMode="true"
    android:description="@string/app_name"
    android:notificationTimeout="100"/>
1.3 添加清单文件
<service android:name=".MyAccessibilityService"
    android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
    android:exported="false">
    <intent-filter>
        <action android:name="android.accessibilityservice.AccessibilityService" />
    </intent-filter>
    <meta-data android:name="android.accessibilityservice"
        android:resource="@xml/service_config" />
</service>
1.4 启动服务
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    //跳转无障碍模式设置界面
    startActivity(Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS))
}
2.实现无障碍功能

gif动画

gif动画

3.获取UI布局
3.1 findAccessibilityNodeInfosByText

在1.1中使用findAccessibilityNodeInfosByText来进行模糊匹配,为了满足精准匹配的需求,我们也可以通过获取id来实现(findAccessibilityNodeInfosByViewId)

3.2 findAccessibilityNodeInfosByViewId

使用uiautomatorviewer工具分析app界面

注:工具路径 在安卓sdk中 C:\Users\XX\AppData\Local\Android\Sdk\tools\bin\uiautomatorviewer.bat

运行的命令框请勿关闭

详情

详情

private fun skip(nodeInfo: AccessibilityNodeInfo?) {
    val nodeInfoList = nodeInfo?.findAccessibilityNodeInfosByViewId("com.moutai.mall:id/tvSkip")
    if (nodeInfoList == null || nodeInfoList.isEmpty()) {
        //页面跳转过程中,有可能获取不到
        return
    }
    for (info in nodeInfoList) {
        info.performAction(ACTION_CLICK)
        Toast.makeText(this, "跳过广告", Toast.LENGTH_SHORT).show()
    }
}
3.3 遍历父节点

通过获取父节点的AccessibilityWodeInfo,再通过该对象的getChild 方法来查询目标节点

private fun findInfo(
    info: AccessibilityNodeInfo?,
    str: String?,
): AccessibilityNodeInfo? {
    if (info == null) return null
    if (info.childCount == 0) {
        if (info.text!=null){
            if (info.text.toString().contains(str!!)) {
                info.performAction(ACTION_CLICK)
                Log.e("findInfo","$info")
            }
            return info
        }
    } else {
        for (i in 0 until info.childCount) {
            findInfo(info.getChild(i), str)
        }
    }
    return null
}
4.遇到的问题
4.1  android findAccessibilityNodeInfosByViewId return null although the node id exists

遇到这个问题时排查下获取nodeInfo是不是根活动视图,如果没有解决,再看下配置文件accessibilityEventTypes中的设置

最开始出现是使用event!!.source来获取,该方法是获取当前界面的可访问节点信息,但在跳转过程中有可能获取不到。

5.防范方式
1. 重写TextView的findViewsWithText方法
2. Event干扰
3. 使用onTouch代替onClick
6.MIUI14使用跳过功能

进入开发者选项--》启用MIUI功能--》关闭--》开启无障碍模式--》开启跳过广告的app--》重新启用MIUI功能

亲测使用正常!

以上就是无障碍服务的学习过程,如果有好的建议和想法可以留言或者私信,如果想深入了解可以访问官方文档,方便的话给个赞或者评分吧。

免费评分

参与人数 12威望 +1 吾爱币 +31 热心值 +12 收起 理由
junjia215 + 1 + 1 用心讨论,共获提升!
ygr233 + 1 + 1 我很赞同!
恶搞大王 + 2 + 1 我很赞同!
正己 + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
Lucky8663 + 1 + 1 我很赞同!
smilingk + 1 + 1 用心讨论,共获提升!
zhangxiaoxiao + 1 用心讨论,共获提升!
笙若 + 1 + 1 谢谢@Thanks!
lfm333 + 1 + 1 谢谢@Thanks!
SysEntry + 1 + 1 鼓励转贴优秀软件安全工具和文档!
爱窜洞的闰土 + 1 + 1 谢谢@Thanks!
偶说了算 + 1 + 1 用心讨论,共获提升!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

thatCbin 发表于 2023-2-15 16:36
zhang7069 发表于 2023-2-15 16:27
丶汇梦 发表于 2023-2-15 15:00
Pwaerm 发表于 2023-2-15 15:16
丶汇梦 发表于 2023-2-15 15:00
李跳跳工具还有什么

auto.js 也可以,但需要自己写脚本。
头像被屏蔽
夏520 发表于 2023-2-15 15:51
提示: 作者被禁止或删除 内容自动屏蔽
j717013225 发表于 2023-2-15 15:55
很及时,我搞了好几次自动任务软件也没搞定,
dlovec 发表于 2023-2-15 16:10
学习基础知识  爱了
 楼主| 后脑i 发表于 2023-2-15 16:34
夏520 发表于 2023-2-15 15:51
现在的手机,无障碍服务都是不是长久开启的,重启手机或者过10分钟时间就自动关闭服务了,没得玩呢

是的,重启后基本上需要用户手动开启,根据不同的用户使用需求,可以采取后台保活的方式。
thatCbin 发表于 2023-2-15 16:38
比如视频中间暂停后出现广告也能实现关闭
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-28 03:24

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表