Desconectar un zócalo bluetooth en Android
disconnection (6)
Estoy desarrollando un programa en el que, desde un teléfono con Android, tengo que conectarme como cliente a un sensor médico Bluetooth. Estoy usando la API oficial de Bluetooth y no hay problema durante la conexión (perfil SPP), pero cuando termino el socket, el sensor todavía está conectado a mi teléfono (aunque tengo cerrada la conexión).
¿Hay alguna forma de hacer una desconexión de Bluetooth? Creo que hay una intención llamada ACTION_ACL_CONNECTED, que hace eso. ¿Alguien puede explicarme cómo usar esto?
Gracias por adelantado.
EDITADO: Aquí está el código, si alguien necesita información adicional, es un sensor médico 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();
}
}
}
}
}
Descubrí que si llamo a socket.close () demasiado pronto después de una comunicación reciente a través de OutputStream, el cierre falla y no puedo volver a conectarme. Agregué un Thread.sleep (1000) justo antes de la llamada para cerrar () y esto parece resolverlo.
Estaba desarrollando una aplicación que se conecta a un dispositivo BT. Tu código funciona bien en mi HTC Wildfire pero con un Samsung Galaxy I5700 no funciona. Ambos os son 2.1 actualización pero .....
La excepción fue ''InvocationTargetException''
Lo único que tuve que modificar fue la desconexión ().
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());
}
}
HOLA,
He visto exactamente el mismo problema (HTC Desire). A pesar de cerrar el socket por el libro (como sugiere Brad), el siguiente connect () bloquea para siempre, hasta que termina por close () por otro hilo.
Evité el problema llamando siempre a BluetoothAdapter.disable () /. Enable () antes de conectarme. Horrible, antipático hack, lo sé ...
Sospecho que algunos de los problemas actuales de BT son específicos del fabricante, ya que algunos implementadores de aplicaciones parecen vivir felices con createRfcommSocketToServiceRecord (), que definitivamente falla en mi HTC Desire (Android 2.1 actualización 1).
He visto indicaciones (lo siento, no tengo referencias) de que la pila BT de HTC Desire es diferente a la del Nexus One, aunque parecen ser dispositivos muy similares ...
BR Per
(Además) Aquí hay una actividad muy simple para reproducir el problema (sin mi inhabilitar / habilitar ''cura''):
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 alguien puede detectar si lo estoy haciendo mal, no dude en comentar :)
(Además 2) Creo que lo tengo para trabajar ahora:
- El método oficial para conectar RFCOMM (a través de SDP) ahora parece funcionar (HTC Desire, 2.1 actualización 1), PERO tuve que eliminar y volver a sincronizar el dispositivo BT. Imagínate..
- La reconexión aún puede fallar (falla en el descubrimiento del servicio) si me vuelvo a conectar ''demasiado rápido'' (salgo de la aplicación y luego reinicio de inmediato). Adivina que la conexión aún no ha terminado.
- Si siempre termino la (última) actividad no solo con finish (), sino también con Runtime.getRuntime (). Exit (0) ;, funciona mucho mejor. Ve figura de nuevo ...
Si alguien puede explicar esto, felizmente aprenderé. /Por
(Además 3) Finalmente obtuve la actualización de Froyo (2.2) para mi deseo, y hasta donde puedo ver, SPP ahora funciona :) / por
Hola, he estado usando la aplicación Bluetooth Chat desde el sitio de Desarrollo de Android y proporcionan un método stop()
en la clase BluetoothChatService. Así que simplemente creé una instancia en mi clase principal y llamé a la función de detención desde mi botón de desconexión.
Así es como lo llamo en mi clase principal
// Objeto miembro para los servicios de chat
private BluetoothManager mChatService = null;
case R.id.disconnect:
mChatService.stop();
break;
El método stop () en 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;
}
}
Recuerde cerrar primero las transmisiones de entrada / salida, luego cierre el socket.
Al cerrar las transmisiones, inicia el proceso de desconexión. Después de cerrar el socket, la conexión debe estar completamente desglosada.
Si cierra el socket antes de las transmisiones, puede estar pasando por alto ciertos pasos de apagado, como el cierre (correcto) de la conexión de la capa física.
Este es el método que uso cuando es hora de romper la conexión.
/**
* 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;
}
}
EDITAR: Agregar código para 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;
}
Tengo el mismo problema. Este es el problema con el Módulo Bluetooth CSR BC417, presente en muchos dispositivos como adaptador serie a bluetooth con perfil SPP. Con otro módulo Bluetooth, el dispositivo Android funciona bien, y el bluetooth libera la conexión después de que se cierra el socket, pero con dispositivos con este núcleo CSR no. Probado en SPP Bluetooth a adaptador serie basado en CSR BC417, y módulo Bluetooth de Actisys. Ambos con dispositivos Android 4.0. No sé por qué, pero es un problema de compatibilidad entre harwares, intente cambiar el adaptador de serie por otro con un Core diferente. Pruebo programáticamente para encontrar una solución, incluso deshabilitar un bluetooth, pero es imposible, el problema se origina en el módulo CSR.