Как разговаривать с клавиатурой Bluetooth?

Я написал приложение для Android, которое подключается к клавиатуре Bluetooth. Он подключается через разъем BT к клавиатуре и получает входной поток сокета.

InputStream inStrm = socket.getInputStream();

Затем я попытался прочитать поток ввода, но он говорит, что нет доступных байтов.

int nBytesAvail = inStrm.available(); // always gives me 0

Или же

int  dataByte = inStrm.read(); // always generates IOException

Исключение говорит: программное обеспечение вызвало разрыв соединения

Если я пытаюсь выполнить запись в поток, я получаю еще одно исключение: конечная точка транспорта не подключена.

Может происходить одно из двух.

  1. Мой первый страх состоит в том, что есть HID-протокол, который нужно говорить с клавиатурой, и он не раскроет свои секреты, пока я не произнесу правильное заклинание. Это верно? Или об этом должен позаботиться стек BT BT автоматически? Поток сокетов кажется стандартным последовательным потоком, и я не уверен, что это правильно.

  2. Мой второй страх состоит в том, что, поскольку это Galaxy Tab, моя проблема может заключаться в том, что эта конкретная часть операционной системы была удалена Samsung (но получу ли я по-прежнему действительный входной поток из сокетного соединения?). Широко сообщается, что американские версии Tab просто не будут подключаться к каким-либо BT HID с использованием стандартных утилит Android BT, хотя передача файлов BT работает нормально.

Я полагаю, что третья возможность состоит в том, что я просто пропускаю нажатия клавиш, когда они происходят. Я не знаю, сколько Java выполняет буферизацию данных BT, поступающих из HID, но если соединение с сокетом установлено, данные должны появиться во входном потоке, нет?

Я не хочу тратить на это гораздо больше времени на тот случай, если поступлю совершенно неправильно (см. № 1) или он обречен на провал (см. № 2).

3 ответа

Все обычные Bluetooth-клавиатуры реализуют профиль HID, для которого требуется соединение L2CAP. До сих пор Android предоставляет только возможность использовать соединения RFCOMM. Вам нужно будет использовать Native Development Kit и написать код клавиатуры на C, чтобы использовать bluez для достижения своей цели. Посмотрите на приложения, которые используют Nintendo WiiMote. WiiMote также реализует профиль HID.

Ответ mringwal верный, кроме подхода NDK, возможно использование отражения на некоторых устройствах для достижения соединения L2CAP:

public static BluetoothSocket createL2CAPBluetoothSocket(String address, int psm){
        return createBluetoothSocket(TYPE_L2CAP, -1, false,false, address, psm);
    }
    // method for creating a bluetooth client socket
    private static BluetoothSocket createBluetoothSocket(
            int type, int fd, boolean auth, boolean encrypt, String address, int port){
        try {
            Constructor<BluetoothSocket> constructor = BluetoothSocket.class.getDeclaredConstructor(
                    int.class, int.class,boolean.class,boolean.class,String.class, int.class);
            constructor.setAccessible(true);
            BluetoothSocket clientSocket = (BluetoothSocket) 
                constructor.newInstance(type,fd,auth,encrypt,address,port);
            return clientSocket;
        }catch (Exception e) { return null; }
    }

где TYPE_L2CAP является целым числом, имеющим постоянное значение 3.

Обратите внимание, что этот подход будет работать только на некоторых устройствах Android.

Написание HID-приложения не простая задача. Вам необходимо реализовать анализатор дескриптора отчета, компонент, используемый для "обнаружения" возможностей (специальных клавиш, функций) удаленного устройства HID. Вам также нужно будет изучить протокол HID и рабочий процесс, копию можно найти здесь: http://www.dawidurbanski.pl/public/download/projekty/bluepad/HID_SPEC_V10.pdf

Уже есть профессиональные программы, которые делают именно это, поддерживая HID на Android, см., Например, это программное обеспечение: http://teksoftco.com/index.php?section=product&pid=24

Из-за ограничений стека протокол L2CAP доступен не на всех устройствах, поэтому решение, которое работает на ВСЕХ устройствах, в настоящее время невозможно.

Некоторые Galaxy Tab поддерживают протокол HID, некоторые нет. Это зависит от носителя, а не от Samsung. Моя Verizon Galaxy Tab была без поддержки HID, хотя у T-Mobile она была. Но в апреле этого года Verizon (не Samsung) выпустил обновление прошивки, которое включало поддержку HID, так что моя клавиатура BT и мышь начали работать. Я использую Android 2.2, и мой номер сборки прошивки SCH-I800.EC02.

Я думаю, что вы пытаетесь сделать это, потому что ваша вкладка не будет подключаться к клавиатуре BT вообще. Это именно то, что я пытался сделать до апреля. Из того, что я помню, магическая часть заклинания должна обрабатываться Android автоматически: когда вы устанавливаете HID-соединение, Android открывает окно сообщения, чтобы ввести код на клавиатуре, затем сокетное соединение возвращается вашей программе (Или что-то в этом роде).

Поэтому, если вы не можете заставить Tab подключаться к клавиатуре в обычном режиме, тогда ваш профиль HID отключен, и (afaik) никакое количество программ не заставит его работать, кроме, возможно, переписывания профиля HID в Java.

Я уверен, что вы уже пробовали это, но чтобы проверить это, перейдите в Настройки> Беспроводные сети> Настройки Blutetooth, вы должны увидеть клавиатуру в списке, независимо от того, поддерживает ли она HID. Нажмите на запись клавиатуры, он должен подключиться сразу. Если это просто задерживается на неопределенное время или вы получаете сообщение об ошибке, то у вас нет поддержки HID.

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