Есть ли способ заставить разговор говорить?
Когда я делаю свое приложение доступным, у меня есть проблема - нет способа заставить его ГОВОРИТЬ!!
Ссылаясь на библиотеку 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. Подробнее здесь.