Должен ли я оставить bluetooth-отражение взлома в производственном коде?

Я работаю над проектом, где мне нужно подключиться через bluetooth к принтеру. Производитель принтера заявляет, что с телефоном смогут подключаться только телефоны Android, имеющие SPP (профиль последовательного порта).

Вот как я сначала открыл соединение:

UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); //SPP long UUID BluetoothSocket socket = device.createRfcommSocketToServiceRecord(uuid); 

Использование UUID – единственный способ открыть соединения RFCOMM с использованием общедоступного API Android с JellyBean. Работая раньше с подключениями SPP в BlackBerry и JavaME, где UUID не требуются, я нашел это немного странным. UUID – это сервисное обнаружение, то есть использование SDP для запроса об услугах, присутствующих в устройстве. Мне действительно не нужно инициировать открытие, так как у меня есть мой принтер в паре заранее, и я знаю, что он поддерживает SPP. Однако это именно то, что делает метод BluetoothDevice.createRfcommSocketToServiceRecord и небезопасная версия. Это стек SPP, где мы можем видеть, как SDP является другим протоколом на том же уровне, и поэтому должно быть возможно использовать RFCOMM, не инициировав сначала:

  ----------------------------------- | My Application | ----------------------------------- | Serial Port Emulation | | or other API | ----------------------------------- | RFCOMM | SDP | ----------------------------------- | LMP | L2PCAP | ----------------------------------- | Baseband | ----------------------------------- 

Я начал тестировать свое приложение на нескольких старых устройствах HTC без проблем. Позже, тестирование на телефонах Samsung, несколько устройств не смогли открыть соединение. Эти телефоны, как утверждается, не поддерживают профиль SPP, как по спецификации производителя, так и по сторонним спецификациям ( EDIT: спецификации сторонних производителей SPP поддерживаются, а спецификации производителя недостаточно точны ). IOException (Service Discovery failed) было сброшено, и я выполнил подход, показанный в этом вопросе:

Обнаружение сбоя службы с помощью Bluetooth на Android

Предлагаемое решение заключается в использовании взлома отражения, а именно:

  Method m = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class}); BluetoothSocket socket = socket = (BluetoothSocket) m.invoke(device, 1); 

Взлом работал для меня. Удивительно, но этот метод в классе BluetoothDevice является общедоступным, но он удаляется из API с помощью аннотации @hide. Это исходный код JellyBean:

  /** * Create an RFCOMM {@link BluetoothSocket} ready to start a secure * outgoing connection to this remote device on given channel. * <p>The remote device will be authenticated and communication on this * socket will be encrypted. * <p> Use this socket only if an authenticated socket link is possible. * Authentication refers to the authentication of the link key to * prevent man-in-the-middle type of attacks. * For example, for Bluetooth 2.1 devices, if any of the devices does not * have an input and output capability or just has the ability to * display a numeric key, a secure socket connection is not possible. * In such a case, use {#link createInsecureRfcommSocket}. * For more details, refer to the Security Model section 5.2 (vol 3) of * Bluetooth Core Specification version 2.1 + EDR. * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing * connection. * <p>Valid RFCOMM channels are in range 1 to 30. * <p>Requires {@link android.Manifest.permission#BLUETOOTH} * * @param channel RFCOMM channel to connect to * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection * @throws IOException on error, for example Bluetooth not available, or * insufficient permissions * @hide */ public BluetoothSocket createRfcommSocket(int channel) throws IOException { return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, true, true, this, channel, null); } 

Я не понимаю, почему публичный метод удаляется из API таким образом. Но, позволяя этому приложению, как этот метод, так и официально поддерживаемый с использованием UUID – это тонкие конверты, вызывающие один и тот же конструктор BluetoothSocket с различными параметрами:

  public BluetoothSocket createRfcommSocketToServiceRecord(UUID uuid) throws IOException { return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, true, true, this, -1, new ParcelUuid(uuid)); } 

Копаясь немного больше в источниках, я понял, что оба открывают соединение RFCOMM, но метод UUID инициирует обнаружение, а скрытый – нет.

В целом, рефлекторные хаки работают безупречно в каждом устройстве, которое я тестировал, от OS 2.2 до 4.1. EDIT: «неисправные» устройства поддерживают SPP, просто их пользовательская реализация BT-стека запутывается с процессом обнаружения; Есть и другие ошибки, такие как отображение диалога сопряжения для уже сопряженных устройств в ICS. Вызов этого скрытого API с помощью отражения позволяет обходным путем для всех этих ошибок или различного поведения, введенного различными производителями .

Должен ли я держать взломать производственный код? Есть ли способ достичь этого с помощью публичного API?

Заранее спасибо.

Solutions Collecting From Web of "Должен ли я оставить bluetooth-отражение взлома в производственном коде?"

Превосходный вопрос. В основном вы можете использовать отражение, которое вы хотите. Даже я сделал что-то подобное, чтобы рассчитать время запуска приложения, получил метод через отражение и его работу как шарм от FroYo до Jelly Bean. Это единственное слово предостережения, которое вам нужно проявить,

  • Поскольку это не общедоступный API, Google может изменить его в любое время без предупреждения
  • Если он изменится, системные приложения или HAL, которые его используют, будут соответственно изменены без каких-либо последствий для приложений.

Где вам нужно быть осторожным?

Скорее всего, аргументы этого метода могут быть изменены в будущем.

Поэтому вам нужно будет проверить это с каждой новой версией ОС, чтобы ваше приложение не сломалось. В противном случае вам не нужно беспокоиться об использовании этого взлома. Во многих приложениях используются такие хаки, когда они не работают с API.