我正在开发一个程序,其中,从Android手机,我必须作为客户端连接到蓝牙医疗传感器。我正在使用官方蓝牙API并且在连接期间没有问题(SPP配置文件),但是当我结束插座时,传感器仍然连接到我的手机(虽然我已经关闭连接)。
有没有办法让蓝牙断开连接?我认为有一个名为ACTION_ACL_CONNECTED的意图,它就是这样做的。任何人都可以解释我如何使用它吗?
提前致谢。
编辑:这是代码,如果有人需要其他信息,它是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();
}
}
}
}
}
答案 0 :(得分:59)
请记得首先关闭输入/输出流,然后关闭套接字。
通过关闭流,您可以启动断开连接过程。关闭套接字后,连接应完全分解。
如果在流之前关闭套接字,则可能会绕过某些关闭步骤,例如(正确)关闭物理层连接。
这是我在分解连接时使用的方法。
/**
* 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;
}
}
编辑:添加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;
}
答案 1 :(得分:13)
我发现如果我在最近通过OutputStream进行通信后过早地调用socket.close(),则关闭失败并且我无法重新连接。我在调用close()之前添加了一个Thread.sleep(1000),这似乎解决了它。
答案 2 :(得分:9)
HI,
我已经看到了完全相同的问题(HTC Desire)。 尽管本书关闭了套接字(正如Brad建议的那样),但下一个connect()会永远阻塞 - 直到另一个线程以close()结束。
我通过在连接之前始终调用BluetoothAdapter.disable()/。enable()来规避问题。可怕的,不友好的黑客,我知道......
我怀疑目前的一些BT问题是制造商特定的,因为一些应用程序实现者似乎与createRfcommSocketToServiceRecord()幸福地生活在一起,这肯定在我的HTC Desire(Android 2.1更新1)上失败。
我已经看到HTC Desire的BT堆栈与Nexus One不同的迹象(对不起,没有参考),尽管它们似乎是非常相似的设备......
BR 每
<强>(加)强> 这是一个非常简单的活动来重现问题(没有我的禁用/启用'治愈'):
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");
}
}
如果有人能够发现我做错了,请随意发表评论:)
(补充2) 我想我现在就开始工作了:
如果有人能够解释这一点,我会高兴地学习。 /每
(补充3) 终于得到了我的欲望的Froyo(2.2)更新,据我所知,SPP现在可以工作:) /每
答案 3 :(得分:2)
我正在开发一款适用于BT设备的应用。您的代码在我的HTC Wildfire中工作正常,但使用三星Galaxy I5700无法正常工作。这两个操作系统都是2.1更新但是......
例外是'InvocationTargetException'
我唯一需要修改的是disconnect()。
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());
}
}
答案 4 :(得分:1)
嘿所以我一直在使用Android开发网站上的蓝牙聊天应用程序,他们在BluetoothChatService类中提供了stop()
方法。所以我只是在我的主类中创建了一个实例,并从我的断开按钮调用了stop函数。
以下是我在主课程中的称呼方式
//聊天服务的成员对象
private BluetoothManager mChatService = null;
case R.id.disconnect:
mChatService.stop();
break;
BluetoothChatService中的stop()方法
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;
}
}
答案 5 :(得分:0)
我有同样的问题。 这是蓝牙模块CSR BC417的问题,在许多设备中作为具有SPP配置文件的串行到蓝牙适配器存在。 使用另一个蓝牙模块Android设备运行良好,蓝牙在套接字关闭后释放连接, 但是没有这个CSR核心的设备。 基于CSR BC417的SPP蓝牙到串行适配器和Actisys的蓝牙模块进行了测试。 两者都使用Android 4.0设备。 我不知道为什么但是harware之间存在兼容性问题,尝试使用不同的Core更改另一个的串行适配器。 我试图以编程方式找到解决方案,甚至禁用蓝牙,但是不可能,麻烦来自CSR模块。