Android Accessibility Services for Noobs ; Detect User Interactions Like a Pro
So, you’re building an Android app and at some point, you probably wondered:
“Can I detect user interactions…even when my app isn’t running?”
Good news! Yes, you can.
We just need to use something called Accessibility Services; and no, it’s not as scary as it sounds.
Let’s break it all down, Noob-Style.
What’s an Accessibility Service?
It’s a special service in Android that was originally made to help users with disabilities — think screen readers or switch controls. But for us developers, they open the door to some powerful features:
- Watch what’s happening on the screen
- Read UI elements from other apps
- Detect button presses (like volume up/down)
- Perform actions even when the app isn’t active
Yes, it’s powerful. But as someone’s wise uncle once said:
“With great power comes great hostility”
Why “Hostility”?
Because Accessibility Services can do things like:
- Read text on the screen.
- Detect every user interaction.
- Perform gestures or click buttons on behalf of the user.
- All this even if your app is not running.
That’s a lot of control. And with that control, comes suspicion.
What’s the Catch?
- Heavily restricted: From Android 13 onwards, Google has locked down how and when you can use Accessibility Services.
- Play Store Drama: If your app doesn’t have a legit accessibility use-case, it could get flagged or rejected during publishing.
Quick Reality Check
Before we go deeper: do NOT abuse this.
Accessibility Services have access to a lot of sensitive stuff, so only use them when you really need to; and always tell users why.
Let’s Build One : Step by Step
Here’s how you set up your own Accessibility Service to detect volume button presses.
Step 1: Create a Service Class
Create a class that extends AccessibilityService.
This is where we handle key presses (like volume buttons) and react to them.
class MyAccessibilityService : AccessibilityService() {
override fun onAccessibilityEvent(event: AccessibilityEvent?) {
// Optional: Handle UI events here if needed
}
override fun onInterrupt() {
// Called when the system wants to stop your service
}
override fun onKeyEvent(event: KeyEvent): Boolean {
when (event.keyCode) {
KeyEvent.KEYCODE_VOLUME_UP -> {
Log.d("TAG", "Volume Up Pressed")
Toast.makeText(this, "Volume Up Pressed", Toast.LENGTH_SHORT).show()
return true
}
KeyEvent.KEYCODE_VOLUME_DOWN -> {
Log.d("TAG", "Volume Down Pressed")
Toast.makeText(this, "Volume Down Pressed", Toast.LENGTH_SHORT).show()
return true
}
}
return super.onKeyEvent(event)
}
}Step 2: Add this to Your AndroidManifest.xml
Declare service in the manifest and give it the right permission.
This tells Android that our app has a background service for accessibility.
<service
android:name=".MyAccessibilityService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
android:exported="true">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService"/>
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/accessibility_service_config"/>
</service>Step 3: Create the Config File (res/xml/accessibility_service_config.xml)
This XML file tells Android what events our service cares about.
<accessibility-service
xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackGeneric"
android:notificationTimeout="100"
android:canRequestFilterKeyEvents="true"
android:accessibilityFlags="flagRequestFilterKeyEvents"
android:description="@string/volume_service_description" />Wait… XML Outside res/layout? What is this sorcery?
Get Syed Mohammad Ayaan’s stories in your inbox
Join Medium for free to get updates from this writer.
If you’re like me (aka a noob), you probably thought:
“XML files are just for designing UI, right?”
Welp, not always!
This particular XML file is not for your app’s layout. It’s a config file that tells the Android ecosystem:
- What kind of events our service wants to listen to
- Whether we want to capture key presses (spoiler: yes we do)
- How the service should behave overall
Think of it like a “settings sheet” for your service — just written in XML.
TL;DR:
1. Layout XML (res/layout/) = UI stuff.
2. Config XML (res/xml/) = Tells Android how your service should work behind the scenes.
Step 4: Ask the User to Enable It(using an intent)
Accessibility Services must be turned on manually by the user.
Here’s a quick way to send the user to the right settings screen:
// Check if the accessibility service is enabled
if (Settings.Secure.getString(contentResolver, Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES)
?.contains(packageName) != true) {
// If not enabled, open the Accessibility Settings page
val intent = Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)
startActivity(intent)
}Real-World Use Case
I was building an app that sends a HTTP request when the user presses the volume buttons in a specific pattern.
The catch?
The app shouldn’t be running in the foreground.
The Usual Options?
- Foreground Service : drains battery, feels intrusive, and can’t reliably detect volume button presses in the background
What Worked?
- Accessibility Service : the cleanest, most reliable way to detect those button presses even when the app isn’t running.
Pro Tips (from a noob)
Look, I probably shouldn’t be giving “pro” tips…
But hey, I believe in fake it till you make it, so here we go:
- This only works if the user manually enables the service.
- Be transparent. Users should always know what’s going on.
- Use logs to test and debug. It won’t work unless permission is granted.
- Check event.packageName in onAccessibilityEvent() if you want to respond to changes in other apps.
Bonus: This Video Helped Me Understand It Better
The official Android Developers team explains Accessibility really well in this Youtube video. Highly recommend watching it if you’re curious about all the cool things this service can do.
That’s a Wrap!
If you’ve reached this farcongrats! You’ve just unlocked the power of Accessibility Services like a true Android dev.
Got questions? Found a bug? Drop it in the comments — I’d love to help!





