Je suis en train de développer un programme dans lequel, à partir d'un téléphone Android, je dois me connecter en tant que client à un capteur médical Bluetooth. J'utilise l'API Bluetooth officielle et aucun problème lors de la connexion ( Profil SPP), mais lorsque je termine la prise, le capteur est toujours connecté à mon téléphone (bien que j'aie fermé la connexion).
Existe-t-il un moyen de procéder à une déconnexion Bluetooth? Je pense qu'il y a une intention appelée ACTION_ACL_CONNECTED, qui fait cela. Quelqu'un peut-il m'expliquer comment l'utiliser?
Merci d'avance.
EDITÉ: Voici le code, si quelqu'un a besoin d'informations supplémentaires, c'est un capteur médical Nonin 4100.
Set<BluetoothDevice> pairedDevices = Activa.myBluetoothAdapter.getBondedDevices();
// If there are paired devices
if (pairedDevices.size() > 0) {
// Loop through paired devices
for (BluetoothDevice device : pairedDevices) {
// Add the name and address to an array adapter to show in a ListView
String name = device.getName();
if (name.contains("Nonin")) {
try {
found = true;
// socket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
// handler.sendEmptyMessage(5);
// Activa.myBluetoothAdapter.cancelDiscovery();
// socket.connect();
BluetoothDevice hxm = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(device.getAddress());
Method m;
try {
m = hxm.getClass().getMethod("createRfcommSocket", new Class[]{int.class});
socket = (BluetoothSocket)m.invoke(hxm, Integer.valueOf(1));
handler.sendEmptyMessage(5);
socket.connect();
} catch (Exception e) {
handler.sendEmptyMessage(7);
e.printStackTrace();
break;
}
handler.sendEmptyMessage(6);
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
byte[] retrieve = { 0x44, 0x31};
out.write(retrieve);
byte [] ack = new byte [1];
in.read(ack);
if (ack[0] == 0x15) {
cancelMeasurement();
return;
}
byte [] data = new byte [3];
long timeStart = System.currentTimeMillis();
this.timePassed = System.currentTimeMillis() - timeStart;
while ((this.timePassed < (this.time))&&(this.finished)) {
try {
in.read(data);
processData(data);
Thread.sleep(1000);
this.timePassed = System.currentTimeMillis() - timeStart;
} catch (Exception e) {
e.printStackTrace();
}
}
in.close();
out.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
N'oubliez pas de fermer d'abord vos flux d'entrée/sortie, puis fermez le socket.
En fermant les flux, vous lancez le processus de déconnexion. Après avoir fermé le socket, la connexion doit être complètement interrompue.
Si vous fermez le socket avant les flux, vous pouvez ignorer certaines étapes d'arrêt, telles que la fermeture (correcte) de la connexion de la couche physique.
Voici la méthode que j'utilise lorsqu'il est temps de rompre la connexion.
/**
* Reset input and output streams and make sure socket is closed.
* This method will be used during shutdown() to ensure that the connection is properly closed during a shutdown.
* @return
*/
private void resetConnection() {
if (mBTInputStream != null) {
try {mBTInputStream.close();} catch (Exception e) {}
mBTInputStream = null;
}
if (mBTOutputStream != null) {
try {mBTOutputStream.close();} catch (Exception e) {}
mBTOutputStream = null;
}
if (mBTSocket != null) {
try {mBTSocket.close();} catch (Exception e) {}
mBTSocket = null;
}
}
EDIT: Ajout de code pour connect ():
// bluetooth adapter which provides access to bluetooth functionality.
BluetoothAdapter mBTAdapter = null;
// socket represents the open connection.
BluetoothSocket mBTSocket = null;
// device represents the peer
BluetoothDevice mBTDevice = null;
// streams
InputStream mBTInputStream = null;
OutputStream mBTOutputStream = null;
static final UUID UUID_RFCOMM_GENERIC = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
/**
* Try to establish a connection with the peer.
* This method runs synchronously and blocks for one or more seconds while it does its thing
* SO CALL IT FROM A NON-UI THREAD!
* @return - returns true if the connection has been established and is ready for use. False otherwise.
*/
private boolean connect() {
// Reset all streams and socket.
resetConnection();
// make sure peer is defined as a valid device based on their MAC. If not then do it.
if (mBTDevice == null)
mBTDevice = mBTAdapter.getRemoteDevice(mPeerMAC);
// Make an RFCOMM binding.
try {mBTSocket = mBTDevice.createRfcommSocketToServiceRecord(UUID_RFCOMM_GENERIC);
} catch (Exception e1) {
msg ("connect(): Failed to bind to RFCOMM by UUID. msg=" + e1.getMessage());
return false;
}
msg ("connect(): Trying to connect.");
try {
mBTSocket.connect();
} catch (Exception e) {
msg ("connect(): Exception thrown during connect: " + e.getMessage());
return false;
}
msg ("connect(): CONNECTED!");
try {
mBTOutputStream = mBTSocket.getOutputStream();
mBTInputStream = mBTSocket.getInputStream();
} catch (Exception e) {
msg ("connect(): Error attaching i/o streams to socket. msg=" + e.getMessage());
return false;
}
return true;
}
J'ai constaté que si j'appelle socket.close () trop tôt après une communication récente via OutputStream, la fermeture échoue et je ne peux pas me reconnecter. J'ai ajouté un Thread.sleep (1000) juste avant l'appel à close () et cela semble le résoudre.
SALUT,
J'ai vu exactement le même problème (HTC Desire). Malgré la fermeture du socket par le livre (comme Brad le suggère), le prochain connect () se bloque pour toujours - jusqu'à ce qu'il soit terminé par close () par un autre thread.
J'ai contourné le problème en appelant toujours BluetoothAdapter.disable () /. Enable () avant de me connecter. Hack horrible et hostile, je sais ...
Je soupçonne que certains des problèmes BT actuels sont spécifiques au fabricant, car certains implémenteurs d'applications semblent vivre heureux avec createRfcommSocketToServiceRecord (), qui échoue définitivement sur mon HTC Desire (Android 2.1 mise à jour 1).
J'ai vu des indications (désolé, je n'ai pas de références) que la pile BT du HTC Desire diffère du Nexus One, bien qu'il semble s'agir d'appareils très similaires ...
BR Per
(ajout) Voici une activité très simple pour reproduire le problème (sans désactiver/activer le "traitement"):
package com.care2wear.BtTest;
import Java.io.IOException;
import Java.io.InputStream;
import Java.io.OutputStream;
import Java.lang.reflect.InvocationTargetException;
import Java.lang.reflect.Method;
import Android.app.Activity;
import Android.bluetooth.BluetoothAdapter;
import Android.bluetooth.BluetoothDevice;
import Android.bluetooth.BluetoothSocket;
import Android.os.Bundle;
import Android.util.Log;
import Android.widget.TextView;
public class BtTestActivity extends Activity {
private static final String TAG="BtTest";
BluetoothAdapter mBtAdapter = null;
BluetoothDevice mBtDev = null;
BluetoothSocket mBtSocket = null;
InputStream isBt;
OutputStream osBt;
String mAddress = "00:18:E4:1C:A4:66";
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
init();
connect(); // ok
disconnect(); // ok
connect(); // this invariably fails - blocked until BT is switched off by someone else, or the peer device turns off/goes out of range
disconnect();
}
private void init() {
Log.d(TAG, "initializing");
mBtAdapter = BluetoothAdapter.getDefaultAdapter();
mBtDev = mBtAdapter.getRemoteDevice(mAddress);
Log.d(TAG, "initialized");
}
private void connect() {
try {
Log.d(TAG, "connecting");
Method m = mBtDev.getClass().getMethod("createRfcommSocket", new Class[] { int.class });
mBtSocket = (BluetoothSocket) m.invoke(mBtDev, 1);
mBtSocket.connect();
Log.d(TAG, "connected");
} catch (SecurityException e) {
Log.e(TAG, "SecEx", e);
} catch (NoSuchMethodException e) {
Log.e(TAG, "NsmEx", e);
} catch (IllegalArgumentException e) {
Log.e(TAG, "IArgEx", e);
} catch (IllegalAccessException e) {
Log.e(TAG, "IAccEx", e);
} catch (InvocationTargetException e) {
Log.e(TAG, "ItEx", e);
} catch (IOException e) {
Log.e(TAG, "IOEx", e);
}
}
private void disconnect() {
Log.d(TAG, "closing");
if (isBt != null) {
try {
isBt.close();
} catch (IOException e) {
Log.e(TAG, "isBt IOE", e);
}
isBt = null;
}
if (osBt != null) {
try {
osBt.close();
} catch (IOException e) {
Log.e(TAG, "osBt IOE", e);
}
osBt = null;
}
if (mBtSocket != null) {
try {
mBtSocket.close();
} catch (IOException e) {
Log.e(TAG, "socket IOE", e);
}
mBtSocket = null;
}
Log.d(TAG, "closed");
}
}
Si quelqu'un peut repérer si je le fais mal, n'hésitez pas à commenter :)
(ajout 2) Je pense que je l'ai fait fonctionner maintenant:
Si quelqu'un peut expliquer cela, je l'apprendrai avec plaisir. /Par
(ajout 3) J'ai enfin obtenu la mise à jour Froyo (2.2) pour mon Desire, et pour autant que je puisse voir, SPP fonctionne maintenant :)/Per
Je développais une application qui se connecte à un appareil BT. Votre code fonctionne bien dans mon HTC Wildfire mais avec un Samsung Galaxy I5700 ne fonctionne pas. Les deux OS sont une mise à jour 2.1 mais .....
L'exception était "InvocationTargetException"
La seule chose que j'ai dû modifier, c'est la déconnexion ().
private void disconnect() {
if(Conectado){
try {
***mBtSocket.close();***
texto.setText(texto.getText()+"\nDesconectado");
Conectado = false;
} catch (IOException e1) {
// TODO Auto-generated catch block
texto.setText(texto.getText()+"\n"+e1.getMessage());
}
catch (Exception e2) {
// TODO Auto-generated catch block
texto.setText(texto.getText()+"\n"+e2.getMessage());
}
}
Hé, donc j'utilise l'application Bluetooth Chat du site de développement Android et ils fournissent une méthode stop()
dans la classe BluetoothChatService. J'ai donc simplement créé une instance de celle-ci dans mon classe principale et et appelé la fonction d'arrêt de mon bouton de déconnexion.
Voici comment je l'appelle dans ma classe principale
// Objet membre pour les services de chat
private BluetoothManager mChatService = null;
case R.id.disconnect:
mChatService.stop();
break;
La méthode stop () dans BluetoothChatService
private AcceptThread mAcceptThread;
private ConnectThread mConnectThread;
public synchronized void stop()
{
if (mConnectThread != null)
{
mConnectThread.cancel(); mConnectThread = null;
}
if (mConnectedThread != null)
{
mConnectedThread.cancel(); mConnectedThread = null;
}
if (mAcceptThread != null)
{
mAcceptThread.cancel(); mAcceptThread = null;
}
}
J'ai le même problème. C'est le problème avec le module Bluetooth CSR BC417, présent dans de nombreux appareils comme adaptateur série à bluetooth avec profil SPP. Avec un autre module Bluetooth Android fonctionne bien, et le bluetooth libère la connexion après la fermeture du socket, mais pas avec les appareils avec ce noyau CSR. Testé sur SPP Bluetooth vers adaptateur série basé sur CSR BC417 et le module Bluetooth d'Actisys. Tous les deux avec des appareils Android 4.0. Je ne sais pas pourquoi mais c'est un problème de compatibilité entre les logiciels, essayez de changer l'adaptateur série pour un autre avec un Core différent. J'essaie par programme pour trouver une solution, même en désactivant un bluetooth, mais c'est impossible, le problème provient du module CSR.