Android: как проверить, включена ли конкретная служба специальных возможностей

Я написал приложение для Android, которое требует использования AccessibilityService. Я знаю, как проверить, включены или отключены специальные возможности на телефоне, но я не могу найти способ определить, было ли мое приложение специально включено в меню специальных возможностей.

Я хочу сообщить пользователю, если AccessibilityService не запущен, но не могу найти хороший способ сделать это. Существуют ли какие-либо методы API, которые я мог бы пропустить, которые позволили бы мне узнать, какие службы специальных возможностей включены на устройстве?


person Andrew    schedule 22.02.2011    source источник


Ответы (8)


В конце концов я сам разобрался с этим:

public boolean isAccessibilityEnabled() {
    int accessibilityEnabled = 0;
    final String LIGHTFLOW_ACCESSIBILITY_SERVICE = "com.example.test/com.example.text.ccessibilityService";
    boolean accessibilityFound = false;
    try {
        accessibilityEnabled = Settings.Secure.getInt(this.getContentResolver(),android.provider.Settings.Secure.ACCESSIBILITY_ENABLED);
        Log.d(LOGTAG, "ACCESSIBILITY: " + accessibilityEnabled);
    } catch (SettingNotFoundException e) {
        Log.d(LOGTAG, "Error finding setting, default accessibility to not found: " + e.getMessage());
    }

    TextUtils.SimpleStringSplitter mStringColonSplitter = new TextUtils.SimpleStringSplitter(':');

    if (accessibilityEnabled==1) {
        Log.d(LOGTAG, "***ACCESSIBILIY IS ENABLED***: ");

        String settingValue = Settings.Secure.getString(getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
        Log.d(LOGTAG, "Setting: " + settingValue);
        if (settingValue != null) {
             TextUtils.SimpleStringSplitter splitter = mStringColonSplitter;
             splitter.setString(settingValue);
             while (splitter.hasNext()) {
                 String accessabilityService = splitter.next();
                 Log.d(LOGTAG, "Setting: " + accessabilityService);
                 if (accessabilityService.equalsIgnoreCase(ACCESSIBILITY_SERVICE_NAME)){
                     Log.d(LOGTAG, "We've found the correct setting - accessibility is switched on!");
                     return true;
                 }
             }
        }

        Log.d(LOGTAG, "***END***");
    }
    else {
        Log.d(LOGTAG, "***ACCESSIBILIY IS DISABLED***");
    }
    return accessibilityFound;
}
person Andrew    schedule 24.02.2011
comment
Я бы рекомендовал просто использовать код из сплиттера и ниже. Верхний код слишком дорог. Это было причиной того, что мое приложение было очень медленным и не знало причины. - person Andreas Lymbouras; 29.06.2014
comment
@ Андрей, я получаю null за settingValue. Не уверен, почему это так. У меня есть разрешение. Я пытаюсь найти способ проверить, включен ли color correction. - person Carrie; 25.05.2016
comment
См. мой ответ для версии этого кода, которая менее запутана и ближе к реализации Android. - person Sam; 13.11.2016
comment
@YabinSong, этот вопрос касается доступности сервисов, но коррекция цвета выглядит как обычная настройка доступности. - person Sam; 13.11.2016

Поскольку API уровня 14, также можно получить включенные службы специальных возможностей через AccessibilityManager:

public static boolean isAccessibilityServiceEnabled(Context context, Class<? extends AccessibilityService> service) {
    AccessibilityManager am = (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
    List<AccessibilityServiceInfo> enabledServices = am.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_ALL_MASK);

    for (AccessibilityServiceInfo enabledService : enabledServices) {
        ServiceInfo enabledServiceInfo = enabledService.getResolveInfo().serviceInfo;
        if (enabledServiceInfo.packageName.equals(context.getPackageName()) && enabledServiceInfo.name.equals(service.getName()))
            return true;
    }

    return false;
}

Использование:

boolean enabled = isAccessibilityServiceEnabled(context, MyAccessibilityService.class);
person Martin    schedule 17.02.2013
comment
Опечатка в вашем примере кода 1-й части. getEnabledAccessibilityServiceList(AccessibilityEvent.TYPES_ALL_MASK) должен быть изменен как getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_ALL_MASK) 2-й параметр getEnabledAccessibilityServiceList() — FeedbackTypeFlags. - person Sam Lu; 02.05.2016
comment
АКТУАЛЬНОЕ решение! - person BamsBamx; 30.09.2016
comment
На самом деле это не работает, потому что я вижу, что моя служба специальных возможностей включена, но getEnabledAccessibilityServiceList() возвращает пустой список (работает на API 28 эмулятора Pixel 2). - person azizbekian; 17.04.2019

Проверка если служба включена

/**
 * Based on {@link com.android.settingslib.accessibility.AccessibilityUtils#getEnabledServicesFromSettings(Context,int)}
 * @see <a href="https://github.com/android/platform_frameworks_base/blob/d48e0d44f6676de6fd54fd8a017332edd6a9f096/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java#L55">AccessibilityUtils</a>
 */
