[prg] Исходники к книге Android Accessibility by Tutorials

GvXTlBDMX21fVeDb9XRZ1y6hutG1mjP9p0q3qjrKnZErnjoFJ5btcjQ7yemKsdzNig9jbFHNCm8Z
p
gv4JpS8KK0kKflNWZV8M=;

Приветствую всех!
Исходники (исключительно Kotlin):
https://github.com/raywenderlich/acca-materials/tree/editions/1.0

Книгу на английском тоже нетрудно найти, формат ePub.
Android Accessibility by Tutorials (1st Edition)
Victoria Gonda
2020
Learn to build accessible apps on Android using WCAG through hands-on,
step-by-step tutorials. Accessibility is an important, often overlooked,
part of
building a quality app. The Web Content Accessibility Guidelines (WCAG)
can be confusing and it's often unclear how to apply these guidelines to
Android.
Thank you! By picking up this book, you're proving that you care about
an important topic: accessibility, which is often shortened to a11y.
Whether you're
looking to deepen your existing accessibility knowledge, or are
beginning your learning journey, this book will support your goals. In
the Chapter 1 you'll
discover what accessibility is and answer the question: Why should I
care about accessibility? Once you reach the end of this chapter, you'll
have a number
of answers to that question, and you'll be able to have effective
conversations with your peers about why developers should prioritize
accessibility in
their designs.
Concepts covered in this book:
Importance of accessibility
Oboarding your team to accessible apps
Testing
Web Content Accessibility Guidelines (WCAG)
Android accessibility
Custom views
Who is this book for:
This book is for intermediate Android developers who already know the
basics of Android and Kotlin development and want to learn about
accessibility.

