49 votes

Exception d'échec de la découverte du service avec Bluetooth sur Android

Je travaille actuellement sur une application Android qui se connecte à un instrument via Bluetooth et j'ai besoin d'écrire des commandes de chaîne et de recevoir des réponses de chaîne en retour. Actuellement, la connexion/lecture/écriture fonctionne pour TCP/IP sur Wi-Fi et j'essaie maintenant de mettre en œuvre Bluetooth. Mais je me heurte à des obstacles. J'ai fait des recherches sur le web pour essayer de trouver des exemples de quelque chose de similaire, mais je n'ai pas eu de chance. J'ai utilisé l'exemple de la ressource Android developer : Bluetooth Chat comme point de référence principal.

Mon code actuel semble fonctionner Ensuite, une exception de type "Service Discovery Failed" est levée au moment de la connexion. J'utilise le DeviceListActivity pour découvrir et sélectionner l'appareil auquel je veux me connecter. Elle renvoie unActivityResult et ma classe Bluetooth attend qu'elle le traite pour s'y connecter. Le code ci-dessous est presque identique à celui de l'application de chat Bluetooth.

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

C'est 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 ce que je fais mal est simple, mais j'ai peur que ce ne soit jamais aussi simple. C'est la première fois que je fais du développement Bluetooth, et peut-être que je fais quelque chose de complètement faux... Mais je ne suis pas sûr pourquoi j'obtiens l'exception de découverte de service échouée.

Vous pouvez jumeler/trouver l'appareil à tout moment manuellement sur le téléphone... Il faut un code d'accès, mais je ne pense pas que ce soit le problème que je rencontre.

93voto

TxAg Points 957

Après trois jours, j'ai trouvé la solution grâce à des messages très utiles.

J'ai dû le 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 !

1 votes

Attendez, j'ai quelques applications Bluetooth et je n'ai pas trouvé de situation où l'utilisation de la réflexion (getclass.getmethod) est nécessaire. Pouvez-vous m'en dire un peu plus sur le matériel que vous avez essayé ? Je suis très intéressé de savoir si la réflexion est réellement nécessaire dans certaines situations.

0 votes

Après quelques tests. J'ai découvert que c'était en fait le téléphone qui avait des problèmes avec ça. Le HTC Incredible ne s'est pas connecté en utilisant la première méthode, mais le Samsung Galaxy S et un autre, je ne me souviens plus lequel, se sont connectés du premier coup.

0 votes

Je souffrais de cette exception et cette solution a semblé résoudre mes problèmes. Comprenez-vous ce qui se passe ici et pourquoi cela résout le problème de l'échec de la découverte de service ?

13voto

Muzikant Points 2073

À partir de l'API 15, vous pouvez utiliser la méthode suivante :

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

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

La raison pour laquelle cela fonctionne est que différents dispositifs supportent différents UUIDs et en obtenant les UUIDs du dispositif à l'aide de getUuids vous prenez en charge toutes les fonctionnalités et tous les dispositifs.

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

2voto

Rup Points 17863

C'était une modification suggérée par un utilisateur anonyme en 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û le 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 voilà, ça marche ! Le code original est pour une application Android peer to peer. Cela n'a aucun sens d'utiliser l'UUID de l'application quand on se connecte à un simple appareil bluetooth en série. C'est pourquoi la découverte échoue.

0 votes

Et maintenant un autre utilisateur anonyme commente : La modification suggérée utilise exactement la même méthode que le code qui ne fonctionne pas. Le code qui fonctionne utilise une méthode non publique différente qui ne nécessite pas l'uuid.

0 votes

J'ai obtenu la même erreur que ci-dessus en essayant d'écrire une application Android qui se connecte à un scanner Bluetooth. Cette solution a fonctionné pour moi.

0 votes

@Monsingor Je ne peux pas faire de commentaire, j'ai juste pris la modification suggérée - mais s'il vous plaît, dites-nous pourquoi, ou mieux encore, modifiez et corrigez la réponse.

1voto

Devgrapher Points 87

Comme indiqué ci-dessus, l'essentiel est d'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 quels UUID le périphérique écoute. Vous pouvez voir les UUIDs comme ceci.

UUID[] uuids = bluetoothDevice.getUuids();

Et si vous voulez savoir ce que ces UUIDs signifient, voir este .

1voto

animalito maquina Points 1120

Il s'agit d'une vieille question, mais j'ai découvert qu'en utilisant la fonction createInsecureRfcommSocketToServiceRecord() au lieu de createRfcommSocketToServiceRecord() ainsi que le getUuids() mentionnés précédemment font l'affaire pour moi

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X