Комментарии 49
:) это случайно не я ваш "заказчик"? прям про меня написано :)
Два, точнее три вопроса:
- Насколько это решение применимо к телефонам/планшетам на Андроиде с заделом на будущее?
- Если да, то каковы шансы провести приложение в Google Play?
- А что с Apple?
1. Решение прекрасно ложиться на телефоны/планшеты на android, так как нет никаких видимых причин на изменение поведения. Работа с USB хорошо документирована, поддерживается (возникают новые методы, устаревают старые) гуглом и нет предпосылок к изменению этого в будущем.
2. Опять же не вижу причин не попасть в Google Play. Политика гугл в этом отношении сейчас достаточно жесткая, но конкретно к работе с USB, каких-то особых требований я не видел. К тому же, как правило, все что Вам нужно сделать, это в манифесте задекларировать uses-feature, остальное Google Play сделает за Вас. Вероятно у Вас возникают сомнения, когда вы видите слово Custom. Но это напрямую относится к периферийному устройству, но даже с его сертификацией, проблем не возникнет (если вы приобрели свой VID и PID). С точки зрения Android, каких то отклонений от нормы нет.
3. Не могу Вам ответить на этот вопрос, не смотрел. Но опять же повторю, протокол достаточно стандартизирован, и если у Apple есть возможность дотянуться до USB из вашего application, Вы с большой вероятностью сможете легко подружить его с Вашим периферийным устройством.
Повторюсь, основная магия все равно идет в железе на периферийном устройстве, по причине того, что в данном случае Android используется, как host. Вероятно, если вы захотите использовать Android в качестве device, то Вам придется пережить все танцы с бубном, связанные с дескрипторами, но это уже немного другой уровень погружения в usb стек, хоть и тоже весьма поверхностный
Тут вопрос в том, что не идет ли предпосылка в телефонах/планшетах к отказу от USB вообще? Т.е. в Apple, например, USB вообще нет, а всякие Lightning, что вынуждает делать отдельную версию устройства под них, да еще и с чипом. В андроидах сейчас идет Type C и может быть в конце-концов тоже уйдет, как и разъем для наушников, или придумают такую же фигню, как Apple с чипом "Certified for Android"?
"если вы приобрели свой VID и PID" — вот это уже начинает напрягать. Т.е. прикинуться чайником (или FTDI каким-нибудь) может уже не получиться? Просто кастомизация все больше и больше не в почете у гигантов.
Что касается использования USB в смартфонах в отрыве от статьи, прогнозировать сложно, но мне на данный момент сложно предположить подобное развитие событий именно для android смартфонов. USB протокол прост в реализации на уровне железа, программный стек достаточно хорошо подходит почти для всех задач и прекрасно отработан и документирован. Изменение типа разъема, спецификации и прочего это одно, а вот убрать разъем целиком, это совсем другое дело. Согласен, большую часть стандартных вещей можно и без USB провернуть, даже дебажить можно по Wi-Fi. Но боюсь закрыть все дыры таким образом не получится. К тому же я не по совсем понимаю, зачем его убирать. С разъемом наушников все понятно, а вот USB… Чип USB стоит немного, небольшой по размеру, если его убрать, места на плате не сильно уменьшится. К тому же текущая тенденция увеличения размера экрана, позволяет об этом не париться. Если речь идет о размере разъема, то если уже и он мешает, то я не знаю, насколько тонкие телефоны нужны человечеству)
2. Кастомизация происходит на уровне периферийного устройства, к Android отношения не имеет, если речь идет о host. VID и PID придется приобрести, правда не во всех случаях)) FDTI — это не к USB. Сам протокол он не реализует, а является лишь преобразователем интерфейса. К слову о FTDI, USART на Android, насколько мне известно, тоже можно потрогать из Вашего Application
fun sendReport(data: ByteArray) {
usbConnection?.bulkTransfer(usbOutEndpoint, data, data.size, 0)
}
собственно Вы уже привели тут единственный метод.
FTDI, USART на чистой яве? это фантастика. Вам придется
работать через оберку с двоичной либой.
github.com/chzhong/serial-android
Я так понимаю Вы говорите именно про Bluetooth, безотносительно к USB.
Насколько мне известно Android смартфон мог играть роль Device достаточно давно по крайней мере в Bluetooth Low Energy. В классическом Bluetooth это вероятно является нововведением, к сожалению не знаю, так как при разработке чаще пользовался BLE — стабильнее работает, по крайней мере со стороны embedded железки (точнее соотношение цена/стабильность получше)
Играть роль Device (например, мышь) через BLE мне его стабильно заставить так и не удалось, что-то в стеке всё-таки реализовано странно, по крайней мере в последних версиях: где-то на Marshmallow-Nougat это ещё работало, но дальше практически перестало нормально работать. Ну а Device через Bluetooth Classic — это действительно нововведение.
Извините, но я с Вами не согласен. Да, с одной стороны характеристики и сервисы в bluetooth low energy действительно напоминают usb hid report, но только по структуре разве что. На этом сходства заканчиваются. Работают они абсолютно по разному. Я хотел даже привести здесь пример различий, но понял, что привести его достаточно сложно, потому что отличается все кроме этой самой структуры.
BLE действительно не похож ни разу.
Если речь идет про протокол HID натянутый поверх Bluetooth, то это просто протокол HID, который по идее спецификой USB не является. можно пользовать где угодно. Вот только отношения к Bluetooth я так и не просек)
Bluetooth HID is a lightweight wrapper of the human interface device protocol defined for USB. The use of the HID protocol simplifies host implementation (ex: support by operating systems) by enabling the re-use of some of the existing support for USB HID to also support Bluetooth HID.
Все Bluetooth Classic устройства ввода (а это разнообразные мыши, клавиатуры, джойстики, и т.п.) по сути общаются по тому же самому USB HID протоколу, сообщая хосту те же самые дескрипторы и репорты.
Ну а BLE — это уже другой профиль, известный как GATT…
Для коммерческих продуктов стандартный драйвер не всегда хорошая идея. К примеру драйвер VCP под Windows просто ужасный. Позволяет все прекрасно запустить на малых скоростях и небольших объёмах данных, но шаг вправо, шаг влево и драйвер выдает удивительные вещи. Попробуйте предавать по VCP с STM большой объем данных и при этом щелкать мышкой на ПК (знаю, звучит глупо), на котором вы принимаете данные. Уверяю Вас, часть данных вы не получите.
например. флайчик. все программные тесты говорят юсб поддерживается, а железки нет.
Поэтому простой тест. Берем мышку. Берем флешку. Втыкаем через отг кабель.
Вместо конкретных vid&tid в хмл для фильтрации можно просто классы написать.
Просто работать с устройствами, которые поддерживают булк на ендпоинтах.
Эмуляция COM порта гиморой.
Согласен, к тому же я заметил, что android работает и с interrupt конечными точками через булк методы. Подробное поведение нигде не описано, так что можно схватить не логичное поведение
Каждый раз после коннекта устройство считается новым и идет запрос пермишинов.
Единственное юзабельное решение.
Становится слушателем на все подключения. Тогда у пользователя появиться
вариант «открывать ваше приложение при подключении всегда».
Активити слушатель этого может быть пустышкой. Нужно только для автополучения
разрешения. Ну а я в своей проге меняю настроки в этом случае так (транспорт-usb,vid,pid).
Еще в андроиде не получиться подключить два устройства с одинаковыми vid&pid одновременно, так как смотри выше обход дерева требуется, чтобы найти устройство.
А uri адрес устройства при каждом конекте новый.
usbConnection?.bulkTransfer(usbOutEndpoint, data, data.size, 0), выполнилось неправильно.
<usb-device vendor-id="1155" product-id="22352" />
приписал также и <usb-device vendor-id="1240" product-id="63"/> // Microchip USB HID
Также изменил
const val VENDOR_ID = 1240//1155
const val PRODUCT_ID = 63//22352
При втыкания устройства в USB-порт ожидалось, что как только я подключу устройство он предложит запустить программу (не предложил, в списке остались только ранее написанный мною программы).
Поменять VID и PID в res/xml/device_filter.xml на свои.
Для дальнейшего взаимодействия изменить CUSTOM_HID_INTERFACE на тот, с которым вы работаете, ну и репорты привести в соответствие с вашими.
Если хотите, чтобы ваше приложение реагировало на подключение устройства, надо добавить интент фильтр в манифест.
< intent-filter >
< action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
< /intent-filter >
_?xml version="1.0" encoding="utf-8"?_
_resources_
_usb-device class="02" /_
_usb-device class="07" /_
<usb-device class="255" />
_/resources_
а vid & pid через сеттинги приложения
Можно и так, правда в таком случае вы скорее всего интент на подключение не получите от конкретно вашего устройстаа
говоришь. открывать всегда c помощью приложения.
в манифесте
uses-permission android:name=«android.permission.USB_PERMISSION»
uses-feature android:name=«android.hardware.usb» android:required=«false»
< activity
android:name=".activity.UsbKnownActivity"
android:excludeFromRecents=«true»
android:noHistory=«true»
android:theme="@android:style/Theme.NoDisplay"
< intent-filter >
< action android:name=«android.hardware.usb.action.USB_DEVICE_ATTACHED» / >
< /intent-filter >
< meta-data
android:name=«android.hardware.usb.action.USB_DEVICE_ATTACHED»
android:resource="@xml/device_filter" / >
в активити запоминаю в сеттингах vid & pid
Да, но при таком раскладе, ваше приложение будет реагировать на любое устройство с тем классом, который вы описали в device_filter. В данном случае вы будете реагировать на любое устройство реализующее интерфейс 07h, к примеру, т.е. Printer
Если вы хотите реагировать на интент при подключении конкретного устройства (или серии устройств), то надо прописывать VID и PID в device_filter
7 — представляется принтером, 255 — прочие.
например китайский шнурок для старых принтеров.
photos.app.goo.gl/zzkndEFGscHbtF2dA
USB-OTG кабели тоже могут быть виноваты в том, что устройство не находиться. Через беленькую штучку видится, через короткий кабель нет ;(
Диалог на следующем рисунке может иметь варианты. Если программ
под фильтр окажется несколько, появиться выбор из нескольких вариантов.
поставили галку на себя или другую. Дальше будет молча
Согласен, это действительно так.
Но, насколько мне известно, (возможно я конечно не прав, но все же), если поставить правильные VID и PID в фильтр, то подобные диалоги будут появляться только в случае, если вы подключите ваше устройство. (Вы также можете поставить галочку и больше не получать диалог, а сразу запускать приложение)Во всех остальных случаях, вы диалог получать не будете в принципе. Если я сейчас подключу к телефону мышку, то диалог я не получу и мышка будет спокойно работать.
А если указать в вашем приложение в device_filter класс устройства, как сделали в коде выше Вы, то я буду получать диалог при каждом подключении устройства этого класса. Если устраивает такое поведение, то тогда это правильный шаг.
2. У меня я проверил в коде другой программы, которая видит устройство тоже CUSTOM_HID_INTERFACE при коннекте.
3. Репорты пока не менял, т.к. у него ошибка на этапе коннекта.
4. Да, после добавления в манифест реагирует, спасибо.
Сейчас какую-нибудь мышку попробую потестировать, может с мышкой законнектится.
Подебажде метод подключения. Находит ли устройство, затем интерфейс
P.S. Мышка (Logitech) тоже не запустилась.
P.P.S. Я собираю под API 22, может быть в этом проблема?
Критические ошибки я себе через интент кидаю в errorActivity
Да согласен, с предыдущим комментарием, отлаживать надо через Wi-Fi. Она и не запустится просто так, проверяйте интерфейсы и дебажте функцию коннекта, чтобы понять в чем причина.
Данный пример не панацея, для корректной работы надо описать Ваше конкретное устройство
На эмуляторе никогда не пробовал, не могу посоветовать и если честно, не уверен, что это легко можно провернуть на стандартном эмуляторе. Но опять же, не пробовал и даже не пытался вникать в тему
и 16 гиг оперативы имхо слишком жирно.
Я недавно добил с 4 до 12 свой старенький комп. Стало легче. Но эмулятор все равно медленный. А на 4х нельзя было держать одновременно студию, эмулятор и хотя бы одну вкладку в хроме.
idx in 0..usbInterface!!.endpointCount
на
idx in 0..usbInterface!!.endpointCount-1
В модуле UsbHelper.kt
общий принцип.
пройтись по всем
проверить тип и направление ( возможно еще что-то нужное именно Вам)
подходящее запомнить
Ну да, в данной статье рассмотрен конкретный кейс. Цели написать универсальную библиотеку не было) Дело в том, что это custom hid и как правило назначение и номера конечных точек вы должны знать и в моем примере, даже поиск этих точек излишен по идее. Формально получить их по номерам можно, просто задефайниф значения номеров с учётом направления.
Но если вы хотите пройтись по всем, и вывести к примеру информацию, то да, есть смысл этот кусок кода преобразовать по вашему замыслу)
Во первых в цикле дает неопределенность (выходной последний найденный).
И есть еще ендпоинты, которые для управления, а не для передачи данных.
Да, конечные точки для управления есть, но не содержатся в интерфейсе, и таким циклом вы их не найдете.
Что касается цикла, то он перебирает конечные точки по направлению передачи, а не по типу. В данном случае они могут быть либо IN, либо OUT, а тип конечной точки и тип передачи (Bulk, Isoc, Interrupt) в данном случае не рассматриваются.
Из этого проистекает то, что цикл не дает неопределенности, все вполне логично — если точка не имеет направление IN, то она имеет направление OUT. И цель определить это, а не тип точки, тип передачи, размер пакета, частоту опроса и прочие параметры конечной точки, которые имеет место быть и важны в той или иной ситуации. Однако для того, чтобы передавать и принимать данные этого достаточно, а большего в этом примере и не нужно)
Работаем с USB Custom HID на Android