"Обнаружение службы не удалось" из Android Bluetooth Небезопасный Rfcomm

Кто-нибудь знает, как создать небезопасное соединение RFCOMM между двумя устройствами Android на уровне API 2.3.3 при использовании произвольно объявленного имени службы? (не случайное или не меняющее имя службы, просто имя службы, которое я определяю сам)

подробности

Я пытаюсь создать небезопасное соединение Rfcomm между двумя устройствами Android: Droid X2 и Asus Transformer. Я предполагаю, что оба этих устройства имеют функциональность на уровне Android 2.3.3, чтобы фактически получить возможность использовать небезопасный Rfcomm.

Когда я пытаюсь создать соединение Bluetooth, как описано здесь, используя теперь общедоступные createInsecureRfcommSocketToServiceRecord() и listenUsingInsecureRfcommWithServiceRecord(SERVICE, UUID), я получаю сообщение:

java.io.IOException: Service discovery failed
at android.bluetooth.BluetoothSocket$SdpHelper.doSdp(BluetoothSocket.java:377)
at android.bluetooth.BluetoothSocket.connect(BluetoothSocket.java:201)
at com.s4d.bluenomad.DeviceConnections$ClientThread.run(DeviceConnections.java:406)

Я нашел связанный вопрос, где кто-то, создающий нормальное соединение, получал эту ошибку и использовал отражение, чтобы вызвать частный метод. Однако я понятия не имею, какой приватный метод теперь будет соответствовать инициации "небезопасного" соединения. Я попытался использовать решение, предложенное в этом связанном вопросе, но Android попросил меня соединить устройства, и это именно то, чего мне нужно избегать. Мне действительно нужен небезопасный подход.

Я даже попробовал комбинацию официальных и взломанных решений, изложенных здесь

Соответствующие фрагменты кода

Создание ServerThread для прослушивания соединений

Log.i(TAG, "Constructing a ServerThread");
// Use a temporary object that is later assigned to serverSocket,
// because serverSocket is final
BluetoothServerSocket tmp = null;
try {
    // MY_UUID is the app's UUID string, also used by the client code
    tmp = btAdapter.listenUsingInsecureRfcommWithServiceRecord(SERVICE_NAME, SERVICE_UUID);
    Log.i(TAG,"Started listening on insecure RFCOMM channel for service requests for: " + SERVICE_NAME);
} catch (IOException e) { }
serverSocket = tmp;

ServerThread Прослушивание для соединений

BluetoothSocket socket;
while(true)
{
    try
    {
        socket = serverSocket.accept();
    }
    catch( IOException e)
    {
        break;
    }

    if( socket != null )
    {
        Log.i(TAG, "Received new socket connection requesting service: " + SERVICE_NAME);
    }
    else
    {
        Log.i(TAG, "Socket connection attempted, but socket received is NULL.");
    }
}

Создание ClientThread для инициации соединений

Log.i(TAG, "Constructing a ClientThread");
BluetoothSocket tmp = null;
try {
    // MY_UUID is the app's UUID string, also used by the server code
    tmp = device.createInsecureRfcommSocketToServiceRecord(SERVICE_UUID);
    Log.i(TAG,"Created client socket on insecure RFCOMM channel for service requests for: " + SERVICE_NAME);
} 
catch (IOException e) 
{ 
    Log.i(TAG, "Failed to createInsecureRfcommSocket() against MAC: " + device.getAddress());
}
clientSocket = tmp;

ClientThread Подключение к серверу

try
{
    clientSocket.connect();
}
catch( final IOException e)
{
    DeviceConnections.this.runOnUiThread(new Runnable()
    {

        @Override
        public void run() 
        {
            console.append("Client unable to connect to service.");
            Log.i(TAG, "Client socket unable to connect() to: " + clientSocket.getRemoteDevice().getAddress());
            e.printStackTrace();
        }

    });

}

Я получаю вывод журнала "Клиентский сокет не может подключиться () к: [MY_MAC_ADDRESS]", затем получаю трассировку стека для исключения "Обнаружение службы не удалось".

5 ответов

Решение

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

clientSocket.connect()

Мне нужно было позвонить

btAdapter.cancelDiscovery()

Я видел это в документации, но это было указано как проблема "производительности" - в моем случае кажется, что это была "функциональная" проблема. После того, как я добавил вызов отмены обнаружения, соединение с сокетом работало немедленно.

Несколько вещей, чтобы проверить

  • использование одинакового и уникального UUID как на клиенте, так и на сервере.
  • Иметь разрешение BLUETOOTH
  • Попробуйте со стандартным общеизвестным SPP UUID 00001101-0000-1000-8000-00805F9B34FB

Также это поможет, если вы можете вставить полные журналы на клиентские и серверные коды печати API, если таковые имеются.

"Ошибка обнаружения службы" просто означает, что наше устройство не может найти службу с таким же UUID на любом другом устройстве.

Второе устройство не вызвало метод listenUsingInsecureRfcommWithServiceRecord до того, как вы попытаетесь вызвать метод createInsecureRfcommSocketToServiceRecord с первого устройства.

Убедитесь, что этот код был выполнен на втором устройстве (например, onResume() или при нажатии кнопки /optionsItem), прежде чем пытаться подключиться с первого устройства.

 if ((mChatService != null) &&  (mBluetoothAdapter.isEnabled())) {
// Only if the state is STATE_NONE, do we know that we haven't started already
if (mChatService.getState() == BluetoothChatService.STATE_NONE) {
// Start the Bluetooth chat services
mChatService.start();
            }
        }

Вам следует изменить 8ce255c0-200a-11e0-ac64-0800200c9a66 на любой другой UUID, и вы можете использовать имя своей службы, поскольку 8ce255c0-200a-11e0-ac64-0800200c9a66 используется для предопределенной службы BluetoothChatInsecure

Внедрение Android Bluetooth является болезненным, потому что это может варьироваться на разных устройствах.

Я испытывал ту же проблему. В моем конкретном случае ошибка произошла, когда хотя бы одно из устройств BluetoothAdapter.getScanMode() был установлен на BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE (т.е. устройство может быть обнаружено и подключено с удаленных устройств Bluetooth).

Это любопытно, потому что устройство должно быть подключаемым, но это не так.

Если устройство getScanMode() ==SCAN_MODE_CONNECTABLE, то никакой ошибки не возникает.

К настоящему времени решение, которое я нашел, состоит в том, чтобы показывать предупреждение пользователям, чтобы они подключались только к сопряженным устройствам. Если устройства не сопряжены, пользователь должен использовать настройки Android и выполнить работу.

Включение связи Bluetooth только для сопряженных устройств устраняет необходимость обнаружения и, следовательно, позволяет избежать "Обнаружение службы не удалось".

Опять же, это мой конкретный случай на моем конкретном устройстве. Это не может быть общим правилом, но надеюсь, что это поможет любому, кто получает ту же ошибку.

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