kotlin 无障碍服务_GitHub - Autfy/Android-Accessibility-Api: 安卓无障碍服务Api, 为了简化无障碍服务使用,并使用 Kotlin 以提供简洁的Api。...

这篇博客介绍了如何使用 Kotlin 和 Android-Accessibility-Api 库简化 Android 无障碍服务的开发。内容涵盖基础导航操作,如下拉通知、快捷设置、返回等,以及视图检索、文本操作和全局手势的实现。示例代码展示了如何查找和操作屏幕元素,以及执行自定义手势。此外,还提供了服务的创建和注册指南。
摘要由CSDN通过智能技术生成

Android-Accessibility-Api

安卓无障碍服务Api, 为了简化无障碍服务使用,并使用 Kotlin 以提供简洁的Api。

[TOC]

基础导航

(图片加载过慢可到 Gitee 查看)

查看代码

//无障碍服务声明 未开启会跳转设置页面提示开启服务,并抛出异常 终止执行

requireBaseAccessibility()

toast("下拉通知栏..")

delay(1000)

toast("快捷设置..")

//操作之间需要适当延时等待

delay(1000)

//下拉通知栏快捷设置

quickSettings()

delay(1000)

//返回操作

back()

delay(500)

//返回操作

back()

delay(1000)

//电源菜单

powerDialog()

delay(500)

back()

delay(1000)

//进入最近任务页面

recents()

delay(1000)

back()

delay(1000)

//Home 按键 / 返回桌面

home()

delay(100)

更多操作:

方法

说明

lockScreen()

锁屏,需要Android P

screenShot()

触发系统截屏,需要Android P

splitScreen()

触发系统分屏,需要Android P

视图检索

提取文字

requireBaseAccessibility()

//使用 ScreenTextFinder() 来搜索屏幕上的文字

val ts = ScreenTextFinder().find().joinToString("\n\n")

withContext(Dispatchers.Main) {

AlertDialog.Builder(act).apply {

setTitle("提取文字:")

setMessage(ts)

show()

}

}

视图搜索

提供一个基础类 ViewFinder, 并封装一个 ViewFinderWithMultiCondition 来指定搜索条件,实现快速搜索;查看所有方法:view_finder_api.kt

ViewFinder 主要方法:

方法

说明

findFirst(includeInvisible: Boolean = false): ViewNode?

立即搜索,返回满足条件的第一个结果

includeInvisible: 是否包含不可见元素

findAll(includeInvisible: Boolean = false): Array

立即搜索,返回满足条件的所有结果

waitFor(waitMillis: Long = 30000): ViewNode?

等待搜索,在指定时间内循环搜索(视图更新),超时返回null

require(waitMillis: Long = WAIT_MILLIS): ViewNode

等待超时抛出异常

示例1: 等待 Chrome 打开 > 展开菜单

//等待无障碍开启 默认时间30s,超时将抛出异常

waitBaseAccessibility()

toast("start chrome after 1s")

delay(1000)

//打开Chrome

val targetApp = "com.android.chrome"

act.startActivity(act.packageManager.getLaunchIntentForPackage(targetApp))

//等待页面

if (

waitForApp(targetApp, 5000).also {

toast("wait " + if (it) "success" else "failed")

}

) {

//id 搜索,点击打开菜单

withId("menu_button").tryClick()

}

示例2: 文本操作

查看代码

requireBaseAccessibility()

//editor() 指定编辑框

editor().require().apply { // this is ViewNode

repeat(5) {

//追加文本

appendText(".x")

delay(500)

}

delay(1000)

//清空文本

text = ""

delay(1000)

//设置文本

text = "123456"

delay(1000)

//选择文本

setSelection(0, 5)

delay(1000)

//清除选择

clearSelection()

//失去焦点

clearFocus()

}

提供自定义搜索条件 CustomViewFinder

搜索所有可点击的视图:

requireBaseAccessibility()

//自定义条件搜索

val s = findAllWith { it: AccessibilityNodeInfo ->

it.isClickable

}.joinToString("\n\n")

