Android 快速连接和断开以读取1个特征。一些BLE设备在快速连接断开后停止广播

Android 快速连接和断开以读取1个特征。一些BLE设备在快速连接断开后停止广播,android,bluetooth,bluetooth-lowenergy,Android,Bluetooth,Bluetooth Lowenergy,我正在尝试编写一个android应用程序来扫描可编程设备,当它找到具有命名方案的特定设备时,它会连接到该设备并读取一个特征(设备的用户定义名称),然后立即断开连接。然后,它将在一个列表中显示该设备以及找到的任何其他设备,并读取用户定义的名称。然后,用户可以选择要连接的设备(或多个设备),然后连接到该设备并从中传输数据 不断发生的问题是,在它获得用户定义的名称并断开连接后,BLE设备停止广播,我在扫描时无法再找到它,或者在读取用户定义的名称并断开连接后尝试连接到它 这是Android BLE堆栈的

我正在尝试编写一个android应用程序来扫描可编程设备,当它找到具有命名方案的特定设备时,它会连接到该设备并读取一个特征(设备的用户定义名称),然后立即断开连接。然后,它将在一个列表中显示该设备以及找到的任何其他设备,并读取用户定义的名称。然后,用户可以选择要连接的设备(或多个设备),然后连接到该设备并从中传输数据

不断发生的问题是,在它获得用户定义的名称并断开连接后,BLE设备停止广播,我在扫描时无法再找到它,或者在读取用户定义的名称并断开连接后尝试连接到它

这是Android BLE堆栈的问题还是我需要添加更多延迟(我使用的整个蓝牙服务都有100毫秒的延迟)

这是我在服务中使用的部分代码

 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;
如果(!结果){
日志