Android BLE - 连接到多个设备似乎失败并且两个连接的 GATT 响应相同?
Posted
技术标签:
【中文标题】Android BLE - 连接到多个设备似乎失败并且两个连接的 GATT 响应相同?【英文标题】:Android BLE - Connecting to multiple devices seem to fail and GATT Response is the same for both connections? 【发布时间】:2016-02-15 09:53:34 【问题描述】:我正在开发一个连接到 BLE 设备并读取我需要检查的特定 GATT 特征和服务的 android 应用程序。我使用了来自 Android Dev 站点的 BluetoothLeGATT 示例作为参考。我可以毫无问题地连接到预定义地址并读取 GATT 属性更新。
我接下来要做的是能够同时连接到两个 BLE 设备。然而,这似乎是一个挑战。
我所做的基本上是复制连接到单个 BLE 设备所需的代码。我有 2 个 BluetoothLeServices、2 个用于 GattCharacteristics 和 Gatt 服务数据的 ArrayList,以及 2 个服务连接和 2 个用于 GattCallbacks 的广播接收器。
但是,在我的 GattCallback 函数中,我收到了相同的消息——就好像它们连接到同一个区域一样。这是我的代码:
public class MainActivity extends AppCompatActivity
/*
UUIDs
Dog Block - 20:CD:39:87:DC:AA
Cat Block - 20:CD:39:87:DF:82
*/
private final String TAG = this.getClass().getSimpleName();
private BluetoothAdapter mBluetoothAdapter;
private Handler mHandler;
private static final int REQUEST_ENABLE_BT = 1;
private static final long SCAN_PERIOD = 10000;
private ArrayList<String> addressID = new ArrayList<>();
private ArrayList<BluetoothDevice> deviceList = new ArrayList<>();
private boolean mScanning = false;
private boolean mConnected = false;
private BluetoothLeService mBluetoothLeService;
private BluetoothLeService mBluetoothLeService1;
private ArrayList<ArrayList<BluetoothGattCharacteristic>> mGattCharacteristics =
new ArrayList<ArrayList<BluetoothGattCharacteristic>>();
private ArrayList<ArrayList<BluetoothGattCharacteristic>> mGattCharacteristics1 =
new ArrayList<ArrayList<BluetoothGattCharacteristic>>();
private final String LIST_NAME = "NAME";
private final String LIST_UUID = "UUID";
ArrayList<HashMap<String, String>> gattServiceData = new ArrayList<HashMap<String, String>>();
ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData
= new ArrayList<ArrayList<HashMap<String, String>>>();
ArrayList<HashMap<String, String>> gattServiceData1 = new ArrayList<HashMap<String, String>>();
ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData1
= new ArrayList<ArrayList<HashMap<String, String>>>();
private BluetoothGattCharacteristic mNotifyCharacteristic;
private BluetoothGattCharacteristic mNotifyCharacteristic1;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHandler = new Handler();
// Use this check to determine whether BLE is supported on the device. Then you can
// selectively disable BLE-related features.
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE))
Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
finish();
// Initializes a Bluetooth adapter. For API level 18 and above, get a reference to
// BluetoothAdapter through BluetoothManager.
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
// Checks if Bluetooth is supported on the device.
if (mBluetoothAdapter == null)
Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show();
finish();
return;
addressID.add("20:CD:39:87:DC:AA");
addressID.add("20:CD:39:87:DF:82");
@Override
protected void onResume()
super.onResume();
Log.e(TAG, "onResume");
// Ensures Bluetooth is enabled on the device. If Bluetooth is not currently enabled,
// fire an intent to display a dialog asking the user to grant permission to enable it.
if (!mBluetoothAdapter.isEnabled())
if (!mBluetoothAdapter.isEnabled())
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
scanLeDevice(true);
if (mBluetoothLeService != null)
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
// User chose not to enable Bluetooth.
if (requestCode == REQUEST_ENABLE_BT && resultCode == Activity.RESULT_CANCELED)
finish();
return;
super.onActivityResult(requestCode, resultCode, data);
@Override
protected void onPause()
super.onPause();
scanLeDevice(false);
unregisterReceiver(mGattUpdateReceiver);
unregisterReceiver(mGattUpdateReceiver1);
@Override
protected void onDestroy()
super.onDestroy();
unbindService(mServiceConnection);
mBluetoothLeService = null;
mBluetoothLeService1 = null;
private void scanLeDevice(final boolean enable)
if (enable)
Log.e(TAG, "scanLeDevice true");
// Stops scanning after a pre-defined scan period.
mHandler.postDelayed(new Runnable()
@Override
public void run()
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
invalidateOptionsMenu();
, SCAN_PERIOD);
mScanning = true;
mBluetoothAdapter.startLeScan(mLeScanCallback);
else
Log.e(TAG, "scanLeDevice false");
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
invalidateOptionsMenu();
// Device scan callback.
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback()
@Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord)
runOnUiThread(new Runnable()
@Override
public void run()
deviceList.add(device);
Log.e(TAG, "deviceList count = " + deviceList.size());
if(deviceList.size() >= 2)
checkDevices();
);
;
private void checkDevices()
Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
Intent gattServiceIntent1 = new Intent(this, BluetoothLeService.class);
bindService(gattServiceIntent1, mServiceConnection1, BIND_AUTO_CREATE);
registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
registerReceiver(mGattUpdateReceiver1, makeGattUpdateIntentFilter());
//TODO -- connect functions here
private static IntentFilter makeGattUpdateIntentFilter()
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
return intentFilter;
// Code to manage Service lifecycle.
private final ServiceConnection mServiceConnection = new ServiceConnection()
@Override
public void onServiceConnected(ComponentName componentName, IBinder service)
mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
if (!mBluetoothLeService.initialize())
Log.e(TAG, "Unable to initialize Bluetooth");
finish();
Log.e(TAG, "connecting to " + deviceList.get(0).getAddress());
mBluetoothLeService.connect("20:CD:39:87:DC:AA");
@Override
public void onServiceDisconnected(ComponentName componentName)
mBluetoothLeService = null;
;
private final ServiceConnection mServiceConnection1 = new ServiceConnection()
@Override
public void onServiceConnected(ComponentName componentName, IBinder service)
mBluetoothLeService1 = ((BluetoothLeService.LocalBinder) service).getService();
if (!mBluetoothLeService1.initialize())
Log.e(TAG, "1Unable to initialize Bluetooth");
finish();
// Automatically connects to the device upon successful start-up initialization.
Log.e(TAG, "1connecting to " + deviceList.get(1).getAddress());
mBluetoothLeService1.connect("20:CD:39:87:DF:82");
@Override
public void onServiceDisconnected(ComponentName componentName)
mBluetoothLeService = null;
;
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver()
@Override
public void onReceive(Context context, Intent intent)
final String action = intent.getAction();
if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action))
Log.e(TAG, "connected");
else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action))
Log.e(TAG, "disconnected");
mConnected = false;
else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action))
// Show all the supported services and characteristics on the user interface.
Log.e(TAG, "gatt services discovered");
displayGattServices(mBluetoothLeService.getSupportedGattServices());
else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action))
Log.e(TAG, "data available");
String data = intent.getStringExtra(BluetoothLeService.EXTRA_DATA);
Log.e(TAG, "data is = " + data);
;
private final BroadcastReceiver mGattUpdateReceiver1 = new BroadcastReceiver()
@Override
public void onReceive(Context context, Intent intent)
final String action = intent.getAction();
if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action))
Log.e(TAG, "1connected");
else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action))
Log.e(TAG, "1disconnected");
mConnected = false;
else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action))
// Show all the supported services and characteristics on the user interface.
Log.e(TAG, "1gatt services discovered");
displayGattServices1(mBluetoothLeService1.getSupportedGattServices());
else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action))
Log.e(TAG, "1data available");
String data = intent.getStringExtra(BluetoothLeService.EXTRA_DATA);
Log.e(TAG, "1data is = " + data);
;
private void displayGattServices(List<BluetoothGattService> gattServices)
if (gattServices == null) return;
Log.e(TAG, "display gatt services not null.");
String uuid = null;
String unknownServiceString = getResources().getString(R.string.unknown_service);
String unknownCharaString = getResources().getString(R.string.unknown_characteristic);
mGattCharacteristics = new ArrayList<ArrayList<BluetoothGattCharacteristic>>();
// Loops through available GATT Services.
for (BluetoothGattService gattService : gattServices)
HashMap<String, String> currentServiceData = new HashMap<String, String>();
uuid = gattService.getUuid().toString();
currentServiceData.put(
LIST_NAME, SampleGattAttributes.lookup(uuid, unknownServiceString));
currentServiceData.put(LIST_UUID, uuid);
gattServiceData.add(currentServiceData);
ArrayList<HashMap<String, String>> gattCharacteristicGroupData =
new ArrayList<HashMap<String, String>>();
List<BluetoothGattCharacteristic> gattCharacteristics =
gattService.getCharacteristics();
ArrayList<BluetoothGattCharacteristic> charas =
new ArrayList<BluetoothGattCharacteristic>();
// Loops through available Characteristics.
for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics)
charas.add(gattCharacteristic);
HashMap<String, String> currentCharaData = new HashMap<String, String>();
uuid = gattCharacteristic.getUuid().toString();
currentCharaData.put(
LIST_NAME, SampleGattAttributes.lookup(uuid, unknownCharaString));
currentCharaData.put(LIST_UUID, uuid);
gattCharacteristicGroupData.add(currentCharaData);
if(uuid.equals(SampleGattAttributes.DOG_CHARACTERISTIC_CONFIG))
Log.e(TAG, "uuid characteristic detected");
final int charaProp = gattCharacteristic.getProperties();
if ((charaProp | BluetoothGattCharacteristic.PROPERTY_READ) > 0)
Log.e(TAG, "gatt characteristics read!");
// If there is an active notification on a characteristic, clear
// it first so it doesn't update the data field on the user interface.
if (mNotifyCharacteristic != null)
mBluetoothLeService.setCharacteristicNotification(
mNotifyCharacteristic, false);
mNotifyCharacteristic = null;
mBluetoothLeService.readCharacteristic(gattCharacteristic);
if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0)
Log.e(TAG, "gatt characteristics notify!");
mNotifyCharacteristic = gattCharacteristic;
mBluetoothLeService.setCharacteristicNotification(
gattCharacteristic, true);
mGattCharacteristics.add(charas);
gattCharacteristicData.add(gattCharacteristicGroupData);
private void displayGattServices1(List<BluetoothGattService> gattServices)
if (gattServices == null) return;
Log.e(TAG, "1display gatt services not null.");
String uuid = null;
String unknownServiceString = getResources().getString(R.string.unknown_service);
String unknownCharaString = getResources().getString(R.string.unknown_characteristic);
mGattCharacteristics1 = new ArrayList<ArrayList<BluetoothGattCharacteristic>>();
// Loops through available GATT Services.
for (BluetoothGattService gattService : gattServices)
HashMap<String, String> currentServiceData = new HashMap<String, String>();
uuid = gattService.getUuid().toString();
currentServiceData.put(
LIST_NAME, SampleGattAttributes.lookup(uuid, unknownServiceString));
currentServiceData.put(LIST_UUID, uuid);
gattServiceData1.add(currentServiceData);
ArrayList<HashMap<String, String>> gattCharacteristicGroupData =
new ArrayList<HashMap<String, String>>();
List<BluetoothGattCharacteristic> gattCharacteristics =
gattService.getCharacteristics();
ArrayList<BluetoothGattCharacteristic> charas =
new ArrayList<BluetoothGattCharacteristic>();
// Loops through available Characteristics.
for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics)
charas.add(gattCharacteristic);
HashMap<String, String> currentCharaData = new HashMap<String, String>();
uuid = gattCharacteristic.getUuid().toString();
currentCharaData.put(
LIST_NAME, SampleGattAttributes.lookup(uuid, unknownCharaString));
currentCharaData.put(LIST_UUID, uuid);
gattCharacteristicGroupData.add(currentCharaData);
if (uuid.equals(SampleGattAttributes.DOG_CHARACTERISTIC_CONFIG))
Log.e(TAG, "1uuid characteristic detected");
final int charaProp = gattCharacteristic.getProperties();
if ((charaProp | BluetoothGattCharacteristic.PROPERTY_READ) > 0)
Log.e(TAG, "1gatt characteristics read!");
// If there is an active notification on a characteristic, clear
// it first so it doesn't update the data field on the user interface.
if (mNotifyCharacteristic1 != null)
mBluetoothLeService1.setCharacteristicNotification(
mNotifyCharacteristic1, false);
mNotifyCharacteristic1 = null;
mBluetoothLeService1.readCharacteristic(gattCharacteristic);
if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0)
Log.e(TAG, "1gatt characteristics notify!");
mNotifyCharacteristic1 = gattCharacteristic;
mBluetoothLeService1.setCharacteristicNotification(
gattCharacteristic, true);
mGattCharacteristics1.add(charas);
gattCharacteristicData1.add(gattCharacteristicGroupData);
我所做的是,一旦我获得了我想要连接的 2 个地址,我就会初始化所有必要的连接、服务和广播接收器。但是,我收到的 bluetoothLeGatt 消息是相同的。根据它连接到 Dog 或 Cat 块,我会得到以下线路:
data = dog
1data = dog
来自 LogCat。好像它们连接到同一个设备。
我检查了我的代码,甚至硬编码了地址,但无济于事。
【问题讨论】:
这有什么更新吗? 我也很感兴趣.. 在尝试这样做时,我遇到了这个:***.com/a/30455650/2349192. 【参考方案1】:我已经与多个设备建立了连接,并且工作正常。我还为扫描内容制作了一项服务,为每个 ble 通信制作了一项服务。确保不要将绑定服务用于通信部分,因为断开连接可能是一个问题。(在我的情况下)。 对于扫描的东西,我制作了一个包含 Mac 地址的字符串列表。当我在扫描仪中找到一个设备时,我通过广播接收器将设备发送到我的主要活动,然后我将其传输到它的服务。因此,每个连接都在它自己的服务中运行,具有自己的广播接收器和过滤器设置。为了确保这不是您的广播接收器的问题,请在您立即显示输出的每个服务中创建一个控制台日志。我无法想象您的设备必须连接到同一台服务器。
【讨论】:
以上是关于Android BLE - 连接到多个设备似乎失败并且两个连接的 GATT 响应相同?的主要内容,如果未能解决你的问题,请参考以下文章
为啥在 Android 中将 autoConnect 设置为 true 时,App 不会重新连接到 BLE 设备?
强制关闭连接到 Android 应用程序的 BLE 设备会触发状态为 8 的 onConnectionStateChange
Android 8.1 连接到调用 connectGatt 的 BLE 外围设备。回调总是说断开连接。从不连接