news 2026/10/14 16:34:05

SKIP:正确启用安卓无障碍服务并理解其在自动跳过开屏广告中的工作机制

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SKIP:正确启用安卓无障碍服务并理解其在自动跳过开屏广告中的工作机制
  • 移动开发
  • 原生移动
  • GUI 自动化

【免费下载链接】SKIP

自动跳过APP开屏广告

项目地址:https://gitcode.com/gh_mirrors/ski/SKIP
点击查看免费下载

本文以 SKIP 官方文档《启用无障碍服务》为骨架,完整讲解在 Android 系统中启用 SKIP 无障碍服务的两步操作(点击屏幕中央按钮、在系统无障碍页面打开「使用"SKIP"」开关),并进一步结合仓库源码剖析服务声明、状态判定与自动点击手势的底层实现。读完后,你不仅能按步骤完成启用,还能理解 SKIP 从「服务连接」到「识别开屏广告并点击跳过」的完整链路,以及遇到「发生故障」状态时该如何恢复。

1. 操作步骤:两步启用无障碍服务

SKIP 依赖 Android 系统的**无障碍服务(Accessibility Service)**来感知当前前台应用的界面节点并模拟点击。启用过程分为两步:

步骤一:点击屏幕中央按钮。打开 SKIP 主界面后,界面顶部是一个占据屏幕中央的宽按钮。当服务未启动时,按钮显示为灰色的「已停止 / 点此启动」;点击该按钮后,SKIP 会直接跳转到系统「无障碍设置」页面(首次启动会先弹出「开始使用」教程提示框,确认后跳转)。

步骤二:点击「使用"SKIP"」。在系统无障碍设置页中找到「SKIP」条目并进入,打开「使用"SKIP"」开关,随后按系统要求确认授权。开启成功后返回 SKIP 主界面,中央按钮会变为「运行中」。

下图分别展示两个操作步骤的位置(原文档 enable-accessibility-service.md 中的配图):

提示:系统页面上「SKIP 简介」一栏显示「若无障碍服务发生故障,可以关闭后再打开」,这与 SKIP 主界面的故障状态提示相互对应,详见 第 5 节。

2. 服务声明:无障碍服务的注册入口

跳过广告能力的前提是系统认可 SKIP 是一个合法的无障碍服务。这一点由两处配置保证:

AndroidManifest.xml 中的服务声明。在 AndroidManifest.xml 中,MyAccessibilityService以如下方式注册:

<service android:name=".service.MyAccessibilityService" android:enabled="true" android:exported="true" 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/accessibility" /> </service>

三个关键属性缺一不可:

  • android.permission.BIND_ACCESSIBILITY_SERVICE:系统绑定无障碍服务所需的权限门槛;
  • intent-filter中的android.accessibilityservice.AccessibilityServiceaction:让系统能在「已安装的服务」列表中检索到它;
  • meta-data指向的@xml/accessibility资源文件:描述该服务的能力参数。

accessibility.xml 的能力配置。accessibility.xml 中声明了 SKIP 运行时所需的全部能力:

<accessibility-service android:accessibilityEventTypes="typeAllMask" android:accessibilityFeedbackType="feedbackAllMask" android:accessibilityFlags="flagReportViewIds|flagIncludeNotImportantViews|flagDefault|flagRetrieveInteractiveWindows|flagRequestFilterKeyEvents" android:canPerformGestures="true" android:canRequestFilterKeyEvents="true" android:canRetrieveWindowContent="true" android:description="@string/accessibility_description" android:notificationTimeout="100" />

各参数对 SKIP 的实际意义(可结合 MyAccessibilityService.kt 的实现理解):

属性取值对 SKIP 的意义
accessibilityEventTypestypeAllMask接收所有类型的事件,onAccessibilityEvent才能持续被回调,从而反复扫描界面
canRetrieveWindowContenttrue允许通过getCurrentRootNode()获取当前窗口根节点,遍历节点树是定位「跳过」按钮的基础
flagReportViewIds/flagIncludeNotImportantViews已启用节点会携带viewIdResourceName,SKIP 的「按 ID 跳过」规则依赖此标记;包含非重要视图可避免漏掉广告页元素
canPerformGesturestrue允许调用dispatchGesture模拟点击,这是执行「跳过」动作的核心权限
canRequestFilterKeyEventstrue允许拦截按键事件,SKIP 用它监听「音量减」键来触发布局检查功能(见onKeyEvent,MyAccessibilityService.kt)
notificationTimeout100单位毫秒,事件回调节流时间,控制扫描频率
description系统页面上展示的简介文案取自 strings.xml:SKIP 可以帮您自动跳过应用开屏广告,即上文系统设置页「SKIP 简介」中显示的文字

