Connexion RFCOMM Bluetooth ne pouvait pas être établie consécutivement sur Android 4.2
j'ai une application qui parle à un appareil personnalisé via RFCOMM via Bluetooth. Le code de communication est basé sur le projet BluetoothTalk sample. Il fonctionnait sans aucun problème auparavant sur Galaxy S3, Galaxy S2, Galaxy Note et Nexus 7.
récemment, Nexus 7 ont été mis à niveau à Android 4.2 et depuis lors, le problème se produit comme suit:
Lorsque vous utilisez l'application pour configurer une connexion pour la première fois, ce qui signifie que l'appareil est juste activé et app est juste lancé, pas de problème, vous pouvez obtenir des données normalement.
Alors si vous arrêtez de la communication, et essayez de redémarrer, la communication échoue avec l'erreur "java.io.IOException: bt socket fermée, lire retour: -1". À partir de là, peu importe le nombre de fois où vous essayez de vous reconnecter, cela échoue tout simplement.
la seule façon de le faire fonctionner à nouveau est, si vous redémarrez le périphérique personnalisé et l'application, puis essayer de se connecter, la communication devient normal. Mais ensuite, une fois que vous arrêtez et redémarrez la communication, il continue à échouer.
J'ai emprunté un Nexus 4 avec Android 4.2 et le problème reste.
c'est vraiment ennuyeux parce que la valeur principale de notre appareil est de compter sur L'application RFCOMM Bluetooth. J'ai vérifié deux fois la documentation sur BT dans Android 4.2 et n'ai vu aucun changement significatif. Je suis assez confiant sur le code de mon côté parce qu'il fonctionne pour tout Android l'appareil ne fonctionne pas 4.2
toute suggestion serait grandement appréciée. Le dispositif doit faire l'objet d'une interdiction dès le début du mois de décembre et nous voulons vraiment aborder cette question dès que possible.
EDIT: maintenant que 4.2.1 a été libéré et que le problème n'est toujours pas résolu. Pouvons-nous au moins obtenir une confirmation quant à savoir si elle est en train de fonctionner et si elle sera bientôt réparée?
8 réponses
cela ne vous aide pas beaucoup, mais notez que Google a introduit une nouvelle pile Bluetooth avec 4.2.
cela devrait être une bonne chose - dans mon expérience en tant qu'utilisateur et développeur, Android avec Bluez (l'ancien combo) n'a jamais fonctionné de manière fiable, donc j'ai été très heureux d'entendre qu'ils ont entrepris une réécriture totale.
je pense que tout ce que je peux dire c'est que vous avez rencontré un bug ou une bizarrerie dans la nouvelle pile. Il est regrettable d'entendre qu'il y a des problèmes avec la nouvelle pile.
en ce qui concerne votre démo, notez que Google publie les images du micrologiciel pour tous ses périphériques Nexus (https://developers.google.com/android/nexus/images), et les clignoter sur vos appareils est assez facile.
je vous suggère donc de déposer un rapport de bogue et ensuite flash vos appareils à 4.1.2.
Il m'est arrivé dans mes tests. I le code d'échantillon BluetoothChat vous devriez regarder à la méthode connectlost. Je ne me souviens pas s'il y a une variable qui garde le nombre de connexions perdues, mais vous pouvez l'ajouter vous-même. dans la méthode du coût de connexion, tester si le nombre de connexions perdues est inférieur à un nombre prédéfini (dans mon cas 3). Si c'est vrai, envoyez un message à l'interface utilisateur avec mHandler ( un toast) et appelez connect(périphérique) à nouveau. Si ce n'est pas vrai (vous avez perdu la connexion plus plus de 3 fois), la méthode call stop ().
assurez-vous également d'ouvrir la douille en ConnectThread comme ceci:
public ConnectThread(BluetoothDevice device, boolean isSecure) {
mmDevice = device;
BluetoothSocket tmp = null;
mSocketType = isSecure ? "Secure" : "Insecure";
// Get a BluetoothSocket for a connection with the given BluetoothDevice
if (isSecure) {
// reflection is better to use
Method m = null;
try {
Log.d(TAG, "create reflection");
m = device.getClass().getMethod("createRfcommSocket",new Class[] { int.class });
} catch (NoSuchMethodException e1) {
e1.printStackTrace();
}
try {
tmp = (BluetoothSocket) m.invoke(device, 1);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
mmSocketFallBack = tmp;
} else {
Log.d(TAG, "create insecure");
try {
tmp = device
.createInsecureRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
e.printStackTrace();
}
}
mmSocket = mmSocketFallBack;
}
votre coût de connexion devrait ressembler à quelque chose comme:
public void connectionLost() {
init = false;
Log.d(TAG, "connectionLost -> " + mConnectionLostCount);
mConnectionLostCount++;
if (mConnectionLostCount < 3) {
// Send a reconnect message back to the Activity
Message msg = mHandler.obtainMessage(cBluetooth.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(WebAppInterface.TOAST, "Connection lost. Reconnecting...");
msg.setData(bundle);
mHandler.sendMessage(msg);
connect(mSavedDevice,true);
} else {
mConnectionLostCount = 0;
Message msg = mHandler.obtainMessage(cBluetooth.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(WebAppInterface.TOAST,"Device connection was lost!");
msg.setData(bundle);
mHandler.sendMessage(msg);
cBluetooth.this.stop();
}
}
j'espère que vous pouvez les adapter à votre cas. Vous pouvez le vérifier ce trop de liens, ils m'ont beaucoup aidé:
j'ai eu un problème similaire et j'ai passé du temps à déboguer ce problème. J'exécute Android 4.3 et j'ai trouvé que la seule modification de base qui était nécessaire pour BluetoothChat sample code était le réglage:
MY_UUID_SECURE = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
j'essaie de me connecter à un module bluetooth HC-05 et je crois qu'il utilise le profil SPP indiqué par cet UUID. Vous pouvez interroger L'UUID d'un périphérique avec cette ligne de code:
UUID uuid = device.getUuids()[0].getUuid();
vérifier L'UUID et voir si elle correspond avec un profil qui a du sens, en fonction du type d'appareil que vous connectez.
MY_UUID_SECURE = uuid;
L'UUID peut indiquer un type différent de profil d'appareil, selon ce à quoi vous vous connectez. Avec L'UUID approprié, j'étais encore capable d'exécuter le code AcceptThread et d'écouter comme un BluetoothServerSocket sans aucun problème. J'espère que cela aide, cependant, je suis relativement nouveau à Android et Bluetooth développement, Donc si mes hypothèses sont fausses, s'il vous plaît corriger moi.
ont rencontré des problèmes similaires. Fixe certains d'entre eux en construisant avec le 4.2 SDK avec 17 comme cible de construction.
j'ai finalement trouvé la solution.
Il s'avère que ce n'est pas un bug dans le nouveau pilote Bluetooth. C'est un cas de coin non pris en compte dans L'application d'échantillon Bluetooth, plus précisément, le projet BluetoothChat, fourni par Android SDK.
dans le code de service Bluetooth à L'intérieur de BluetoothChat sample project, lorsque la connexion est défaillante ou perdue, il démarre toujours le service pour redémarrer le mode d'écoute. Ce n'est pas un problème quand le téléphone est utilisé comme serveur, cependant, dans certains cas, lorsque le téléphone est utilisé comme client, une fois qu'il passe en mode d'écoute, vous ne pouvez pas vous connecter à d'autres serveurs. Parce que dans la fonction" connect", il n'annule pas (In)SecureAcceptThread. Vous écoutez donc essentiellement d'autres connexions en tant que serveur tout en essayant de vous connecter à d'autres serveurs en tant que client. Il est en conflit.
la façon de résoudre ce problème est, si vous êtes sûr que votre téléphone ne sera pas utilisé comme serveur écoutant la connexion entrante, puis tout simplement supprimer le code pour redémarrer le mode d'écoute en cas de panne ou d'arrêt de la connexion.
Rencontré le même problème avec mon Nexus 4.
dans mon cas, je pense que le problème réside dans le protocole de découverte du service SDP. Le périphérique et le serveur doivent utiliser le même UUID pour un certain service.
j'utilise le protocole SPP (serial port protocol) dans mon application. Donc je change UUID de ce qui est dans le code d'échantillon de BluetoothChat comme "fa87c0d0-afac-11de-8a39-0800200c9a66" à SPP "00001101-0000-1000-8000-00805F9B34FB". Maintenant c'est la fin.
Et j'ai désactiver le code d'écoute pour acceptThread dans BluetoothChatService.commencer.)( Plus concis maintenant. J'espère que ça aidera.
j'ai la même expérience sur 4.2.2.
mais j'ai constaté que la pile bluetooth commence à mal se comporter seulement après la chute de mon application ou est tuée sans avoir nettoyé correctement les ressources (socket et/ou flux). Avant que quand je ferme mon application correctement, il fonctionne très bien.
par exemple quand je ferme la socket et que je tue l'application, je peux la démarrer et me connecter à nouveau normalement. Si je tue mon application sans fermer précédemment socket il est damné et je dois redémarrer le appareil pour le faire fonctionner à nouveau.
il semble donc que la nouvelle pile de bluetooth Android a un bug dans le mécanisme de nettoyage implicite. Quand une application tombe Android devrait nettoyer les ressources bluetooth ouverte qui ne se produit pas.
mon code de gestion bluetooth est dans la sous-classe Application. Il n'y a aucun moyen - ou Je ne peux pas voir un - comment accrocher sur l'Application détruire et faire le nettoyage.
toute suggestion apprécié
EDIT:
j'ai fait un contournement assez désordonné.
j'ai créé une application séparée contenant un seul service à distance. J'ai transféré tout le code de communication (socket et streams d'ouverture, de lecture, d'écriture, de fermeture) dans ce service à distance. Ensuite, si l'application se bloque ou est tué, le service est toujours en cours d'exécution. Lorsque je démarre à nouveau l'application, la connexion est toujours en place. Les octets lus à partir du flux d'entrée bluetooth sont transféré dans l'application principale via un service de messagerie standard. Pour mon cas, c'est ok car je transfère de très petites quantités de données.
Encore lorsque l'application contenant le service est tué même désordre qui se passe.
je fais face au même problème. Cela fonctionne pour moi:
try {
Thread.sleep(1000);
}
catch(Exception e3)
{
Toast.makeText(getApplicationContext(), "wa ni sud sa thread sleep!", Toast.LENGTH_SHORT).show();
}
btSocket.close();