withContext(Dispatchers.Main) {

AlertDialog.Builder(act).apply {

setTitle("可点击节点:")

setMessage(s)

show()

}

}

视图节点(ViewNode)

根据视图搜索得到 ViewNode,可进行的操作详见接口:ViewOperation.kt

全局手势

全局手势可以点击/长按任意坐标,执行路径手势。

示例

查看代码

class DrawableAction : Action {

override val name: String

get() = "手势画图 - Rect - Circle - Oval"

@RequiresApi(Build.VERSION_CODES.N)

override suspend fun run(act: Activity) {

requireBaseAccessibility()

requireGestureAccessibility()

act.startActivity(Intent(act, DrawableActivity::class.java))

toast("1s后开始绘制,请不要触摸屏幕")

delay(1000)

//设置相对屏幕 非必须

setScreenSize(500, 500)

//指定点转路径手势

gesture(

2000L, arrayOf(

100 t 100,

100 t 200,

200 t 200,

200 t 100,

100 t 100

)

)

delay(800)

//点击clear按钮

withText("clear").tryClick()

//使用Path

drawCircle()

delay(800)

withText("clear").tryClick()

drawOval()

}

@RequiresApi(Build.VERSION_CODES.N)

fun drawCircle() {

val p = Path().apply {

//此处路径坐标为绝对坐标

addOval(RectF(500f, 500f, 800f, 800f), Path.Direction.CW)

}

gesture(2000L, p) {

toast("打断")

}

}

//AdapterRectF 会根据设置的相对屏幕大小换算

@RequiresApi(Build.VERSION_CODES.N)

fun drawOval() {

val p = Path().apply {

//使用AdapterRectF 会根据设置的相对屏幕尺寸将坐标转换

addOval(AdapterRectF(200f, 200f, 300f, 300f), Path.Direction.CW)

}

gesture(2000L, p)

}

infix fun A.t(that: B): Pair = Pair(this, that)

}

Api文档

手势Api全部需要Android N+;代码必须执行于非主线程

展开查看

方法

说明

fun setScreenSize(width: Int, height: Int)

设置屏幕相对坐标

fun gesture(

duration: Long,

points: Array>,

onCancel: Function0? = null

): Boolean

根据点坐标生成路径 执行手势

fun gesture(

duration: Long,

path: Path,

onCancel: Function0? = null

): Boolean

根据Path执行手势

fun gestureAsync(

duration: Long,

points: Array>

)

异步执行手势

fun gestures(

duration: Long,

ppss: Array>>,

onCancel: Function0? = null

): Boolean

多路径手势

fun click(x: Int, y: Int)

点击; x,y 相对坐标

fun longClick(x: Int, y: Int)

长按; x,y 相对坐标

fun swipe(x1: Int, y1: Int, x2: Int, y2: Int, dur: Int)

两点间滑动

fun scrollUp(): Boolean

向上滑动

fun scrollDown(): Boolean

向下滑动

使用

由于部分系统版本启动支持手势的无障碍服务会造成系统卡顿(掉帧),所以本库分为两个服务来设计(若无需手势功能,可不实现手势服务)。

引入 Android-Accessibility-Api

Add it in your root build.gradle at the end of repositories:

allprojects {

repositories {

...

maven { url 'https://jitpack.io' }

}

}

Add the dependency

dependencies {

implementation 'com.gitee.Vove:Android-Accessibility-Api:Tag'

}

the TAG is

创建你的服务

基础服务

用来支持 布局检索,视图操作

定义你的 BaseAccessibilityService

展开查看 BaseAccessibilityService

class BaseAccessibilityService : AccessibilityApi() {

//启用 页面更新 回调

override val enableListenAppScope: Boolean = true

override fun onCreate() {

//must set

baseService = this

super.onCreate()

}

override fun onDestroy() {

//must set

baseService = null

super.onDestroy()

}

//页面更新回调

override fun onPageUpdate(currentScope: AppScope) {

Log.d("TAG", "onPageUpdate: $currentScope")

}

}

服务注册

android:name=".service.BaseAccessibilityService"

android:description="@string/base_ser_desc"

android:label="BaseService Demo"

android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">