3. 主界面按钮:一个由服务状态驱动的按钮

「屏幕中央按钮」并非普通按钮,它的文案、颜色和图标都由无障碍服务状态实时驱动。

入口逻辑。MainActivity.kt 中,StartButton的点击回调为:

StartButton(startAccessibilityViewModel = startAccessibilityViewModel) { if (DataStoreUtils.getSyncData(getString(R.string.store_show_tutorial), true)) { tutorialViewModel.changeDialogState(true) // 首次:弹教程提示框 } else { startActivity(Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)) // 之后:直达无障碍设置 } }

即首次点击会弹出「是否需要前往查看『开始使用』教程」的对话框(TutorialDialog.kt),选择「立即前往」后同样会跳转到Settings.ACTION_ACCESSIBILITY_SETTINGS系统页面——这正对应步骤二所在的界面。

按钮的三态映射。StartAccessibilityViewModel.kt 定义了三种状态对应的按钮样式:

服务状态按钮文案外观图标
STOPPED(未启动)「已停止 点此启动」灰色0xFF808080block
STARTED(运行中)「运行中」深蓝0xFF1E4377check_circle
FAULTED(故障)「发生故障 点此重新启动」深红0xFF771E1Eerror

StartButton组合(StartAccessibilityButton.kt)通过collectAsState收集buttonState并渲染到ExtendedFloatingActionButton上,这就是截图中屏幕中央那个大按钮的实现。

4. 启用成功后发生了什么:从服务连接到自动点击

用户在系统页打开「使用"SKIP"」开关后,系统会绑定MyAccessibilityService,源码中的关键路径如下:

1. 服务连接并上报状态。onServiceConnected(MyAccessibilityService.kt)被调用时,立即执行startAccessibilityRepository.changeAccessibilityState(AccessibilityState.STARTED),主界面按钮随之切换为「运行中」。同时服务订阅了「常驻通知栏」「提示」「严格模式」三个开关的 LiveData,供后续行为使用。

2. 持续扫描当前界面。系统按事件持续回调onAccessibilityEvent(MyAccessibilityService.kt),核心流程:

  • 通过getCurrentRootNode()获取前台窗口根节点,取出packageName;
  • 若前台应用切换,则重置扫描计数scanTimes与已点击区域集合clickedRect;
  • 若该应用不在白名单中(whiteListRepository.isAppInWhiteList),且处于严格模式或scanTimes < 50(即进入应用后的前 50 次扫描窗口内),则调用configLoadRepository.getTargetRect按配置查找「跳过」按钮的Rect坐标;
  • 找到且该坐标尚未点击过时,切换回主线程执行click。

3. 用模拟手势完成点击。click方法(MyAccessibilityService.kt)构造一条位于目标Rect中心的零长度路径,封装为GestureDescription后调用dispatchGesture下发;手势完成后若用户开启了「是否允许提示」(tipRepository),会弹出「已为您跳过广告」的 Toast。

4. 命中规则来自哪里。getTargetRect在 ConfigLoadRepository.kt 中并行执行三类匹配任务:skipByTexts(按文本,如「跳过」)、skipByIds(按 viewId)、skipBounds(按屏幕区域),取最先命中者返回坐标。非严格模式下,若配置缺失还会退化为默认匹配文本「跳过」。配置文件的结构与字段含义可进一步参阅 custom-config 系列文档。

此外,onKeyEvent还利用无障碍服务的按键拦截能力实现了第二个入口:当布局检查服务(InspectService)运行中时,按下「音量减」键会触发一次界面节点捕获(MyAccessibilityService.kt),这与 布局检查 文档中「点按音量-执行布局检查」的说明一致。

5. 状态检测与故障恢复

SKIP 如何判断服务处于STARTED / STOPPED / FAULTED三种状态?答案在 AccessibilityStateUtils.kt:

fun getAccessibilityState(): AccessibilityState { val isSettingOn = isAccessibilitySettingsOn() // 系统设置中开关是否打开 val isRunning = isAccessibilitySettingsRunning() // 服务进程是否真正在跑 return when { isSettingOn && isRunning -> AccessibilityState.STARTED isSettingOn && !isRunning -> AccessibilityState.FAULTED else -> AccessibilityState.STOPPED } }

两个判定函数的实现细节值得注意:

  • isAccessibilitySettingsOn(AccessibilityStateUtils.kt)先读取Settings.Secure.ACCESSIBILITY_ENABLED总开关,再解析Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES(以:分隔的已启用服务列表),并匹配以下两种组件写法(兼容带/不带包名前缀的组件名):

    val serviceNameList = listOf( "com.android.skip/.service.MyAccessibilityService", "com.android.skip/com.android.skip.service.MyAccessibilityService" )
  • isAccessibilitySettingsRunning则直接检查MyAccessibilityService进程实例是否存活。

这正好解释了截图里系统页面那句「若无障碍服务发生故障,可以关闭后再打开」:「发生故障」(FAULTED)= 设置里开关是开的,但服务进程已不在运行(例如被系统省电策略杀死)。恢复方法就是把「使用"SKIP"」开关关掉再打开;返回 SKIP 主界面点击红色的「发生故障 点此重新启动」按钮,同样会带你回到系统无障碍设置页重新开启。

另外,onDestroy(MyAccessibilityService.kt)中会在服务被系统拆除时上报STOPPED状态并顺带停止布局检查服务等伴生服务,保证主界面按钮状态与实际运行状态一致。

6. 启用之后还需要做什么

无障碍服务只负责「跳过」,不负责「保活」。系统(尤其是 MIUI/HyperOS 等定制系统)可能随时回收后台服务,因此官方文档建议接着完成应用保活配置:关闭电池优化、允许自启动、锁定后台任务等,具体步骤参见 background-process-keep-alive.md。主界面的「应用保活」入口即对应该功能(AliveActivity)。

小结

  • 两步启用:主界面中央按钮 → 系统「无障碍设置」→ 打开「使用"SKIP"」开关(第 1 节截图所示)。
  • 声明位置:服务注册在 AndroidManifest.xml,能力参数在 accessibility.xml,其中canPerformGestures、canRetrieveWindowContent是跳过广告两大核心能力。
  • 运行链路:onServiceConnected上报 STARTED →onAccessibilityEvent持续扫描根节点 →ConfigLoadRepository.getTargetRect按文本/ID/区域命中坐标 →dispatchGesture模拟点击。
  • 故障恢复:按钮显示「发生故障」时,关闭再打开系统开关即可(状态判定逻辑见 AccessibilityStateUtils.kt)。
  • 下一步:完成 应用保活配置,确保服务长期存活。
  • 移动开发
  • 原生移动
  • GUI 自动化

【免费下载链接】SKIP

自动跳过APP开屏广告

项目地址:https://gitcode.com/gh_mirrors/ski/SKIP
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/14 16:34:04

Windows大数据开发必备:winutils.exe配置与避坑指南

简介&#xff1a;winutils.exe 是 Hadoop 在 Windows 平台运行所必需的适配组件&#xff0c;面向需要在 Windows 上搭建、调试 Hadoop 集群的大数据开发者与运维人员。它弥补了 Hadoop 原生依赖 Unix 文件路径、Posix 文件系统等特性带来的兼容性缺口&#xff0c;使 HDFS、MapR…

作者头像 李华
网站建设 2026/10/14 16:33:55

基于React Native的鸿蒙跨平台成长体系:任务进度与奖励领取实践

先说我为什么会做这个项目吧。我们团队当时接到的需求很明确&#xff1a;做一个内置在App里的用户成长激励模块&#xff0c;用户能看到任务、追踪自己的等级进度、完成任务后领取奖励&#xff0c;整套流程要同时跑在Android、iOS和鸿蒙设备上。传统做法是每个端各写一套原生页面…

作者头像 李华
网站建设 2026/10/14 16:33:52

ROS 2功能包ROSTCM6从解压到运行:避坑与配置实战

简介&#xff1a;ROST CM6 是一款面向即将毕业的高校学生及科研人员的专业论文查重工具&#xff0c;用于快速判断论文内容是否存在剽窃风险、统计重复率&#xff0c;辅助完成定稿前的自查与修改。软件内置全网分析、浏览分析、微博分析与情感分析等多种文本挖掘模块&#xff0c…

作者头像 李华
网站建设 2026/10/14 16:33:38

技术小团队管理实战:从程序员到组长的关键转型

1. 基层技术团队管理的核心挑战带领4-5人技术小组是许多工程师晋升后的第一个管理岗位。这个角色既要做具体技术工作&#xff0c;又要协调团队产出&#xff0c;常常面临"既要写代码又要管人"的双重压力。我在某互联网公司带过3个不同技术小组&#xff0c;最深体会是&…

作者头像 李华
网站建设 2026/10/14 16:32:47

INAV 在 Windows 10 下使用 VS Code + WSL 搭建开发环境的完整指南

无人机嵌入式智能硬件 【免费下载链接】inav INAV: Navigation-enabled flight control software 项目地址&#xff1a; https://gitcode.com/gh_mirrors/in/inav 点击查看 免费下载 本文面向所有在 Windows 10 上参与 INAV&#xff08;Navigation-enabled flight control sof…

作者头像 李华