Abilash
Abilash

Reputation: 1163

How to Programmatically Enable/Disable Accessibility Service in Android

I would like to programmatically enable/disable Accessibility Services listed under Settings->Accessibility option.

I could start Accessibility Intent like below:

Intent intent = new Intent(android.provider.Settings.ACTION_ACCESSIBILITY_SETTINGS);
startActivityForResult(intent, 0);

But I don't have any idea on how to enable the services listed in the view through my code.

Please, provide me your views.

Upvotes: 40

Views: 83818

Answers (11)

Naprzod
Naprzod

Reputation: 1

enabled_accessibility_services contains all the enabled services separated by ':'. It's something like 'serviceA:serviceB:serviceC'

If you replace the string, it will enable your service, but you will also disable everyone else's.

The correct code would be:

    fun enableAccessibility(activity: Activity) {
        var accessibilityServices: String? = Settings.Secure.getString(
            activity.contentResolver,
            Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES
        )

        if (accessibilityServices == null) {
            accessibilityServices = ""
        } else if (accessibilityServices.isNotEmpty()) {
            accessibilityServices = ":$accessibilityServices"
        }
        Settings.Secure.putString(
            activity.contentResolver,
            Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
            "${activity.applicationInfo.packageName}/${ForegroundDetectorService::class.java.canonicalName}$accessibilityServices"
        )
        Settings.Secure.putString(
            activity.contentResolver,
            Settings.Secure.ACCESSIBILITY_ENABLED, "1"
        )
    }

You only need to declare this permission:

<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>

You can only enable this permission if you are rooted or via adb.

Upvotes: 0

Tyler
Tyler

Reputation: 6891

You can enable accessibility services for multiple apps by separating them by a colon, like this:

adb shell settings put secure enabled_accessibility_services com.app1/com.app1.MyAccessibilityService:com.app2/com.app2.MyAccessibilityService

Upvotes: 3

BlackShaman
BlackShaman

Reputation: 31

Here is the working solution (if your activity is not running it will disable itself)

@Override
protected void onServiceConnected() {
    super.onServiceConnected();
    Toast.makeText(this, "Connected!",Toast.LENGTH_SHORT).show();
    ScheduledExecutorService scheduleTaskExecutor = Executors.newScheduledThreadPool(1);
    scheduleTaskExecutor.scheduleAtFixedRate(new Runnable() {
        public void run() {
            serviceChecker();
        }
    }, 0, 5, TimeUnit.SECONDS);
}

private void serviceChecker(){
    if(!isActivityRunning(MainActivity.class)) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            disableSelf();
        }
    }
}
protected Boolean isActivityRunning(Class activityClass)
{
    ActivityManager activityManager = (ActivityManager) getBaseContext().getSystemService(Context.ACTIVITY_SERVICE);
    List<ActivityManager.RunningTaskInfo> tasks = activityManager.getRunningTasks(Integer.MAX_VALUE);

    for (ActivityManager.RunningTaskInfo task : tasks) {
        if (activityClass.getCanonicalName().equalsIgnoreCase(task.baseActivity.getClassName()))
            return true;
    }

    return false;
}

Upvotes: 3

Maxim Blumental
Maxim Blumental

Reputation: 743

In instrumented tests I start my accessibility service like this:

private fun enableAccessibilityService() {
    val packageName = "com.example"
    val className = "$packageName.service.MyService"
    val string = "enabled_accessibility_services"
    val cmd = "settings put secure $string $packageName/$className"
    InstrumentationRegistry.getInstrumentation()
      .getUiAutomation(UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES)
      .executeShellCommand(cmd)
      .close()
    TimeUnit.SECONDS.sleep(3)
}

I tested on Android 6 and 8. This also works for non-system apps.

Upvotes: 4

adb_user
adb_user

Reputation: 31

Just in case anybody still seeks to turn off talkback from adb when you are stuck in your lock screen entering the password or pin. One thing you can try is adb shell am force-stop com.google.android.marvin.talkback

Upvotes: 3

Sam
Sam

Reputation: 42417

In Android 7 (API 24), an AccessibilityService can programmatically disable itself by calling the disableSelf() method.

Upvotes: 15

Zoli_K
Zoli_K

Reputation: 992

From Android 6.0 you can use:

adb shell settings put secure enabled_accessibility_services packagname/servicename

The settings.db from old releases is no longer present on Android 6.0.

Upvotes: 18

Kevin
Kevin

Reputation: 386

I found a solution worked for me by calling

Settings.Secure.putString(getContentResolver(), 
    Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, "pkgname/classname");
Settings.Secure.putString(getContentResolver(), 
    Settings.Secure.ACCESSIBILITY_ENABLED, "1");

Where the pkgname is your package name and the classname is the class name of your accessibility service.

If you need to enable several services or you don't want to destory the previous settings you might want to use : to seperate other services.

Also you might need to run as a system application and you might need the following permissions

<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />

However, according to @Rupert Rawnsley this might not work on some versions of Android, I am working on Android 4.0.4 and hope it works for you.

PS. If it doesn't work, maybe you could find some luck in /data/data/com.android.providers.settings/databases/settings.db/secure, that's where Android stores secure settings.

Upvotes: 31

Eran Katsav
Eran Katsav

Reputation: 1324

The best you can do is manualy open the accessibilty settings with:

Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)

and start the intent - you can also do it from the prefernece xml file:

intent android:action="android.settings.ACCESSIBILITY_SETTINGS"

Upvotes: 5

Rupert Rawnsley
Rupert Rawnsley

Reputation: 2669

AccessibilityService is special and cannot be started programmatically.

Upvotes: 6

Ryan B
Ryan B

Reputation: 3392

I found this post: How to programmatically check if a service is declared in AndroidManifest.xml?. The top answer talks about PackageManager, which tells you what is running.

Upvotes: -7

Related Questions