Подтвердить что ты не робот

"Обнаружение службы не удалось" с Android Bluetooth Insecure 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 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 Listening for Connections

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 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]", после чего я получаю стек для исключения "Неудачное обнаружение службы".

4b9b3361

Ответ 1

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

clientSocket.connect()

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

btAdapter.cancelDiscovery()

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

Ответ 2

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

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

Также это поможет, если вы можете вставить полные журналы на кодах ошибок API на стороне клиента и на стороне сервера, если они есть.

Ответ 3

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

Второе устройство не вызвало метод listenUsingInsecureRfcommWithServiceRecord, прежде чем вы попытаетесь вызвать "createInsecureRfcommSocketToServiceRecord" с 1-го устройства.

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

 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();
            }
        }

Ответ 4

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

Ответ 5

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

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

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

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

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

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

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