Table of Contents
Introduction
Hello Everyone, So in today’s article we are going to learn about accessibility service in android. I will teach you how to implement accessibility service and track different feedbacks from the device. Implementing acccessibilty service consist of majorly 5 steps. We are going to talk about those steps one by one so that you can understand the way to implement the whole process with ease. So without wasting any time let’s get started.
Implementation of Accessibility service
So in this artcle we are going to create an app which will track and tell us the package name of current opened app using accessibility and we will also track user actions such as click, scroll, long click. There are many other user actions we can track with accessibility service but if I start telling all of them then this article will become quite confusing. The implementation to listen all other user event will be the same just chose the accessibility condition according to that. So let’s jump to step 1.
Step 1 : Create Activity xml
First create an activity.xml file. So that our app can ask for the accessibility service permission to the user. Accessibility service is necessary to allow if we wan to extract user feedback from device.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:weightSum="2"
android:gravity="center"
android:layout_gravity="center"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".StartServiceScreen">
<TextView
android:id="@+id/PrmTxt"
android:layout_gravity="center"
android:textSize="18sp"
android:gravity="center"
android:text="Please provide us the below mentioned permissions"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/AccessibilityServiceBtn"
android:text="Allow Accessbility "
android:layout_gravity="center"
android:layout_marginTop="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
Step 2 : Create .java file for activity
Now connect the activity.xml file to an backend. So that when user clicked on button then we can redirect user to accessibility service screen. Were user can allow or deny the permission to our application.
package com.two;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.view.View;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
public class StartServiceScreen extends AppCompatActivity {
androidx.appcompat.widget.AppCompatButton AccessibilityServiceBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start_service_screen);
AccessibilityServiceBtn = findViewById(R.id.AccessibilityServiceBtn);
AccessibilityServiceBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// request permission via start activity for result
startActivity(intent);
}
});
}
}
Step 3 : Create Accessibility service class
This accessibility service class is important because we will define our operations in this class. In this class we can get every information which an accessibility service provides such as click, long click, scroll, window content change etc. If you wan to know more about the action provides by the accessibility service. You can directly by clicking here.
package com.two;
import android.accessibilityservice.AccessibilityService;
import android.os.Handler;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class TrackUserActivity extends AccessibilityService {
// Tag for logging
private static final String TAG = "MyAccessibilityService";
// Variable to hold the last detected package name
private String lastPackageName = "";
// Handler to handle delayed tasks
private Handler handler = new Handler();
// Variable to hold the currently potential package name
private String currentPotentialPackageName = "";
// Set of package names to ignore (e.g., system UI packages)
private Set<String> ignoredPackageNames = new HashSet<>(Arrays.asList(
"com.android.systemui", "com.android.settings", "com.google.android.googlequicksearchbox"
));
// Runnable to handle the debounce logic
private Runnable debounceRunnable = new Runnable() {
@Override
public void run() {
// If the potential package name has changed, update the last package name and log it
if (!currentPotentialPackageName.equals(lastPackageName)) {
lastPackageName = currentPotentialPackageName;
Log.d(TAG, "Current app package name: " + lastPackageName);
}
}
};
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
// Check if the event type is window state changed or window content changed
if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED ||
event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) {
// Get the root node info of the currently active window
AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
if (nodeInfo != null) {
// Extract package name information from the node info
CharSequence packageName = nodeInfo.getPackageName();
if (packageName != null) {
String packageNameString = packageName.toString();
// Check if the package name is not in the ignored package names and has changed
if (!ignoredPackageNames.contains(packageNameString) &&
!packageNameString.equals(currentPotentialPackageName)) {
// Update the current potential package name
currentPotentialPackageName = packageNameString;
// Remove any pending debounce runnable
handler.removeCallbacks(debounceRunnable);
// Post the debounce runnable with a delay of 500ms
handler.postDelayed(debounceRunnable, 500);
}
}
}
}
// We are checking is the event type is just user click
else if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_CLICKED) {
Log.d(TAG, "User clicked");
}// We are checking is the event type is just user long click
else if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_LONG_CLICKED) {
Log.d(TAG, "User long clicked");
}
// We are checking is the event type is just user long click
else if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
Log.d(TAG, "User long clicked");
}
}
@Override
public void onInterrupt() {
// Remove any pending debounce runnable when the service is interrupted
handler.removeCallbacks(debounceRunnable);
}
@Override
public void onDestroy() {
// Clean up by removing any pending debounce runnable when the service is destroyed
super.onDestroy();
handler.removeCallbacks(debounceRunnable);
}
}
Step 4 : Create .xml for accessibility
Create this file in res > xml > create_file.xml. We will user this file later on in our AndroidMainfest.xml.
<accessibility-service
xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeWindowStateChanged"
android:accessibilityFeedbackType="feedbackSpoken"
android:notificationTimeout="100"
android:canRetrieveWindowContent="true" />
Step 5 : AndroidMainfest.xml
In AndroidMainfest.xml define the Accessibility Service. So that android knows that our app uses Accessibility Service.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Prototype"
tools:targetApi="31">
<activity
android:name=".StartServiceScreen"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".TrackUserActivity"
android:exported="true"
android:label="@string/app_name"
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_config" />
</service>
</application>
</manifest>
Output
Conclusion
So I hope you guys understood that how you can implement accessbility service in android. I tried to explain you about this in an easy way. My suggestion to you guys is just don’t only read this article but also try to implement the accessbility service and still if you have any doubt then comment section is all yours. Ask me your doubts in the comment section and I will provide you solutions of your questions. If you have any suggestions please let us know by clicking on this link Contact us.