Android 快速连接和断开以读取1个特征。一些BLE设备在快速连接断开后停止广播
我正在尝试编写一个android应用程序来扫描可编程设备,当它找到具有命名方案的特定设备时,它会连接到该设备并读取一个特征(设备的用户定义名称),然后立即断开连接。然后,它将在一个列表中显示该设备以及找到的任何其他设备,并读取用户定义的名称。然后,用户可以选择要连接的设备(或多个设备),然后连接到该设备并从中传输数据 不断发生的问题是,在它获得用户定义的名称并断开连接后,BLE设备停止广播,我在扫描时无法再找到它,或者在读取用户定义的名称并断开连接后尝试连接到它 这是Android BLE堆栈的问题还是我需要添加更多延迟(我使用的整个蓝牙服务都有100毫秒的延迟) 这是我在服务中使用的部分代码Android 快速连接和断开以读取1个特征。一些BLE设备在快速连接断开后停止广播,android,bluetooth,bluetooth-lowenergy,Android,Bluetooth,Bluetooth Lowenergy,我正在尝试编写一个android应用程序来扫描可编程设备,当它找到具有命名方案的特定设备时,它会连接到该设备并读取一个特征(设备的用户定义名称),然后立即断开连接。然后,它将在一个列表中显示该设备以及找到的任何其他设备,并读取用户定义的名称。然后,用户可以选择要连接的设备(或多个设备),然后连接到该设备并从中传输数据 不断发生的问题是,在它获得用户定义的名称并断开连接后,BLE设备停止广播,我在扫描时无法再找到它,或者在读取用户定义的名称并断开连接后尝试连接到它 这是Android BLE堆栈的
public boolean initialize() {
Log.i(TAG, "Initializing");
try {
synchronized (Thread.currentThread()) {
Thread.currentThread().wait(100);
}
}catch(InterruptedException e){
//ignore
}
if (mBluetoothManager == null) {
mBluetoothManager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
if (mBluetoothManager == null) {
Log.e(TAG, "Unable to initialize BluetoothManager.");
return false;
}
}
mBluetoothAdapter = mBluetoothManager.getAdapter();
if (mBluetoothAdapter == null) {
Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
return false;
}
mReadyToWrite = true;
mReadyToRead = true;
mReady = true;
mCharacteristicWriteQueue = new ArrayDeque<BluetoothGattCharacteristic>();
mCharacteristicReadQueue = new ArrayDeque<BluetoothGattCharacteristic>();
mDescriptorWriteQueue = new ArrayDeque<BluetoothGattDescriptor>();
mDescriptorReadQueue = new ArrayDeque<BluetoothGattDescriptor>();
//mBluetoothGattMap = new HashMap<String, BluetoothGatt>();
return true;
}
/**
* Connects to the GATT server hosted on the Bluetooth LE device.
*
* @param address The device address of the device.
*
* @return Return true if the connection is initiated successfully. The connection result
* is reported asynchronously through the
* {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
* callback.
*/
public boolean connect(final String address) {
if (mBluetoothAdapter == null || address == null) {
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
return false;
}
if(mBluetoothGattMap.containsKey(address)) {
Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
if (mBluetoothGattMap.get(address).connect()) {
mConnectionState = STATE_CONNECTING;
return true;
} else {
return false;
}
}
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
if (device == null) {
Log.w(TAG, "Device not found. Unable to connect.");
return false;
}
try {
synchronized (Thread.currentThread()) {
Thread.currentThread().wait(100);
}
}catch(InterruptedException e){
//ignore
}
mBluetoothGattMap.put(address, device.connectGatt(this, false, mGattCallback));
Log.d(TAG, "Trying to create a new connection to address " + address);
//mBluetoothDeviceAddress = address;
mConnectionState = STATE_CONNECTING;
return true;
}
/**
* Disconnects an existing connection or cancel a pending connection. The disconnection result
* is reported asynchronously through the
* {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
* callback.
*/
public void disconnect(String address) {
if (mBluetoothAdapter == null || !mBluetoothGattMap.containsKey(address)) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
Log.i(TAG, "Disconnecting from gatt");
try {
synchronized (Thread.currentThread()) {
Thread.currentThread().wait(100);
}
}catch(InterruptedException e){
//ignore
}
mBluetoothGattMap.get(address).disconnect();
}
public void close(String address) {
try {
synchronized (Thread.currentThread()) {
Thread.currentThread().wait(100);
}
}catch(InterruptedException e){
//ignore
}
mBluetoothGattMap.get(address).close();
mBluetoothGattMap.remove(address);
Log.w(TAG, "Succeeed removing it");
}
public int getConnectionState(String address) {
Log.i(TAG, "getting connection state for " + address);
BluetoothGatt gatt = mBluetoothGattMap.get(address);
return mBluetoothManager.getConnectionState(gatt.getDevice(), BluetoothProfile.GATT);
}
/**
* Request a read on a given {@code BluetoothGattCharacteristic}. The read result is reported
* asynchronously through the {@code BluetoothGattCallback#onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int)}
* callback.
*
* @param characteristic The characteristic to read from.
*/
public void readCharacteristic(String address, BluetoothGattCharacteristic characteristic) {
Log.i(TAG, "reading characteristic");
if (mBluetoothAdapter == null || !mBluetoothGattMap.containsKey(address)) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
try {
synchronized (Thread.currentThread()) {
Thread.currentThread().wait(100);
}
}catch(InterruptedException e){
//ignore
}
if(mReadyToRead && mReady) {
boolean result = mBluetoothGattMap.get(address).readCharacteristic(characteristic);
mReadyToRead = false;
mReady = false;
if(!result) {
Log.i(TAG, "read failed");
}
}else {
mCharacteristicReadQueue.push(characteristic);
}
}
public void writeCharacteristic(String address, BluetoothGattCharacteristic characteristic) {
Log.i(TAG, "writeCharacteristic - readyToWrite = " + mReadyToWrite + " queue size = " + mCharacteristicWriteQueue.size());
if (mBluetoothAdapter == null || !mBluetoothGattMap.containsKey(address)) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
try {
synchronized (Thread.currentThread()) {
Thread.currentThread().wait(100);
}
}catch(InterruptedException e){
//ignore
}
if(mReadyToWrite && mReady) {
boolean result = mBluetoothGattMap.get(address).writeCharacteristic(characteristic);
mReadyToWrite = false;
mReady = false;
if(!result) {
Log.i(TAG, "characteristic write failed");
}
}else {
mCharacteristicWriteQueue.push(characteristic);
}
}
public void readDescriptor(String address, BluetoothGattDescriptor descriptor) {
Log.i(TAG, "reading descriptor");
if (mBluetoothAdapter == null || !mBluetoothGattMap.containsKey(address)) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
try {
synchronized (Thread.currentThread()) {
Thread.currentThread().wait(100);
}
}catch(InterruptedException e){
//ignore
}
if(mReadyToRead && mReady) {
boolean result = mBluetoothGattMap.get(address).readDescriptor(descriptor);
mReadyToRead = false;
mReady = false;
if(!result) {
Log.i(TAG, "descriptor read failed");
}
}else {
mDescriptorReadQueue.push(descriptor);
}
}
public void writeDescriptor(String address, BluetoothGattDescriptor descriptor) {
Log.i(TAG, "writing descriptor for characteristic " + descriptor.getCharacteristic().getUuid().toString());
if (mBluetoothAdapter == null || !mBluetoothGattMap.containsKey(address)) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
try {
synchronized (Thread.currentThread()) {
Thread.currentThread().wait(100);
}
}catch(InterruptedException e){
//ignore
}
if(mReadyToWrite && mReady) {
boolean result = mBluetoothGattMap.get(address).writeDescriptor(descriptor);
mReadyToWrite = false;
mReady = false;
if(!result) {
Log.i(TAG, "descriptor write failed");
}
}else {
mDescriptorWriteQueue.push(descriptor);
}
}
public BluetoothGattCharacteristic getCharacteristic(String address, UUID uuid) {
if(!mBluetoothGattMap.containsKey(address)) {
Log.i(TAG, "Device address " + address + " not found");
return null;
}
try {
synchronized (Thread.currentThread()) {
Thread.currentThread().wait(100);
}
}catch(InterruptedException e){
//ignore
}
for(BluetoothGattService service : mBluetoothGattMap.get(address).getServices()) {
Log.i(TAG, "Service: " + service.getUuid().toString());
for (BluetoothGattCharacteristic characteristic : service.getCharacteristics()) {
Log.i(TAG, "Characteristic: " + characteristic.getUuid().toString());
if(characteristic.getUuid().equals(uuid)) {
return characteristic;
}
}
}
Log.i(TAG, "Characteristic not found");
return null;
}
public Set<String> getConnectedDevices(){
return this.mBluetoothGattMap.keySet();
}
/**
* Enables or disables notification on a give characteristic.
*
* @param characteristic Characteristic to act on.
* @param enabled If true, enable notification. False otherwise.
*/
public void setCharacteristicNotification(String address, BluetoothGattCharacteristic characteristic, boolean enabled) {
if (mBluetoothAdapter == null || !mBluetoothGattMap.containsKey(address)) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
try {
synchronized (Thread.currentThread()) {
Thread.currentThread().wait(100);
}
}catch(InterruptedException e){
//ignore
}
mBluetoothGattMap.get(address).setCharacteristicNotification(characteristic, enabled);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString(GattAttributes.CLIENT_CHAR_CONFIG));
if(descriptor != null) {
boolean status = descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
Log.i(TAG, "descriptor " + descriptor.getUuid().toString() + " setValue() status: " + status);
Log.i(TAG, "descriptor value: " + descriptor.getValue());
writeDescriptor(address, descriptor);
}
}
public void setPhoneEvents(byte priorities) {
for(String address : mBluetoothGattMap.keySet()) {
BluetoothGattCharacteristic characteristic = getCharacteristic(address, UUID.fromString(GattAttributes.ALERT_ATTRIBUTE));
if (characteristic != null) {
byte prioritiesBuf[] = new byte[1];
prioritiesBuf[0] = priorities;
characteristic.setValue(prioritiesBuf);
writeCharacteristic(address, characteristic);
Log.i(TAG, String.format("Forwarded phone alert priorities: 0x%X", priorities));
} else {
Log.e(TAG, "Failed to get the Alert ID characteristic from Gatt Server for device address " + address);
}
}
}
/**
* Retrieves a list of supported GATT services on the connected device. This should be
* invoked only after {@code BluetoothGatt#discoverServices()} completes successfully.
*
* @return A {@code List} of supported services.
*/
public List<BluetoothGattService> getSupportedGattServices(String address) {
if (mBluetoothGattMap.get(address) == null) return null;
return mBluetoothGattMap.get(address).getServices();
}
public boolean initialize(){
Log.i(标记“初始化”);
试一试{
已同步(Thread.currentThread()){
Thread.currentThread().wait(100);
}
}捕捉(中断异常e){
//忽略
}
if(mBluetoothManager==null){
mBluetoothManager=(BluetoothManager)getSystemService(蓝牙_服务);
if(mBluetoothManager==null){
Log.e(标记“无法初始化BluetoothManager”);
返回false;
}
}
mBluetoothAdapter=mBluetoothManager.getAdapter();
if(mBluetoothAdapter==null){
Log.e(标记“无法获取蓝牙适配器”);
返回false;
}
mReadyToWrite=true;
mReadyToRead=true;
mReady=true;
mCharacteristicWriteQueue=new ArrayDeque();
mCharacteristicReadQueue=新的ArrayQueue();
mDescriptorWriteQueue=new ArrayDeque();
mDescriptorReadQueue=new ArrayDeque();
//mBluetoothGattMap=newhashmap();
返回true;
}
/**
*连接到蓝牙LE设备上托管的GATT服务器。
*
*@param address设备的设备地址。
*
*@return如果连接成功启动,则返回true。连接结果
*通过
*{@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt,int,int)}
*回拨。
*/
公共布尔连接(最终字符串地址){
if(mBluetoothAdapter==null | | address==null){
w(标记“BluetoothAdapter未初始化或未指定地址”);
返回false;
}
if(MBlueTothGattMap.containsKey(地址)){
Log.d(标签,“尝试使用现有MBlueTothGatt进行连接”);
if(mBluetoothGattMap.get(address.connect()){
mConnectionState=连接状态;
返回true;
}否则{
返回false;
}
}
最终BluetoothDevice=mBluetoothAdapter.getRemoteDevice(地址);
如果(设备==null){
Log.w(标记“未找到设备。无法连接”);
返回false;
}
试一试{
已同步(Thread.currentThread()){
Thread.currentThread().wait(100);
}
}捕捉(中断异常e){
//忽略
}
mbluetothgattmap.put(地址、设备、连接gatt(this、false、mGattCallback));
Log.d(标记“尝试创建到地址的新连接”+地址);
//mBluetoothDeviceAddress=地址;
mConnectionState=连接状态;
返回true;
}
/**
*断开现有连接或取消挂起的连接。断开连接的结果
*通过
*{@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt,int,int)}
*回拨。
*/
公共无效断开连接(字符串地址){
if(mBluetoothAdapter==null | |!mBluetoothGattMap.containsKey(地址)){
w(标记“BluetoothAdapter未初始化”);
返回;
}
Log.i(标签“与关贸总协定断开”);
试一试{
已同步(Thread.currentThread()){
Thread.currentThread().wait(100);
}
}捕捉(中断异常e){
//忽略
}
mBluetoothGattMap.get(address.disconnect();
}
公共无效关闭(字符串地址){
试一试{
已同步(Thread.currentThread()){
Thread.currentThread().wait(100);
}
}捕捉(中断异常e){
//忽略
}
mBluetoothGattMap.get(address.close();
MBlueTothGattMap.remove(地址);
Log.w(标记“成功移除”);
}
public int getConnectionState(字符串地址){
Log.i(标签,“获取“+地址”的连接状态);
蓝牙gatt gatt=mbluetothgattmap.get(地址);
返回mBluetoothManager.getConnectionState(gatt.getDevice(),BluetoothProfile.gatt);
}
/**
*请求读取给定的{@code BluetoothGattCharacteristic}。报告读取结果
*通过{@code BluetoothGattCallback#onCharacteristicRead(android.bluetooth.BluetoothGatt,android.bluetooth.BluetoothGattCharacteristic,int)异步执行}
*回拨。
*
*@param characteristic要从中读取的特征。
*/
public void readCharacteristic(字符串地址,BluetoothGattCharacteristic特征){
Log.i(标签“读取特性”);
if(mBluetoothAdapter==null | |!mBluetoothGattMap.containsKey(地址)){
w(标记“BluetoothAdapter未初始化”);
返回;
}
试一试{
已同步(Thread.currentThread()){
Thread.currentThread().wait(100);
}
}捕捉(中断异常e){
//忽略
}
如果(mReadyToRead&&mReady){
布尔结果=mBluetoothGattMap.get(地址).readCharacteristic(特征);
mReadyToRead=false;
mReady=false;
如果(!结果){
日志