2022-11-11 来源:华纳网 责任编辑:谷雨老师 人气:
核心提示:大家好,欢迎来到谷雨课堂 本节, 我们使用Android来实现蓝牙BLE数据的双向收发, 本节虽然使用Android,但协议和内容和上节其实大同小异, 本节与上节联合一起就实现了Android与ESP32通过蓝牙的双向数据通讯 以下是Android实现蓝牙通信的部分代码: public
大家好,欢迎来到谷雨课堂


本节,
我们使用Android来实现蓝牙BLE数据的双向收发,
本节虽然使用Android,但协议和内容和上节其实大同小异,
本节与上节联合一起就实现了Android与ESP32通过蓝牙的双向数据通讯
 
以下是Android实现蓝牙通信的部分代码:
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
public class YsBtle {class cYsBleItem{public int idx=0;public String mac="";public BluetoothDevice dev=null;    }
public static String TAG="ysbt";
public static YsBtle m_instance;    BluetoothAdapter bta;    BluetoothDevice dev;    Handler mHandler;    BluetoothLeScanner scanner;    Context ctx;private BluetoothGattService bluetoothGattService;private BluetoothGattCharacteristic writeCharacteristic;private BluetoothGattCharacteristic notifyCharacteristic;//private BluetoothGatt btDeviceGatt;
    List<cYsBleItem> lstDevices=new ArrayList<>();
//Server    BluetoothGattService mGattService;    BluetoothGattCharacteristic mCharacteristicRead;    BluetoothGattCharacteristic mCharacteristicWrite;    BluetoothGattServer mBluetoothGattServer;    BluetoothManager bluetoothManager;
static UUID UUID_SERVER=UUID.fromString("0000180d-0000-1000-8000-00805f9b34fb");static UUID UUID_CHARREAD=UUID.fromString("00002a37-0000-1000-8000-00805f9b34fb");static UUID UUID_CHARWRITE=UUID.fromString("00002a00-0000-1000-8000-00805f9b34fb");static UUID UUID_DESCRIPTOR=UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");private ConcurrentHashMap<String, BluetoothDevice> btClients = new ConcurrentHashMap<>();

private static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
public boolean isCurUUID(String uuid,String uuid_s){        String uuid_ss=uuid.substring(4,8).toUpperCase();return uuid_ss.equals(uuid_s.toUpperCase());    }
public static String bytesToHexFun1(byte[] bytes) {if(bytes==null)return "";// 一个byte为8位,可用两个十六进制位标识char[] buf = new char[bytes.length * 2];int a = 0;int index = 0;for(byte b : bytes) { // 使用除与取余进行转换if(b < 0) {                a = 256 + b;            } else {                a = b;            }
            buf[index++] = HEX_CHAR[a / 16];            buf[index++] = HEX_CHAR[a % 16];        }
return new String(buf);    }
public String getPropInfo(int prop){        String ret="";if((prop & BluetoothGattCharacteristic.PROPERTY_BROADCAST)==BluetoothGattCharacteristic.PROPERTY_BROADCAST)ret+=" BROADCAST";if((prop & BluetoothGattCharacteristic.PROPERTY_EXTENDED_PROPS)==BluetoothGattCharacteristic.PROPERTY_EXTENDED_PROPS)ret+=" EXTENDED";if((prop & BluetoothGattCharacteristic.PROPERTY_INDICATE)==BluetoothGattCharacteristic.PROPERTY_INDICATE)ret+=" INDICATE";if((prop & BluetoothGattCharacteristic.PROPERTY_READ)==BluetoothGattCharacteristic.PROPERTY_READ)ret+=" READ";if((prop & BluetoothGattCharacteristic.PROPERTY_NOTIFY)==BluetoothGattCharacteristic.PROPERTY_NOTIFY)ret+=" NOTIFY";if((prop & BluetoothGattCharacteristic.PROPERTY_SIGNED_WRITE)==BluetoothGattCharacteristic.PROPERTY_SIGNED_WRITE)ret+=" SIGNED_WRITE";if((prop & BluetoothGattCharacteristic.PROPERTY_WRITE)==BluetoothGattCharacteristic.PROPERTY_WRITE)ret+=" WRITE";if((prop & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE)==BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE)ret+=" WRITE_NO_RESPONSE";return ret;    }
public String getUuidInfo(String typ,String uuid){        String ret="";        String uuid_s=uuid.substring(4,8).toUpperCase();        ret=uuid_s+" "+YsBleStd.getInfo(uuid_s);return ret;    }
public static String bytesToHexFun2(byte[] bytes) {char[] buf = new char[bytes.length * 2];int index = 0;for(byte b : bytes) { // 利用位运算进行转换,可以看作方法一的变种            buf[index++] = HEX_CHAR[b >>> 4 & 0xf];            buf[index++] = HEX_CHAR[b & 0xf];        }
return new String(buf);    }
public static String bytesToHexFun3(byte[] bytes) {        StringBuilder buf = new StringBuilder(bytes.length * 2);for(byte b : bytes) { // 使用String的format方法进行转换            buf.append(String.format("%02x", new Integer(b & 0xff)));        }
return buf.toString();    }
public static byte[] StringtoBytes(String str) {if (str == null || str.trim().equals("")) {return new byte[0];        }
byte[] bytes = new byte[str.length() / 2];for (int i = 0; i < str.length() / 2; i++) {            String subStr = str.substring(i * 2, i * 2 + 2);            bytes[i] = (byte) Integer.parseInt(subStr, 16);        }
return bytes;    }
public YsBtle(Context ctx_){        ctx=ctx_;        bluetoothManager= (BluetoothManager)ctx.getSystemService(BLUETOOTH_SERVICE);        bta=bluetoothManager.getAdapter();   //获取蓝牙适配器        mHandler=new Handler();    }
public void l(String s){        Log.e(TAG,s);    }
public static YsBtle getDefault(Context c) {if(m_instance==null){            m_instance=new YsBtle(c);        }return m_instance;    }
public boolean isOK(){if(bta==null){return false;        }if(!bta.isEnabled()){return false;        }return true;    }
public void start_connect(){if(bta.isDiscovering())        {            l("正在扫描呢");return;        }//btDeviceGatt.connect();    }
public void start_scan(){if(bta.isDiscovering())        {            l("正在扫描呢");return;        }
        scanner=bta.getBluetoothLeScanner();  //获取BluetoothLeScanner对象        scanner.startScan(callback);   //开始扫描,扫描的结果在callback里面处理
        mHandler.postDelayed(new Runnable() {  //20秒后停止扫描,在callback里获取扫描结果@Overridepublic void run() {                scanner.stopScan(callback);            }        },20000);        l("开始扫描...");    }
public void start_server(){//BluetoothServerSocket serverSocket = bta.listenUsingRfcommWithServiceRecord(NAME_INSECURE, MY_UUID);//BluetoothSocket socket = serverSocket.accept();    }
public void start_bt_server(){if(!bta.isEnabled()){return;        }        bta.setName("云杉数据");//获取广播对象        BluetoothLeAdvertiser mBluetoothLeAdvertiser = bta.getBluetoothLeAdvertiser();if(mBluetoothLeAdvertiser == null){            l("设备不支持广播");            Toast.makeText(ctx,"设备不支持蓝牙广播",Toast.LENGTH_SHORT).show();return;        }
//准备广播的参数,最后这个setTimeout是设置广播 发送的时间间隔吧,0应该是默认值,//如果填的太高,可能会导致别人扫描的时候不一定能扫描得到你        AdvertiseSettings.Builder settingsBuilder=new AdvertiseSettings.Builder();        settingsBuilder.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY)                .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH)                .setConnectable(true)                .setTimeout(0);
        AdvertiseSettings advertiseSettings = settingsBuilder.build();
//初始化广播数据        AdvertiseData.Builder dataBuilder = new AdvertiseData.Builder();        dataBuilder.setIncludeDeviceName(true)                .addServiceUuid(new ParcelUuid(UUID_SERVER))                .setIncludeTxPowerLevel(true);        AdvertiseData advertiseData = dataBuilder.build();
//初始化广播的应答数据(当别人扫描时,我们返回这个数据)        AdvertiseData scanResponse = new AdvertiseData.Builder()//.addManufacturerData(MANUFACTURE_ID_RESPONSE, SPECIFIC_DATA_RESPONSE) //可以加上设备的制造商信息                .addServiceUuid(new ParcelUuid(UUID_SERVER))                .build();//开始广播, mAdertiseCallback是开启广播时的回调,我们在下面定义它        mBluetoothLeAdvertiser.startAdvertising(advertiseSettings, advertiseData, scanResponse, mAdertiseCallback);    }
//广播成功或失败时的回调处理private  AdvertiseCallback mAdertiseCallback = new AdvertiseCallback() {@Overridepublic void onStartFailure(int errorCode){super.onStartFailure(errorCode);            l("广播失败:"+errorCode);        }@Overridepublic void onStartSuccess(AdvertiseSettings settingsInEffect){super.onStartSuccess(settingsInEffect);            l("服务端的广播成功开启");//广播开启成功后,我们初始化并蓝牙服务(实现见下面)            initBleServer();        }    };
//添加一个蓝牙服务,该服务下两个特征,一个读特征、一个写特征。private void initBleServer(){//创建蓝牙服务对象        mGattService = new BluetoothGattService(UUID_SERVER, BluetoothGattService.SERVICE_TYPE_PRIMARY);
//创建读特征值,主要用于客户端获取蓝牙的基本信息        mCharacteristicRead = new BluetoothGattCharacteristic(UUID_CHARREAD, BluetoothGattCharacteristic.PROPERTY_READ, BluetoothGattCharacteristic.PERMISSION_READ);        BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor(UUID_DESCRIPTOR,BluetoothGattCharacteristic.PERMISSION_READ);        mCharacteristicRead.addDescriptor(descriptor);//给特征值添加描述符,我理解相当于告诉客户端这个特征值能干嘛,在这个例子里这个特征值就纯用于发送蓝牙的信息到客户端        mGattService.addCharacteristic(mCharacteristicRead);
//创建写特征值,这个特征值有读属性(READ),有写属性(WRITE,发送数据),还可以用于通知客户端接收数据(NOTIFY)        mCharacteristicWrite = new BluetoothGattCharacteristic(UUID_CHARWRITE,                BluetoothGattCharacteristic.PROPERTY_WRITE                        | BluetoothGattCharacteristic.PROPERTY_READ                        | BluetoothGattCharacteristic.PROPERTY_NOTIFY,                BluetoothGattCharacteristic.PERMISSION_WRITE                        |BluetoothGattCharacteristic.PERMISSION_READ                        | BluetoothGattCharacteristic.PROPERTY_NOTIFY);        l( "写UUID:"+UUID_CHARWRITE);//设置描述符的值,此处要注意:如果要用通知方式向客户端发数据,需要加上此两行        descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);        mCharacteristicWrite.addDescriptor(descriptor);
//将写特征值加入到服务        mGattService.addCharacteristic(mCharacteristicWrite);
//启动蓝牙服务,完成这个步骤后,我们就可以收发数据了//注意:此处需要传入gattServerCallback回调,它的实现在下面        BluetoothManager bluetoothManager= (BluetoothManager)ctx.getSystemService(BLUETOOTH_SERVICE);        mBluetoothGattServer = bluetoothManager.openGattServer(ctx, gattServerCallback);        mBluetoothGattServer.addService(mGattService);        l("初始化服务成功:initServices ok");    }
//服务事件的回调private BluetoothGattServerCallback gattServerCallback = new BluetoothGattServerCallback() {//1、首先是连接状态的回调@Overridepublic void onConnectionStateChange(BluetoothDevice device, int status, int newState) {super.onConnectionStateChange(device, status, newState);            l("连接状态发生改变,安卓系统回调onConnectionStateChange:device name="+device.getName()+"address="+device.getAddress()+"status="+status+"newstate="+newState);
if(newState == BluetoothProfile.STATE_CONNECTED) {                l("Add device to clients:"+device.getName()+","+device.getAddress());                btClients.put(device.getAddress(), device);try {                    l("try to create bt socket");                    BluetoothSocket soc = device.createInsecureRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));                    soc.connect();                    InputStream is= soc.getInputStream();                    l("bt is ok");                }catch (Exception e){                    l("create bt socket error "+e.getMessage());                }
            } else if(newState == BluetoothProfile.STATE_DISCONNECTED) {                l("Remove device from clents:"+device.getName()+","+device.getAddress());                btClients.remove(device.getAddress());            }        }
//处理客户端主动发起的读的操作,通过sendResponse发送数据过去,这个数据可以被多次请求重复发送@Overridepublic void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {super.onCharacteristicReadRequest(device, requestId, offset, characteristic);            l("客户端有读的请求,安卓系统回调该onCharacteristicReadRequest()方法");            l("requestId="+requestId+",offset="+offset+","+characteristic.getUuid().toString()+",value:"+bytesToHexFun1(characteristic.getValue()));            mBluetoothGattServer.sendResponse(device,requestId, BluetoothGatt.GATT_SUCCESS,0,new byte[]{'A','B','C'});        }
//接收客户端发过来的数据,当有特征被写入时,回调该方法,写入的数据为参数中的value@Overridepublic void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {super.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value);            l("客户端有写的请求,安卓系统回调该onCharacteristicWriteRequest()方法");//特征被读取,回复客户端接收数据成功,注意:此处作用为通知客户端已收到该数据,否则客户端可能会认为数据传输失败而断开蓝牙            mBluetoothGattServer.sendResponse(device,requestId,BluetoothGatt.GATT_SUCCESS,offset,value);//客户端发送过来的数据,此处是给客户端又发送了回去            l("收到"+value.length+"字节 "+bytesToHexFun1(value));           //响应客户端

        }
//特征被读取。当回复相应成功后,客户端胡读取然后触发本方法@Overridepublic void onDescriptorReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattDescriptor descriptor) {super.onDescriptorReadRequest(device, requestId, offset, descriptor);            l("onDescriptorReadRequest调用了"+requestId);            mBluetoothGattServer.sendResponse(device,requestId,BluetoothGatt.GATT_SUCCESS,offset,null);
        }
//当有描述请求被写入时,回调该方法,@Overridepublic void onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {super.onDescriptorWriteRequest(device, requestId, descriptor, preparedWrite, responseNeeded, offset, value);
            mBluetoothGattServer.sendResponse(device,requestId,BluetoothGatt.GATT_SUCCESS,offset,value);            l("有数据写入");// onResponseToClient(value,device,requestId,descriptor.getCharacteristic());        }
//蓝牙服务添加成功时的回调@Overridepublic void onServiceAdded(int status, BluetoothGattService service){super.onServiceAdded(status,service);            l("添加服务成功,安卓系统回调该onServiceAdded()方法");        }
//MTU改变时的回调,MTU为每个蓝牙数据包最大的字节数,通常默认是20,//如果你有一个数据超过20字节,那需要分成很多个小于或等于20字节的包来发送@Overridepublic void onMtuChanged(BluetoothDevice device, int mtu) {super.onMtuChanged(device, mtu);            l( "MTU改变:"+mtu);        }
//当数据向客户端发送成功时,会调用 此回调@Overridepublic void onNotificationSent(BluetoothDevice device, int status) {super.onNotificationSent(device, status);            l("Notification Sent:"+ status);        }
//没试,不知道作用@Overridepublic void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) {super.onExecuteWrite(device, requestId, execute);            l( "执行写");        }    };
public void start_bt(){if(!bta.isEnabled()){return;        }        start_scan();//start_bt_server();    }
    AdvertiseSettings settings = new AdvertiseSettings.Builder().setConnectable(true).build();
    AdvertiseData advertiseData = new AdvertiseData.Builder()            .setIncludeDeviceName(true)            .setIncludeTxPowerLevel(true)            .build();
    AdvertiseData scanResponseData = new AdvertiseData.Builder()//.addServiceUuid(new ParcelUuid(UUID_SERVER))            .setIncludeTxPowerLevel(true)            .build();
    AdvertiseCallback adcallback1 = new AdvertiseCallback() {
@Overridepublic void onStartSuccess(AdvertiseSettings settingsInEffect) {            l("AdvertiseCallback onStartSuccess");        }
@Overridepublic void onStartFailure(int errorCode) {
            l("Failed to add BLE advertisement, reason: " + errorCode);
        }
    };
    ScanCallback callback=new ScanCallback() {   //扫描回调@RequiresApi(api = Build.VERSION_CODES.M)@Overridepublic void onScanResult(int callbackType, ScanResult result) {   //找到设备super.onScanResult(callbackType,result);//在这里面对你扫描到的蓝牙设备进行操作
            ScanRecord scanRecord = result.getScanRecord();  //获取扫描记录            BluetoothDevice dev=result.getDevice();            String dev_name=dev.getName();            String dev_address=dev.getAddress();int rssi=result.getRssi();int txpower=result.getTxPower();

//l("bt device found name="+dev_name+",address="+dev_address+" ,rssi="+rssi+" ,txpower="+txpower);if(scanRecord!=null){//l(scanRecord.toString());                SparseArray<byte[]> xx=scanRecord.getManufacturerSpecificData();if(xx!=null){
                }            }
               scanner.stopScan(callback);

            }        }@Overridepublic void onScanFailed(int errorCode) { //没有开启扫描super.onScanFailed(errorCode);        }    };
@RequiresApi(api = Build.VERSION_CODES.M)void add_to_list(BluetoothDevice dev){        String dev_address=dev.getAddress();        l("准备连接手环... "+dev_address);for (cYsBleItem d:lstDevices) {if(dev.getAddress().equals(d.mac)){                l("重复手环,跳过");return;            }        }int idx=lstDevices.size()+1;             l("连接第 "+(idx)+" 个");        dev.connectGatt(ctx,true,mBluetoothGattCallback,BluetoothDevice.TRANSPORT_LE);    }
//准备操作手环读写public void init_tba_oper(BluetoothGatt gatt){        String mac=gatt.getDevice().getAddress();
        BluetoothGattService serv= gatt.getService(UUID.fromString("0000180d-0000-1000-8000-00805f9b34fb"));if(serv==null){            l("获取BLE指定Service失败,返回Null");        }else{            BluetoothGattCharacteristic c=serv.getCharacteristic(UUID.fromString("00002a37-0000-1000-8000-00805f9b34fb"));if(c==null){                l("getCharacteristic is null ");            }else{                l("准备开启notify");
                c.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);                gatt.writeCharacteristic(c);
if(!gatt.setCharacteristicNotification(c,true)){                    l("fail to start notify");                }
                BluetoothGattDescriptor descriptor = c.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));                descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);int i=0;
if (!gatt.writeDescriptor(descriptor)){                    l(" !! error writeDescriptor");                }/*                new Timer().schedule(new TimerTask() {                    @Override                    public void run() {                        l("读!");                        if(!bluetoothGatt.readCharacteristic(c)){                            l("try to read err");                        }                    }                },0 ,100);*/            }        }    }
    BluetoothGattCallback mBluetoothGattCallback=new BluetoothGattCallback() {        //连接回调@Overridepublic void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {super.onConnectionStateChange(gatt, status, newState);            l("onConnectionStateChange status="+status);if (status==BluetoothGatt.GATT_SUCCESS) {                l("onConnectionStateChange: ========》》连接成功");                gatt.discoverServices();            }        }
@Overridepublic void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic c, int status) {byte[] buf=c.getValue();            String uuid_info=getUuidInfo("",c.getUuid().toString());            l(" -> LE读取到数据 ["+uuid_info+"] "+bytesToHexFun1(buf)+" "+(new String(buf)).toString());        }
@Overridepublic void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {            l("onDescriptorRead "+status);        }
//写入成功回调函数@Overridepublic void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {super.onCharacteristicWrite(gatt, characteristic, status);            l("onCharacteristicWrite 写入成功");        }
@Overridepublic void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {super.onDescriptorWrite(gatt, descriptor, status);            l("onDescriptorWrite status="+status);        }
@Overridepublic void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {super.onMtuChanged(gatt, mtu, status);            l("onMtuChanged");        }
//UUID搜索成功回调@Overridepublic void onServicesDiscovered(BluetoothGatt gatt, int status) {            l("onServicesDiscovered status="+status);/*            if (status == BluetoothGatt.GATT_SUCCESS) {                List<BluetoothGattService> srvs = gatt.getServices();                for (int i = 0; i < srvs.size(); i++) {                    l(" ");                    l(" ");                    String uuid=srvs.get(i).getUuid().toString();                    String uuid_s=getUuidInfo("Service",uuid);                    l((i+1)+" Service ["+uuid_s+"] UUID=:" + uuid);                    List<BluetoothGattCharacteristic> Characteristic = srvs.get(i).getCharacteristics();
                    for (int j = 0; j < Characteristic.size(); j++) {                        BluetoothGattCharacteristic c=Characteristic.get(j);                        int prop=c.getProperties();                        String uuid_c=c.getUuid().toString();                        String uuid_sc=getUuidInfo("Characteristic",uuid_c);                        l("    "+(j+1)+". Characteristic ["+uuid_sc+"] UUID=:" +uuid_c+",Prop="+getPropInfo(prop));
                        boolean ret=gatt.setCharacteristicNotification(c,true);                        if(!ret)l("     fail");                        for(BluetoothGattDescriptor d : c.getDescriptors()){                            String uuid_d=d.getUuid().toString();                            String uuid_sd=getUuidInfo("Descriptor",uuid_d);                            l("        desc ["+uuid_sd+"] UUID="+uuid_d);                        }
                    }                }            } else {                l("fail , onservicesdiscovered收到: " + status);            }            */            init_tba_oper(gatt);        }

//接受数据回调@Overridepublic void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {            String mac=gatt.getDevice().getAddress();byte[] value = characteristic.getValue();//l("ReceiveSuccess "+ bytesToHexFun1(value));
        }    };
int get_ble_idx(String mac){for (cYsBleItem x:lstDevices) {if(x.mac.equals(mac)){return x.idx;            }        }return -1;    }
public void ble_get_connected_list() {        Set<BluetoothDevice> devices =bta.getBondedDevices();for(BluetoothDevice dev:devices){boolean isConnect = false;
try {//获取当前连接的蓝牙信息                isConnect = (boolean) dev.getClass().getMethod("isConnected").invoke(dev);
            } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {                l("err ");            }
if (isConnect) {                l("device2=" + dev.getAddress());            }
            l("name="+dev.getName());        }    }}
 
 

完整的源代码可以登录【华纳网】下载。
https://www.worldwarner.com/






 





免责声明:本文仅代表作者个人观点,与华纳网无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。