web-dev-qa-db-fra.com

La découverte du service a échoué en utilisant Bluetooth sur Android

Je travaille actuellement sur une application Android qui se connecte à un instrument via Bluetooth et doit écrire des commandes de chaîne et recevoir des réponses de chaîne. Actuellement, la connexion/lecture/écriture fonctionne pour TCP/IP sur Wi-Fi et j'essaie maintenant d'implémenter Bluetooth. Mais je rencontre des obstacles. J'ai cherché sur le Web en essayant de trouver des exemples de quelque chose de similaire et je n'ai pas eu de chance. J'utilise le Android: Bluetooth Chat comme principal point de référence.

Mon code actuel semble fonctionner. Ensuite, il déclenche une exception Échec de la découverte du service au moment de la connexion. J'utilise la classe DeviceListActivity pour faire la découverte et la sélection du périphérique auquel je veux me connecter. Il renvoie anActivityResult, puis ma classe Bluetooth attend qu'il gère cela, puis se connecte à celui-ci. Le code ci-dessous est presque identique à l'application Bluetooth Chat.

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if(!m_BluetoothAdapter.isEnabled())
    {
        m_BluetoothAdapter.enable();
    }
    switch (requestCode) {
        case REQUEST_CONNECT_DEVICE:
            // When DeviceListActivity returns with a device to connect
            if (resultCode == Activity.RESULT_OK) {
                // Get the device MAC address
                String address = data.getExtras()
                                     .getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
                // Get the BLuetoothDevice object
                BluetoothDevice device = m_BluetoothAdapter.getRemoteDevice(address);
                // Attempt to connect to the device
                connect(device);
            }
            break;

        case REQUEST_ENABLE_BT:
            // When the request to enable Bluetooth returns
            if (resultCode == Activity.RESULT_OK) {
                // Bluetooth is now enabled, so set up a chat session
            }
            else {
                // User did not enable Bluetooth or an error occured

                Toast.makeText(this, "Bluetooth not enabled", Toast.LENGTH_SHORT).show();
                finish();
            }
    }
}

Voici ma fonction de connexion:

private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

private void connect(BluetoothDevice device) {
    m_Device = device;
    BluetoothSocket tmp = null;

    // Get a BluetoothSocket for a connection with the
    // given BluetoothDevice
    try {
        tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
    }
    catch (IOException e) {

    }
    m_Socket = tmp;

    m_BluetoothAdapter.cancelDiscovery();

    try {
        // This is a blocking call and will only return on a
        // successful connection or an exception
        m_Socket.connect();
    }
    catch (IOException e) {
        try {
            m_Socket.close();
        }
        catch (IOException e2) {
        }
        return;
    }
}

J'espère que tout ce que je fais mal est simple, mais je crains que ce ne soit jamais aussi simple. C'est la première fois que je fais un développement Bluetooth, et je fais peut-être quelque chose de mal flagrant ... Mais je ne sais pas pourquoi je reçois l'exception de découverte de service qui a échoué.

Vous pouvez jumeler/trouver l'appareil à tout moment manuellement sur le téléphone ... Cela nécessite un mot de passe, mais je ne pense pas que ce soit le problème que j'ai.

49
TxAg

Après trois jours, j'ai compris grâce à des messages très utiles.

J'ai dû remplacer:

tmp = device.createRfcommSocketToServiceRecord(MY_UUID);

avec:

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

et voilà ça marche!

93
TxAg

Depuis l'API 15, vous pouvez utiliser la méthode suivante:

Essayez de remplacer votre UUID par la valeur de retour de la méthode getUuids () de la classe BluetoothDevice. Ce qui a fonctionné pour moi était quelque chose comme ceci:

UUID uuid = bluetoothDevice.getUuids()[0].getUuid();
BluetoothSocket socket = bluetoothDevice.createRfcommSocketToServiceRecord(uuid);

La raison pour laquelle cela fonctionne est que différents appareils prennent en charge différents UUID et qu'en obtenant les UUID de l'appareil à l'aide de getUuids , vous supportez toutes les fonctionnalités et tous les appareils.

Une autre nouvelle méthode intéressante (prise en charge depuis l'API 14) est la suivante: BluetoothHealth.getConnectionState . Je ne l'ai pas essayé mais ça a l'air prometteur ...

13
Muzikant

C'était ne modification suggérée d'un utilisateur anonyme essayant de répondre à la réponse acceptée.

Une grande différence entre votre code avant et après est l'UUID que vous passez. J'ai trouvé ma réponse ici: http://developer.Android.com/reference/Android/bluetooth/BluetoothDevice.html#createRfcommSocketToServiceRecord (Java.util.UUID)

J'ai dû remplacer:

tmp = device.createRfcommSocketToServiceRecord(MY_UUID);

avec:

private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
tmp = device.createRfcommSocketToServiceRecord(SPP_UUID);

et le tour est joué! Le code d'origine est pour un poste à poste Android. Cela n'a aucun sens d'utiliser l'UUID de l'application lors de la connexion à un simple périphérique Bluetooth série. C'est pourquoi la découverte échoue.

2
Rup

Ainsi, comme indiqué ci-dessus, le fait est que vous devez utiliser l'UUID que le serveur attend.

Si vous vous connectez à un périphérique Bluetooth, tel qu'un casque ou une souris, vous devez vérifier les UUID que le périphérique écoute. Vous pouvez voir les UUID comme ceci.

UUID[] uuids = bluetoothDevice.getUuids();

Et si vous voulez savoir ce que ces UUID signifient, voir this .

1
Devgrapher

C'est une très vieille question mais j'ai trouvé qu'en utilisant createInsecureRfcommSocketToServiceRecord() au lieu de createRfcommSocketToServiceRecord() avec getUuids()_ précédemment mentionné, faites le astuce pour moi

UUID uuid = bluetoothDevice.getUuids()[0].getUuid();
BluetoothSocket socket = bluetoothDevice.createInsecureRfcommSocketToServiceRecord(uuid);
1
animalito maquina