May 29th, 2014

Chipkit и Ётафон: дополнительно

Завершаем дружить ChipKIT и Yotaphone: в прошлый раз выбрали оборудование, научили ChipKIT и Ётафон видеть друг друга и отправлять друг другу послания. Сейчас несколько завершающих замечаний о работе с акссессуарами на Андроиде, чтобы при случае не хотеть с ними работать так, как они работать не умеют.

О логике работы с аксессуарами в Андроиде

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

Итак, после некоторого количества экспериментов, лично я для себя выделил 2 основных сценария для работы с аксессуарами из приложения:

1) Концепт акрсессуар подключен - экран открыт, аксессуар отключен - экран закрыт. Для запуска приложения нужно полностью положиться на системный диалог подключения аксесуара: пользователь должен или нажимать ОК при каждом подключении или поставить галочку "Использовать по умолчанию для этого USB-аксессуара" и тогда система будет делать это каждый раз за него автоматически. Этот сценарий в целом уже описан выше. Если пользователь нажал кнопку Отмена в диалоге подключения, то нужно считать, что это окончательное решение - при ручном запуске приложения эта ситуация распознается как "нет разрешения для доступа к аксессуару" и в этом случае нужно просто выходить из приложения. При отключении аксессуара тоже выходить из приложения. Чтобы снова получить доступ к аксессуару, просто выдернуть провод и воткнуть заново.

2) Концепт всегда открытого экрана. В этом случае мы считаем, что пользователь сам решает, когда ему открывать и закрывать приложение, работающее с акссуаром, при этом экран приложения следит за системными событиями от аксессуара (подключен, отключен) и в зависимости от ситуации включает или выключает определенные элементы управления.

Для реализации первого подхода в системе есть все необходимое, и оно уже было показано выше.

Второй подход выглядит более традиционным и на первый взгляд наиболее логичным, т.к. похожим образом релизована работа с другими ресурсами и устройствами, которые в любой момент времени могут быть как доступны, так и не доступны (веб-сервер, подключение вай-фай, сигнал GPS) - работающие с ними приложения в этом случае просто отображают их актуальный статус и корректируют свой функционал. Однако с реализацией этого подхода на практике с текущим API Android Accessory возникает ряд проблем, часть из которых кое-как решается, а часть - нет.

Первая проблема - диалог подключения аксессуара - он будет выскакивать всегда и в любом случае до тех пор, пока пользователь не решит нажать кнопку "Использовать по умолчанию". Но в этом случае, система будет запускать новую копию приложения автоматически при подключении USB-шнура поверх уже открытой. Убрать теги, инициализирующие автозапуск из AndroiManifest.xml, тоже не лучший вариант - вместо диалога подключения будет вылезать другой диалог о неподдерживаемом аксессуаре. Поэтому аккуратно реализовать концепт "пользователь сам решит, когда запускать приложение" не получится - останется фактор назойливого диалога подключения аксессуара или второй копии приложения (хотя еще можно попробовать поиграть с флагами для экранов activity - возможо там есть что-то типа не запускать две копии одного экрана, что может сойти за очередную полумеру).

Вторая проблема - хотя в системе определено событие о подключении аксессуара UsbManager.USB_ACCESSORY_ATTACHED, внутри нашего BroadcastReceiver'а на заранее открытом экране мы его получать не сможем - система просто его не присылает, даже если оно добавлено в IntentFilter. Буквально так: выключить все кнопки на экране автоматически при отключении аксессуара мы можем, а включить их обратно при подключении аксессуара автоматически мы уже не можем - только в ручном режиме через меню или специальную кнопку "подлкючиться к аксессуару" на экране. Работать будет, но с красотой как-то так.

Третяя проблема - разработчики API для работы с аксессуарами по какой-то причине решили не использовать стандартные механизмы разграничения доступа к ресурсам устройства (когда разрешение permission на использование указанного ресурса типа выход в интернет, получение сиглана GPS или отправки СМС прописывается в манифесте приложения AndroidManifest.xml), вместо этого запрос на разрешение доступа к подключенному аксессуару выскакивает в специальном диалоге.

Accessory - request permission.png

Приложение может по своему желанию вызвать этот дилог и запросить доступ к аксессуару в том случае, если в предыдущем автоматическом диалоге пользователь нажал Отмена.


Collapse )

подсветка синтаксиса.