Android-Auto-Api wraps the accessibility service in Kotlin
安卓无障碍服务Api, 为了简化无障碍服务使用,并使用 Kotlin 以提供简洁的Api。
At a glance
- What is it?
- Android-Auto-Api is a Kotlin library that turns the Android accessibility service into a small API for device automation, covering system navigation, view search, text editing and coroutine driven waiting. It is published through JitPack, licensed under Apache-2.0, and its 4.x line requires coroutine scopes for searching.
- Who is it for?
- Adopt Android-Auto-Api when you are writing a Kotlin Android app that must drive the device interface, for example a testing or automation tool, and you want view search, text extraction and system gestures behind a compact API instead of raw AccessibilityNodeInfo code. Skip it if your automation runs as an instrumentation test instead, or if you need a stable release train, since the newest tagged version is 4.2.1 from 2025-06-18 and the API changed shape at 4.0.0.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly Kotlin, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A thin Kotlin layer over AccessibilityNodeInfo
The project describes itself as an Android accessibility service API written in Kotlin to simplify the use of accessibility services and provide a concise API. That is the whole ambition: the platform's own accessibility interfaces are powerful and verbose, and this library wraps the common operations.
The reader is a developer building an app that operates the device interface, which in practice means test automation, self checking apps and helper tools. The readme shows a navigation sequence, a text extraction snippet, a view search API and a coroutine cancellation example, which is the vocabulary of UI automation rather than of an end user application.
The repository layout backs that reading. There is an accessibility/ directory holding the library, a core/ directory, a uiauto/ directory, and an app/ directory that the readme points to as the demo application, with the note that UiAutomator usage can be seen there. The build is Gradle, with build.gradle, settings.gradle, gradle.properties and the gradlew wrapper at the top level, and jitpack.yml alongside, which is how the artifact is distributed.
System gestures that an app cannot reach with its own API
The basic navigation block is the clearest statement of intent. It begins with requireBaseAccessibility(), which per the readme throws an exception and terminates execution if the service is not enabled, and then demonstrates the gestures an app cannot normally perform on itself:
requireBaseAccessibility()
delay(1000)
quickSettings()
delay(1000)
back()
delay(500)
back()
delay(1000)
powerDialog()
delay(500)
back()
delay(1000)
recents()
delay(1000)
back()
delay(1000)
home()
delay(100)The comment in the original snippet says that operations need appropriate delays between them, and the example reflects that with delay calls between almost every action. That is a real characteristic of this style of automation rather than noise in the sample: each gesture is an asynchronous request to the system, and the script has to pace itself.
Three more actions are listed in a separate table with an explicit platform requirement. lockScreen() locks the device, screenShot() triggers a system screenshot and splitScreen() triggers system split screen, and all three need Android P. The version constraint is stated per method, which is a better practice than a blanket minimum version, and it tells you to check the OS level before calling them.
Two ways to assert the service is actually running
Automation against an accessibility service has an obvious failure mode: the user has not enabled the service, or has revoked it, and the script runs against a device that does nothing. The library treats that as a first class case.
requireBaseAccessibility() fails hard. The readme says that if the service is not enabled it jumps to the settings page to prompt the user to turn it on, and it throws an exception that terminates execution. The second variant, waitBaseAccessibility(), waits instead, with a default timeout of 30 seconds and an exception on timeout.
That difference is the important design decision in this library. A script that opens the app cold and then drives Chrome has to wait for the user to finish granting the permission, so the waiting variant exists for that flow. The example that follows shows the pattern, waiting for the accessibility service, starting Chrome by package name, waiting for the app with a 5 second budget, and then searching by view id and clicking.
The honest caveat is that the wait is a user interaction timeout, not a machine guarantee. A user who ignores the settings prompt leaves the script waiting for the full 30 seconds before it fails.
ViewFinder separates immediate search from waiting search
The view search API is built around a base class called ViewFinder, with a ViewFinderWithMultiCondition subclass for specifying search conditions. The method table in the readme shows how carefully the timing options are separated.
findFirst() and findAll() search immediately and return a single node or an array of nodes, with an includeInvisible flag. waitFor() loops the search while the view updates and returns null when the time budget is exhausted, with a default of 30000 milliseconds. require() is the same search but throws on timeout. findByDepths() searches by depth index, and exist() answers the question directly.
The distinction between a null return and a thrown exception is the one to internalise. A timeout on a screen that never renders is an expected outcome in a flaky UI, and returning null lets the caller branch, while require() is for the case where continuing would corrupt the run.
The search results are ViewNode objects, and the operations available on them are listed in an interface file, accessibility-api/src/main/java/cn/vove7/andro_accessibility_api/viewnode/ViewOperation.kt. That includes the text editing operations shown in the readme, where a node located with editor() and required can have text appended, cleared, set and selected, with clearSelection() and clearFocus() available as well.
SmartFinder turns conditions into an expression language
The newest addition to the search layer is SmartFinder, abbreviated SF, which supports multi condition search with AND and OR. The readme shows several levels of use.
The terse form calls a condition directly and returns the first match, with an infix and or() style for chaining:
SF.text("123").or().id("text1").findFirst()A condition can also be built from raw node properties, in which case the where() block takes a lambda over the node, and named conditions can be combined with or:
SF.where(IdCondition("view_id")).or(RTextEqCondition("[0-9]+")).find()Groups express the usual boolean algebra, so a node whose text and description both match one value, or whose text and description both match another value, is selected by combining two condition groups with or. There is also an infix form that reads like an expression, mixing text, id and longClickable() conditions with and and or before calling findAll().
The set of built-in conditions lives in SmartFinderConditions.kt, and the readme links that file as the reference for what is supported. That file is the thing to read before assuming a condition exists.
Custom conditions are a two line extension
The extension mechanism is deliberately small. A custom condition implements the MatchCondition interface and returns whether a node matches, for example by testing the node text against a regular expression:
class TextMatcherCondition(private val regex: String) : MatchCondition {
private val reg = regex.toRegex()
override fun invoke(node: AcsNode) =
node.text?.toString()?.let {
reg.matches(it)
} ?: false
}The readme points out two practical details. The regex is compiled once in the constructor rather than on every search, and the pattern can be validated at construction time. Both matter for a condition that is evaluated across a whole view tree.
Once the class exists it can be used directly, and an extension function on ConditionGroup makes it read like a built-in:
fun ConditionGroup.matchText(reg: String) = link(TextMatcherCondition(reg))After that the call site is identical in shape to the built-in conditions, for example SF.matchText("[0-9]+").findAll(). This is the part of the library that generalises: the built-in condition set is an implementation detail you can extend without forking the search engine.
Coroutine scopes became mandatory in version 3.0.0
The version history contains one note that will break a Java integration, so it is worth stating plainly. The readme says that from version 3.0.0 onwards the search methods must be used inside a coroutine scope, and that callers in Java should use version 2.1.1 instead.
That is a hard boundary between the 2.x line and the 3.x and 4.x lines for anyone calling the library from Java, and it is the reason the 4.0 release note exists at all. The 4.0 release refactored the code, so existing integrations had to change their import package and their dependency coordinate, and the newest artifact is now published as com.github.Krosxx:Android-Auto-Api:Tag, with the older coordinate com.github.Krosxx.Android-Accessibility-Api:accessibility-api:4.0.0 still mentioned for projects that have not moved.
The coroutine requirement is not a formality. A waiting search blocks for up to 30 seconds by design, and the library offers attachCoroutine() so a search can be cancelled and can be interrupted from the caller's job, which is the only sane way to run a search that may wait on a user.
There is a related operational limit. The library needs the user to enable the accessibility service in system settings before anything works, and that step is manual, which makes it unsuitable for unattended use on a fresh device.
Apache-2.0 licence and a version history with a gap
The licence is Apache-2.0, with the text in the LICENSE file at the top level of the repository. That is a permissive grant with an explicit patent clause and no copyleft obligation on code that links against the library, though how your own product distributes it remains a question for your team.
The release history is thin. The most recent tagged release is 4.2.1 from 2025-06-18, before that 4.0.0 from 2023-04-26 and 3.0.0 from 2022-12-20. Those gaps are large, and they tell you something about the maintenance rhythm.
The commit history tells a different story. The last push was on 2026-10-19 and the repository is not archived, so work is continuing between releases. The distribution model also matters: the artifact is published through JitPack rather than to a package repository, so the version you depend on is built from a git tag on request, and the readme points at Tag as the moving coordinate for the newest library.
The project also carries a Chinese readme alongside the English one, a contact group for questions and a note that paid help is available for difficult problems, which is a reasonable sign of an active maintainer but also a sign that this is a single person project.
Editorial conclusion
Adopt Android-Auto-Api when you are writing a Kotlin Android app that must drive the device interface, for example a testing or automation tool, and you want view search, text extraction and system gestures behind a compact API instead of raw AccessibilityNodeInfo code. Skip it if your automation runs as an instrumentation test instead, or if you need a stable release train, since the newest tagged version is 4.2.1 from 2025-06-18 and the API changed shape at 4.0.0. Before integrating, read the migration note about the import package change, confirm that callers live inside a coroutine scope because searching requires it from 3.0.0 onwards, and check that your device and OS version support the helpers you need.
Frequently asked questions
What is Android-Auto-Api?
It is a Kotlin library that simplifies the use of the Android accessibility service by wrapping it in a concise API. It covers system navigation, view search, text extraction and editing, and coroutine driven waiting for elements.
How do I install Android-Auto-Api?
The library is published through JitPack, and the readme gives the newest coordinate as com.github.Krosxx:Android-Auto-Api:Tag. Projects that have not migrated from the 4.0 release still use com.github.Krosxx.Android-Accessibility-Api:accessibility-api:4.0.0.
Can I search for views from Java code?
Not with version 3.0.0 or later. The readme states that from 3.0.0 onwards the search methods must be called inside a coroutine scope, and that callers in Java should use version 2.1.1 instead.
How do I handle the accessibility service being disabled?
requireBaseAccessibility() jumps to the settings page to prompt the user to enable the service and then throws an exception, while waitBaseAccessibility() waits for it, with a default of 30 seconds and an exception on timeout.
Which Android version do the screen and split screen helpers need?
lockScreen(), screenShot() and splitScreen() are documented as requiring Android P. The other helpers in the basic navigation set, such as quickSettings(), powerDialog(), recents(), home() and back(), carry no version requirement in the readme.
How do I add my own search condition to SmartFinder?
Implement the MatchCondition interface in a class whose invoke method returns whether a node matches, then use it with SF.where(...), or add an extension function on ConditionGroup so it reads like a built-in condition. The built-in conditions are listed in SmartFinderConditions.kt.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/krosxx-android-auto-api)Was this useful?