Есть ли способ заставить разговор говорить?

Когда я делаю свое приложение доступным, у меня есть проблема - нет способа заставить его ГОВОРИТЬ!!

Ссылаясь на библиотеку Google, я делаю

public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event)

на моем настроенном представлении, и я получаю правильное сообщение о событии - я проверил его с помощью Log.d
Тем не менее, нет никакого способа заставить разговор говорить...
Мое приложение запускается из API8, поэтому я не могу использовать также,

onPopulateAccessibilityEvent()

Я не так думаю? Пожалуйста, кто-нибудь, помогите мне...

5 ответов

Решение

Если вы хотите, чтобы он говорил, используйте TextToSpeech API. Он берет строку и читает ее вслух.

Для людей, которые хотят реализовать код @Carter Hudson на Java (не судите меня, потому что я все еще не использую Kotlin в 2019 году):

AccessibilityManager accessibilityManager = (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
AccessibilityEvent accessibilityEvent = AccessibilityEvent.obtain();
accessibilityEvent.setEventType(AccessibilityEvent.TYPE_ANNOUNCEMENT);

accessibilityEvent.getText().add("Text to be spoken by TalkBack");
if (accessibilityManager != null) {
    accessibilityManager.sendAccessibilityEvent(accessibilityEvent);
}

Мне нужно было сообщить, когда кнопка стала видимой после перезагрузки RecyclerViewпредметы с новым набором данных. RecyclerView будучи структурным представлением, он поддерживает общение / доступность из коробки. После загрузки новых данных, talkback автоматически объявляет "показывать элементы от x до y из z". Использование TTS API для решения описанного выше варианта использования приводит к следующим подводным камням:

  • Инициализация и управление экземпляром TTS громоздки и сомнительны по следующим причинам:
    • Управление жизненным циклом экземпляра TTS с помощью прослушивателя onInit
    • Управление настройками локали
    • Управление ресурсами через shutdown() привязывает вас к ActivityЖизненный цикл в соответствии с документацией
    • OnDestroy для Activity не гарантированно будет вызван, что кажется плохим механизмом для вызова shutdown() для того, чтобы освободить ресурсы TTS.

Более простое и удобное решение - хорошо играть с TalkBack и использовать Accessibility API, например, так:

class AccessibilityHelper {
    companion object {
        @JvmStatic
        fun announceForAccessibility(context: Context, announcement: String) {
            context
                .getSystemService(ACCESSIBILITY_SERVICE)
                .let { it as AccessibilityManager }
                .let { manager ->
                    AccessibilityEvent
                        .obtain()
                        .apply {
                            eventType = TYPE_ANNOUNCEMENT
                            className = context.javaClass.name
                            packageName = context.packageName
                            text.add(announcement)
                        }
                        .let {
                            manager.sendAccessibilityEvent(it)
                        }
                }
        }
    }
}

Вызывайте выше, где вам нужно (я добавил метод к моей основной деятельности, который перенаправляет помощнику). Это вставит объявление в очередь сообщений, чтобы TalkBack объявлял вслух и не требует обработки экземпляров TTS. Я закончил тем, что добавил параметр и механизм задержки в свою окончательную реализацию, чтобы отделить эти события от текущих событий, инициируемых пользовательским интерфейсом, поскольку они иногда имеют тенденцию перекрывать ручные объявления.

Очень это инструмент, его можно использовать везде с охраной

      public static void speak_loud(String str_speak) {
    if (isGoogleTalkbackActive()) {
        AccessibilityManager accessibilityManager = (AccessibilityManager) getDefaultContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
        AccessibilityEvent accessibilityEvent = AccessibilityEvent.obtain();
        accessibilityEvent.setEventType(AccessibilityEvent.TYPE_ANNOUNCEMENT);

        accessibilityEvent.getText().add(str_speak);
        if (accessibilityManager != null) {
            accessibilityManager.sendAccessibilityEvent(accessibilityEvent);
        }
    }
}


 public static boolean isGoogleTalkbackActive() {
        AccessibilityManager am = (AccessibilityManager) getDefaultContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
        if (am != null && am.isEnabled()) {
            List<AccessibilityServiceInfo> serviceInfoList = am.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_SPOKEN);
            if (!serviceInfoList.isEmpty())
                return true;
        }
        return false;
    }

announceForAccessibilityМетод, определенный в классе View, вероятно, служит этой цели. Он был представлен на уровне API 16. Подробнее здесь.

Другие вопросы по тегам