Ответить   (#3673167)

 

Ответы:

Здравствуйте Анатолий. Воспользовавшись поиском по файлам через
notepad++,я обнаружид,что похоже что в книге не упоминается как
добавлять виртуальные View на экран,используя AccessibilityNodeProvider.
К примеру у меня есть список ссылок в textView. Да,теперь у меня
работает мой код (идею я подсмотрел в исходниках telegram для
android),но почему-то на android 4.4.2 клик на виртуальные вью не
срабатывает при фокусировке с помощью свайпов,зато срабатывает при
прямом касании на элемент. В android 11 на xiaomi всё работает шикарно.
У меня есть предположение,что это связано с тем,что я не указывал
координаты для каждой ссылки,т.е виртуальное view использует координаты
основного View. Если бы я вообще не указывал координаты,скринридер бы
просто не видел моего виртуального view. Я попытался указать координаты
ссылки,от части используя исходники класса в android sdk
LinkMovementMethod,но у меня толком ничего не вышло,поэтому я
закомментировал строчку,которая указывает виртуальному view получившиеся
координаты. Зато при касании с использованием исходников
LinkMovementMethod всё работает отлично. Я даже попытался сделать,чтобы
при выходе за приделы ссылки и при входе в её приделы скринридер
факусировался на ней,чтобы незрячие понимали чётко,где расположена
ссылка. Это приложение есть в плеймаркете,но версия с моими доработками
ещё не была выложена основным разработчиком,поэтому если Вам
нетрудно,Анатолий и Никита Цейковец,посмотрите пожалуйста,как я делаю
accessibility ссылок и accessibility сворачивания/разворачивания view и
почему на старых андроидах (4.4.2,а может и выше где-то возможно до 8-го
или 9-го андроида) клик по ссылкам отрабатывает некорректно,или вообще
не отрабатывает. Да,с помощью меню talkback можно найти эти ссылки,но я
всё же хочу добавить их как виртуальные view,т.к тот же jieshuo
screenreader по моим наблюдениям не видит ссылок в тексте да и так по
ссылкам перемещаться,на мой взгляд,быстрее. Я обращаюсь больше именно к
вам,т.к Вы с Никитой эксперты в accessibility android. Если кто-то
захочет воспользоваться моим кодом для автоматического добавления
виртуальных view,мы не против. Вы можете посмотреть мой код на
https://github.com/AlexandrKozlovskiy/OrthodoxCalendar/blob/main/app/src/main/java/oleksandr/kotyuk/orthodoxcalendarfree/accessibility/MyView.java.
Заранее огромное вам спасибо за помощь и прошу прощения у модераторов за
оффтопик. Просто я работаю очень активно с accessibility
приложений,поэтому есть проблемы,которые я не могу сам решить.

Ответить   Tue, 6 Jul 2021 20:17:07 +0300 (#3673197)

 

Приветствую всех!

При активном TalkBack свайп
перемещает accessibility-фокус на следующий элемент в дереве
accessibility-узлов.
Свайп влияют на состояние accessibility-фокуса, а у вас в исходниках
узел не поддерживает действия с ним (закомментированы).

Чтобы ответить на этот вопрос, надо собрать пример и просмотреть его под
отладчиком или добавить вывод в лог везде, где есть сомнения в том, что
делает ваш код.
Например, поставьте вывод в лог в методе performAction, посмотрите с
какими параметрами он вызывается, приходят ли ожидаемые вами action и
тому подобное.
Никто за вас эту работу не сделает.
Как вариант: вместо вызова .onClick() отправьте интент с требуемым uri
при помощи Contex.startActivity().

Успехов. Анатолий.

Ответить   Thu, 8 Jul 2021 19:45:29 +0400 (#3673288)

 

Здравствуйте Анатолий. Да,я закоментил некоторый код,т.к это мне ничего
не дало. Но почему же на 11-м android всё отрабатывает идиально,а на
android 4.4 есть проблемы? А вот если изучением касанием найти эту
ссылку,всё работает нормально даже на android 4.4.2. А по поводу
action,я даже переопределил performClick,т.к на четвёртом android
action_click не приходит,а на 11-й приходит. Если же я укажу левые
координаты (myAccessibilityNodeInfo.setBoundsInScreen(rect) или как-то
так),talkback не будет фокусироваться при свайпе на элементе не при
каком android. По этому может на четвёртом android мой action не
отрабатывает из-за неправильных координат,т.е для каждой ссылки нужно
указать свои координаты? Но тут возникает вопрос,как правильно посчитать
rect для каждой ссылки?

Ответить   Thu, 8 Jul 2021 19:23:34 +0300 (#3673290)

 

Приветствую всех!

А что это должно было дать конкретно? Какой эффект вы ожидали получить,
раскомментировав или закомментировав эти actions у своего
AccessibilityNodeInfo&
Но почему же на 11-м android всё отрабатывает идиально,а на

Наблюдение внешних проявлений, тем более нами (незрячими людьми), не
является основанием для таких однозначных выводах о работе программного
кода.
Когда же вы поймёте, что после написания исходника начинается этап
работы с отладчиком или хотя бы с подробным выводом в лог-файл, чтобы
проанализировать реальную работу вашего кода, а не то, что вам кажется.
До тех пор, пока вы не получите объективной картины происходящего, можно
гадать сколько угодно и даже можно случайно угадать, в чём проблема, но
это не имеет к профессиональному программированию никакого отношения.
Если проблему не удаётся понять под отладчиком или при подробном выводе
в лог-файл, то идут на такие меры, как написание простых фрагментов
кода, которые позволяют прояснить отдельные моменты, потому что большой
код не обладает такой прозрачностью и очевидностью.
Возможно, в Android 11 основной View по умолчанию распространяет
действие на виртуальные, а в 4.4.2 не делает этого, полагаясь на
программиста. Возможно, у вас есть ошибка (например какой-нибудь неявный
рекурсивный вызов метода) и Android 11 лучше справляется с ней, чем
4.4.2. Предположений может быть сколько угодно...

Это опять всего лишь слова. "Нормально" означает лишь то, что ссылка
активируется, но как при этом работает ваш код, остаётся неизвестным.
Если в указанном случае ссылка активируется, то означает ли это, что ваш
AccessibilityNodeInfo получает ACTION_CLICK, так? Вы это видели в лог-файле?

Тогда сравните то, что происходит при перемещении accessibility-фокуса
по ссылкам при свайпах и последующего щелчка по выбранной ссылке; и что
происходит при выборе ссылки изучении касанием и последующем щелчке по ней.

И почему бы не использовать интенты и startActivity, например, если
основной View получает вызов onClick(), то может проанализировать, в
какой accessibility-узел содержит accessibility-фокус и отправить интент
с ссылкой из этого узла (разумеется, если TalkBack не перемещает
accessibility-фокус на элемент, получивший click как событие ввода).

Успехов. Анатолий.

Ответить   Fri, 9 Jul 2021 08:05:09 +0400 (#3673310)

 

Здравствуйте Анатолий. Вы писали

Ну я делал announceForAccessibility,эмулировал креш,типа так: int
a=1/0,но у меня это не отрабатывало. Сейчас даже невсегда вызывается
performClick и это я говорю опять же не наугад. Сейчас,к примеру при
клике по первой ссылке может кликнутся n-ная и не один из методов не
вызовется. Ещё Вы пишете

Ну Вы же видели в моём коде,что никакой рекурсии нету. Ещё Вы пишете

Так я и анализирую в методе performClick номер узла и работаю со
ссылкой. см. массив spans. Фокус получает нужный узел. Просто я перед
коммитом удаляю отладочный код.

Ответить   Sat, 10 Jul 2021 22:20:27 +0300 (#3673378)

 

Приветствую всех!
Ну Вы же видели в моём коде,что никакой рекурсии нету.

Ну вы же видели в моём сообщении, что я говорю о _неявной _ рекурсии, то
есть о той, что может возникнуть по причине ошибки без явного намерения
с вашей стороны.
Неявную рекурсию нельзя обнаружить, только читая исходник.

Во-первых, не надо удалять отладочный код, потому что каждое удаление /
добавление чревато новыми ошибками.
Во-вторых, речь шла о том, чтобы вместо .onClick() использовать интенты.
В общем случае, ваша позиция не совсем понятна: вы хотите мне доказать,
что ваш код правильный и потому ничего из предложенного вы делать не
будите?

Успехов. Анатолий.

Ответить   Sun, 11 Jul 2021 00:49:50 +0400 (#3673380)

 

Здравствуйте Анатолий. Вы писали

Я просто Вас не совсем понимаю,что значит вместо onClick использовать
интенты? Если Вы про action_VIEW в моей activity,т.е тот случай с quest
player,где Вы мне здорово помогли,за что Вам огромное спасибо,так у меня
этот код работает и на четвёртом андроиде. Если Вы про другое,тогда
поясните пожалуйста,что Вы имеете ввиду. Ещё Вы пишете

Нет,я просто хочу показать,что часть из предложенного Вами я делаю и у
меня есть результаты:

1. Talkback корректно фокусируется на нужном узле.

2. метод performAccessibilityAction не вызывается для action_click.

3. Метод performClick не всегда вызывается.

4. При касании ссылки и клике на неё клик отрабатывает,но actionClick
вроде тоже не вызывается.

Поэтому я делаю то,что Вы мне советуете. Только ещё вопрос как
определить неявную рекурсию?

Кстати когда очень много ссылок,хотя у меня все виртуальные view имеют
один и тот же rect в качестве boundsInScreen,на 11-м андроиде перед
фокусировкой на одно из виртуальных view у меня происходит задержка
перед тем,как на него попадёт фокус. Благодаря отладке я проверил,что у
меня,хоть я и удалил этот action,вызывается action

AccessibilityNodeInfo.AccessibilityAction.ACTION_SHOW_ON_SCREEN перед action accessibility_focus. Правда я не
понимаю,какой алгоритм мне использовать для этого action. Возможно нужно
послать событие прокрутки,только какие значения полей нужно вписывать в
это событие.

Ответить   Sun, 11 Jul 2021 03:32:16 +0300 (#3673383)

 

Приветствую всех!

Верно, речь об ACTION_VIEW, то есть вместо

использовать что-то типа (создайте нужный вам интент;здесь просто запуск
браузера с указанной uri):
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(spans[virtualViewId].getText().toString()));
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getContext().startActivity(i);

Возможно, вас заинтересует подраздел "Handle custom touch events" (ну и
остальной материал на странице тоже):
https://developer.android.com/guide/topics/ui/accessibility/custom-views

Успехов. Анатолий.

Ответить   Sun, 11 Jul 2021 12:45:16 +0400 (#3673387)

 

Здравствуйте Анатолий. Огромное Вам спасибо за ссылку. Я даже зарепортил
issue,что там не всё задокументировано как следует
https://issuetracker.google.com/issues/193263961. И всё же вопрос
упирается в одну тему: Как получить координаты виртуального view для
каждой ссылки. У меня толком ничего не вышло,т.е по отладке вроде rect
родительского accessibilityNodeInfo содержит rect каждой ссылки,но при
этом если я добавляю его на экран (info.setBoundsInScreen),то talkback
фокусируется только на одной ссылке (не считая родительской ноды). Также
без координат,как я понимаю не будет происходить прокрутки,а значит при
изучении касанием не получится попасть на все ссылки. Я даже копался в
исходниках talkback,но особо ничего не понял,хотя talkback,судя по
исходникам,очень активно работает с координатами нод. Я пытался считать
координаты так:

int start =builder.getSpanStart(spans[virtualViewId]);
int end=builder.getSpanEnd(spans[virtualViewId]);
CharSequence content=builder.subSequence(start,end);
int startLine=layout.getLineForOffset(start);
int endLine=layout.getLineForOffset(end);
float startClick=layout.getPrimaryHorizontal(start);
float endClick=layout.getPrimaryHorizontal(end);
Rect r=new Rect((int)endClick,layout.getLineTop(startLine),(int)startClick,layout.getLineBottom(endLine));
int[]location=new int[2];
getLocationOnScreen(location);
location[0]-=getScrollX();
location[1]-=getScrollY();
r.offset(location[0],location[1]);
Rect r1=new Rect();
info.getBoundsInScreen(r1);
announceForAccessibility(r1.contains(r)+" "+content);
info.setBoundsInScreen(r);

Я считал координаты,используя примеры из интернета. В документации не очень понятно написано,что даёт метод класса View getLocationOnScreen,но я догадываюсь,что это верхний левый угол View. Теперь вопрос,какие должны быть координаты у виртуального View,Чтобы их принял talkback?
P.s Огромное Вам спасибо за книгу. Я даже оставил комментарии для улучшения книги https://forums.raywenderlich.com/t/errata-for-android-accessibility-by-tutorials-1st-ed/127243/3.`

Ответить   Tue, 13 Jul 2021 21:41:07 +0300 (#3673550)