android:name="android.accessibilityservice"

android:resource="@xml/base_accessibility_config" />

base_accessibility_config.xml

点击展开 res/xml/base_accessibility_config.xml

android:accessibilityEventTypes="typeWindowStateChanged"

android:accessibilityFeedbackType="feedbackAllMask"

android:accessibilityFlags="flagIncludeNotImportantViews|flagReportViewIds|flagRetrieveInteractiveWindows|flagRequestEnhancedWebAccessibility"

android:canRetrieveWindowContent="true"

android:description="@string/base_ser_desc"

android:notificationTimeout="10"

android:canRequestEnhancedWebAccessibility="true"

android:settingsActivity=".MainActivity"

android:summary="基础导航/视图检索操作"/>

手势服务

用于执行手势,Android N+可用

定义 GestureAccessibilityService

展开查看 GestureAccessibilityService

class GestureAccessibilityService : AccessibilityService() {

override fun onCreate() {

super.onCreate()

//must call

AccessibilityApi.gestureService = this

}

override fun onDestroy() {

super.onDestroy()

//must call

AccessibilityApi.gestureService = null

}

override fun onInterrupt() {}

override fun onAccessibilityEvent(event: AccessibilityEvent?) {}

}

服务注册

android:name=".service.GestureAccessibilityService"

android:description="@string/ges_ser_desc"

android:label="Gesture Service Demo"

android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">

android:name="android.accessibilityservice"

android:resource="@xml/gesture_accessibility_config" />

gesture_accessibility_config.xml

点击展开 res/xml/gesture_accessibility_config.xml

和基础服务配置区别仅为 android:canPerformGestures="true"

android:accessibilityEventTypes=""

android:accessibilityFeedbackType=""

android:accessibilityFlags=""

android:canPerformGestures="true"

android:canRetrieveWindowContent="false"

android:description="@string/ges_ser_desc"

android:notificationTimeout="10"

android:packageNames=""

android:settingsActivity=".MainActivity"

android:summary="执行手势" />

额外配置

在 Application 中初始化:

指定 BASE_SERVICE_CLS 及 GESTURE_SERVICE_CLS

override fun onCreate() {

super.onCreate()

AccessibilityApi.apply {

BASE_SERVICE_CLS = BaseAccessibilityService::class.java

GESTURE_SERVICE_CLS = GestureAccessibilityService::class.java

}

}

合并服务

如果你想使用一个服务来完成,可使用如下配置

创建服务

class MyAccessibilityService : AccessibilityApi() {

//启用 页面更新 回调

override val enableListenAppScope: Boolean = true

override fun onCreate() {

//同时设置

baseService = this

AccessibilityApi.gestureService = this

super.onCreate()

}

override fun onDestroy() {

//同时设置

baseService = null

AccessibilityApi.gestureService = null

super.onDestroy()

}

//页面更新回调

override fun onPageUpdate(currentScope: AppScope) {

Log.d("TAG", "onPageUpdate: $currentScope")

}

}

清单注册

android:name=".service.MyAccessibilityService"

android:description="@string/ser_desc"

android:label="Service Demo"

android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">

android:name="android.accessibilityservice"

android:resource="@xml/accessibility_config" />

res/xml/accessibility_config.xml

点击展开 accessibility_config.xml

android:accessibilityEventTypes="typeWindowStateChanged"

android:accessibilityFeedbackType="feedbackAllMask"

android:accessibilityFlags="flagIncludeNotImportantViews|flagReportViewIds|flagRetrieveInteractiveWindows|flagRequestEnhancedWebAccessibility"

android:canRetrieveWindowContent="true"

android:description="@string/base_ser_desc"

android:notificationTimeout="10"

android:canPerformGestures="true"

android:canRequestEnhancedWebAccessibility="true"

android:settingsActivity=".MainActivity"

android:summary="基础导航/视图检索操作"/>

Application 初始化配置

AccessibilityApi.apply {

BASE_SERVICE_CLS = MyAccessibilityService::class.java

GESTURE_SERVICE_CLS = MyAccessibilityService::class.java

}

更多 Api 可在下列文件查看

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值