我编写了一个应用程序,它定期尝试连接到配对设备,如果连接成功,则执行一个操作。我有一个注册的蓝牙广播接收器,它处理 ACTION_ACL_CONNECTED 和 ACTION_ACL_DISCONNECTED。在服务中,在运行循环中,我获取配对设备的列表并尝试连接到每个设备。当连接成功时,我会收到 ACTION_ACL_CONNECTED 通知,当设备断开连接(或超出范围)时,我会收到 ACTION_ACL_DISCONNECTED。一切正常。
对于耳机,BluetoothHeadset 类会引发 ACTION_ACL_CONNECTED 和 ACTION_ACL_DISCONNECTED,因此我不需要连接到主 UUID 为 00001108 的设备。
我有一个蓝牙扬声器,它的单个 UUID 为 0000110B。它可以整天进出范围,每次我连接到它时我都会收到 ACTION_ACL_CONNECTED 和 ACTION_ACL_DISCONNECTED 信号,并且每次断开连接时都会因为它超出范围而发生。
如果我尝试使用 00001105 连接到另一部手机,则第一次连接成功并引发 ACTION_ACL_CONNECTED。如果我把手机带出范围(或者只是关闭它的蓝牙),我会得到 ACTION_ACL_DISCONNECTED。但是,任何进一步的连接尝试都会导致“服务发现失败”,即使手机在范围内并且蓝牙已打开。这种情况一直持续到我手动或代码切换手机上的蓝牙适配器。然后我可以进行一次连接/断开连接,然后服务发现失败再次发生。显然,切换适配器并不是一个令人满意的解决方案。所以,我的问题是,是什么让 00001105 与 00001108 不同,因为我不能使用 00001105 进行多次连接/断开连接?
代码比较复杂,但在这里(请原谅缩进。剪切和粘贴效果不太好):
public class BluetoothListenerService extends Service {
// The BroadcastReceiver that listens for Connected and disconnected blue tooth devices (HSP,HFP and SPP)
public final BroadcastReceiver mBluetoothReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String devices[]=null;
Intent service_intent;
String action = intent.getAction();
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
// Get the BluetoothDevice object from the Intent
String testUUID=null;
try {
Method method = device.getClass().getMethod("getUuids", (Class<?>[]) null);
ParcelUuid[] phoneUuids = (ParcelUuid[]) method.invoke(device, (Object[]) null);
UUID myUUID=phoneUuids[0].getUuid();
testUUID=myUUID.toString().toLowerCase();
Log.i(TAG,"connected to "+device.getName()+ "using "+ testUUID);
} catch (Exception e) {}
return;
} // end ACTION_ACL_CONNECTED
if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
Log.i(TAG, "disconnected from "+device.getName());
return;
} // end ACTION_ACL_DISCONNECTED
} // end OnReceive
}; // end broadcast receiver definition
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
@Override
public void onStart(final Intent intent, final int startId) {
super.onStart(intent, startId);
if (mBluetoothAdapter == null) {
Toast.makeText(this," Bluetooth is not available on this device", Toast.LENGTH_LONG).show();
return;
}
Thread t = new Thread("MyService(" + startId + ")") {
@Override
public void run() {
_onStart(intent, startId);
stopSelf();
}
};
t.start();
return;
}
public void _onStart(Intent intent, int startId) {
String devices[]=null;
Log.i(TAG,"Bluetooth Listener Service started on thread "+ Integer.toString(android.os.Process.myTid()));
// Register the Bluetooth BroadcastReceiver
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
try {
this.unregisterReceiver(mBluetoothReceiver);
} catch(IllegalArgumentException ignorable) {}
registerReceiver(mBluetoothReceiver, filter);
// the loop
bRun=true;
while(bRun) {
Set <BluetoothDevice> mySet=mBluetoothAdapter.getBondedDevices();
Iterator <BluetoothDevice> iterator=mySet.iterator();
while(iterator.hasNext()) {
BluetoothDevice setElement=iterator.next();
String testUUID=null;
try { // Get UUID for device
Method method = setElement.getClass().getMethod("getUuids", (Class<?>[]) null);
ParcelUuid[] phoneUuids = (ParcelUuid[]) method.invoke(setElement, (Object[]) null);
UUID myUUID=phoneUuids[0].getUuid();
testUUID=myUUID.toString().toUpperCase();
Log.i(TAG, "device UUID is "+testUUID);
if (testUUID.compareTo(headsetUUID)!=0 && testUUID.compareTo(a2dpUUID)!=0) {
try { // create a socket
BluetoothSocket tmp=null;
tmp=setElement.createInsecureRfcommSocketToServiceRecord(UUID.fromString(testUUID));
mmSocket=tmp;
Log.i(TAG,"connecting using socket "+mmSocket.toString());
Log.i(TAG,"connecting to "+setElement.getName());
try {
if (mBluetoothAdapter.isDiscovering()==true) mBluetoothAdapter.cancelDiscovery();
mmSocket.connect();
Log.i(TAG,"connection to "+setElement.getName()+" was sucessful");
// the connection will be handled by the receiver in ACL_CONNECTED
} catch (Exception e) { // connection failed
String sTest=e.getMessage();
Log.e(TAG,"connection to "+setElement.getName()+" returned "+sTest);
if (sTest!=null) {
try { // closing the socket
Log.i(TAG,"closing socket due to error: "+sTest);
Log.i(TAG,"closing socket "+mmSocket.toString());
if (!mmSocket.equals(null)) {
mmSocket.close();
mmSocket=null;
tmp=null;
}
else {
Log.e(TAG, "socket is null");
}
} catch (Exception e1) { // socket close failed
Log.e(TAG,"closing socket failed");
break;
}
if (sTest.compareTo("Unable to start Service Discovery")==0) {
mBluetoothAdapter.disable();
SystemClock.sleep(3000);
mBluetoothAdapter.enable();
SystemClock.sleep(1000);
}
}
} // end catch connection failed
} catch (Exception e1) {
Log.e(TAG, "socket create failed.");
}
} // end test if headset or not
} catch (Exception e1) {
Log.e(TAG, "find UUID failed.");
} // end find UUID
} // end while iterator.hasnext()
} // end of run loop
}
}