public static boolean isAccessibilityServiceEnabled(Context context, Class<?> accessibilityService) {
    ComponentName expectedComponentName = new ComponentName(context, accessibilityService);

    String enabledServicesSetting = Settings.Secure.getString(context.getContentResolver(),  Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
    if (enabledServicesSetting == null)
        return false;

    TextUtils.SimpleStringSplitter colonSplitter = new TextUtils.SimpleStringSplitter(':');
    colonSplitter.setString(enabledServicesSetting);

    while (colonSplitter.hasNext()) {
        String componentNameString = colonSplitter.next();
        ComponentName enabledService = ComponentName.unflattenFromString(componentNameString);

        if (enabledService != null && enabledService.equals(expectedComponentName))
            return true;
    }

    return false;
}

Использование:

boolean enabled = isAccessibilityServiceEnabled(context, MyAccessibilityService.class);

Определение когда служба включена или отключена

Сделать обратный вызов:

ContentObserver observer = new ContentObserver() {
    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);
        boolean accessibilityServiceEnabled = isAccessibilityServiceEnabled(context, MyAccessibilityService.class);
        //Do something here
    }
};

Подписаться:

Uri uri = Settings.Secure.getUriFor(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
context.getContentResolver().registerContentObserver(uri, false, observer);

Отпишитесь, когда закончите:

context.getContentResolver().unregisterContentObserver(observer);

Обратите внимание, что это не работает с подходом getEnabledAccessibilityServiceList(), поскольку его значения синхронизировать со значениями Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES. Вот почему я думаю, что лучше использовать Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES. размер подходит всем подход.

person Sam    schedule 12.11.2016
comment
лучший ответ на данный момент - person Duna; 13.12.2018
comment
Не работает служба специальных возможностей xiaomi (MiUi). Пока этот метод возвращает true, служба не запущена - person Beloo; 19.04.2021
comment
@Beloo, этот ответ о том, включена ли служба, а не запущена ли она - person Sam; 21.04.2021

Можете ли вы просто отслеживать, работает ли служба так? Если служба специальных возможностей включена, разве она не должна работать??

public class MyAccessibilityService extends AccessibilityService{
public static boolean isEnabled = false; 

 @Override
    public void onServiceConnected() {
      isEnabled = true; 
    }
 @Override 
    public void onDestroy(){ 
      isEnabled = false; 
    }
person Nick    schedule 24.11.2014
comment
Имейте в виду, что «включено» и «работает» немного отличаются. Например, если ваше приложение несколько раз дает сбой, служба может не запуститься снова, пока вы не перезагрузите телефон, даже если она включена. - person Sam; 22.02.2019

Получите идентификатор, когда ваша служба активности только что запустилась. В вашей службе Activity OnSeriviceCeonnected после всех инициализирующих вызовов. Использовать это...

AccessibilityServiceInfo serviceInfo = this.getServiceInfo();
    String accessibilityId = serviceInfo.getId();

Требуется API-интерфейс Jelly Bean

Затем вы можете использовать код Мартина (isAccessibilityEnabled) для проверки запущенных служб.

person DarthJaiz    schedule 09.02.2015
comment
Другой вариант (который я использовал) — сравнить строку описания serviceInfo с описанием, используемым для настройки службы специальных возможностей. Идентификатор не может быть получен, если Служба еще не запущена, что происходит только в том случае, если предоставлено разрешение на доступность. Однако описание можно просто загрузить из ресурсов. - person sparkonhdfs; 16.06.2016
comment
Это работает, но сложнее, чем необходимо; следующие подходы позволяют избежать необходимости хранить идентификатор службы: 1. Запрос настройки Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES; 2. Вызов getEnabledAccessibilityServiceList() и сопоставление resolveInfo с ComponentName службы. - person Sam; 13.11.2016
comment
@DarthJaiz не будет работать при перезагрузке устройства, serviceInfo имеет значение null - person Jack; 24.10.2018
comment
@ Сэм, не мог бы ты подробнее объяснить свой подход - person Jack; 24.10.2018

Может быть, уже слишком поздно, но вот как я проверяю статус службы специальных возможностей:

$ adb shell dumpsys accessibility

Результат:

ACCESSIBILITY MANAGER (dumpsys accessibility)
User state[attributes:{id=0, currentUser=true, accessibilityEnabled=false, touchExplorationEnabled=false, displayMagnificationEnabled=false}
           services:{}]
person Banana droid    schedule 06.08.2018
comment
как выполнить это в java-коде?? - person mhdjazmati; 08.05.2021

 AccessibilityManager accessibilityManager = (AccessibilityManager)context.getSystemService(Context.ACCESSIBILITY_SERVICE);
        List<AccessibilityServiceInfo> runningservice = accessibilityManager.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_ALL_MASK);

        accessibilityManager.addAccessibilityStateChangeListener(new AccessibilityManager.AccessibilityStateChangeListener() {
            @Override
            public void onAccessibilityStateChanged(boolean b) {
                Toast.makeText(MainActivity.this, "permission "+b, Toast.LENGTH_SHORT).show();
            }
        });

Listner будет вызываться всякий раз, когда изменяется состояние, вы можете отслеживать логическое значение, чтобы проверить разрешение, это, безусловно, самое простое и легкое решение для проверки разрешения.

person Priyank Patel    schedule 26.08.2016
comment
В вашем ответе основное внимание уделяется проверке состояния доступности телефона, но в вопросе упоминается I know how to check to see if Accessibility is enabled or disabled on the phone. Однако getEnabledAccessibilityServiceList() выглядит ближе к тому, что он хочет. - person Sam; 13.11.2016

это нужно больше раз

AccessibilityManager am = (AccessibilityManager) context
        .getSystemService(Context.ACCESSIBILITY_SERVICE);
person wanghy    schedule 23.02.2014
comment
и нуждается в дополнительной проверке, чтобы определить, включен ли сервис или нет accessibilityManager.getEnabledAccessibilityServiceList(1), он также может полагаться на прослушиватель onAccessibilityStateChanged - person display name; 09.03.2018