1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > Android低功耗蓝牙BLE

Android低功耗蓝牙BLE

时间:2019-08-09 12:11:18

相关推荐

Android低功耗蓝牙BLE

低功耗蓝牙BLE与传统的蓝牙相比最大的优势是功耗降低90%,同时传输距离增大(超过100米)、安全和稳定性提高(支持AES加密和CRC验证),允许Android应用程序与具有更严格电源要求的BLE设备进行通信,如接近传感器、心率传感器等低功耗设备。但是BLE蓝牙一包数据最多20个字节,因此在Android系统下传输大量数据就不太合适,还的需要使用经典蓝牙。

一、蓝牙权限

1、申请权限

静态注册:

<uses-permission android:name="android.permission.BLUETOOTH" /><uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

动态申请定位权限:

String[] p = new String[]{Manifest.permission.ACCESS_FINE_LOCATION};ActivityCompat.requestPermissions(activity,p,1000);

如果您的目标是 Android 10,那么您需要 ACCESS_FINE_LOCATION 来扫描。ACCESS_COARSE_LOCATION 在 Android 10 中不再起作用。本次项目targetApi为29。

2、打开手机定位

Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);MainActivity a = (MainActivity) activity;a.startActivityForResult(intent, OPEN_GPS_CODE)

注意:蓝牙的搜索、配对等等后续功能都需要开启权限,否则啥也获取不到。

二、获取蓝牙设备的RSSI

1、已经配对

BluetoothDevice remoteDevice = bluetoothAdapter.getRemoteDevice(deviceId);remoteDevice.connectGatt(activity, false, new BluetoothGattCallback() {@Overridepublic void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {super.onConnectionStateChange(gatt, status, newState);handler.postDelayed(new Runnable() {@Overridepublic void run() {gatt.readRemoteRssi();}}, 1000);}@Overridepublic void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {super.onReadRemoteRssi(gatt, rssi, status);LogUtils.d("onReadRemoteRssi:" + rssi);}});

2、未配对

public void getBLEDeviceRSSI(JsBLEBean bean) {IntentFilter filter = new IntentFilter();filter.addAction(BluetoothDevice.ACTION_FOUND);activity.registerReceiver(new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {if (intent.getAction().equals(BluetoothDevice.ACTION_FOUND)){BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);if (device.getAddress().equals(deviceId)){short rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, (short) 0);//信号强度LogUtils.d("device.getAddress():"+device.getAddress());LogUtils.d("device.getAddress():"+rssi);}}}}, filter);bluetoothAdapter.startDiscovery();}

三、BLE蓝牙搜索

已知蓝牙的Mac地址:deviceId

//过滤条件ArrayList<ScanFilter> scanFilterList = new ArrayList<>();ScanFilter scanFilter = new ScanFilter.Builder().setDeviceAddress(deviceId).build();scanFilterList.add(scanFilter);//扫描设置。ScanSettings scanSettings = new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).setReportDelay(0).build();//连接BluetoothLeScanner bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();BleScanning bleScanning = new BleScanning(callback);bluetoothLeScanner.startScan(scanFilterList, scanSettings, new ScanCallback() {@Overridepublic void onScanResult(int callbackType, ScanResult result) {super.onScanResult(callbackType, result);}@Overridepublic void onBatchScanResults(List<ScanResult> results) {super.onBatchScanResults(results);}@Overridepublic void onScanFailed(int errorCode) {super.onScanFailed(errorCode);}});

四、BLE蓝牙连接

device.connectGatt(activity, false, callback);

参数2:是直接连接到远程设备(false)还是在远程设备可用时自动连接(true)。注意如果是直接连接使用false。

参数3:将接收异步回调的 GATT 回调处理程序。

1、已经配对了

Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();if (pairedDevices.size() > 0) {for (BluetoothDevice device : pairedDevices) {String id = device.getAddress();if (deviceId.equals(id)) {device.connectGatt(activity, true, new BluetoothGattCallback() {if (status == BluetoothGatt.GATT_SUCCESS) {if (newState == BluetoothProfile.STATE_CONNECTED) {// 已连接状态,表明连接成功// 连接到蓝牙后查找可以读写的服务ApplicationUtils.getMainHander().postDelayed(new Runnable() {@Overridepublic void run() {//延迟一秒,否则扫描失败,没有onServicesDiscovered回调gatt.discoverServices();//扫描特征值}}, 1000);} else if(newState == BluetoothProfile.STATE_DISCONNECTED) {// 避免其他情况出现,不满足条件的都断开连接close(gatt);LogUtils.d("连接失败");}} else {close(gatt);LogUtils.d("连接失败");}}}

//关闭资源,否则会出现BluetoothGatt status 133public void close(BluetoothGatt gatt) {if (gatt != null) {ApplicationUtils.getMainHander().post(new Runnable() {@Overridepublic void run() {gatt.disconnect();gatt.close();}});}}

蓝牙连接随时可能断开,建议监听状态,断开后重新连接即可。

2、没有配对

则执行上一步搜索BLE设备,然后配对,再执行上面的连接方法。

五、获取蓝牙设备所有服务

BluetoothDevice remoteDevice = bluetoothAdapter.getRemoteDevice(deviceId);remoteDevice.connectGatt(activity, false, new BluetoothGattCallback() {@Overridepublic void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {super.onCharacteristicChanged(gatt, characteristic);LogUtils.d("onCharacteristicChanged");}@Overridepublic void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {super.onConnectionStateChange(gatt, status, newState);LogUtils.d("onConnectionStateChange");// 已连接状态,表明连接成功if (newState == BluetoothProfile.STATE_CONNECTED) {// 连接到蓝牙后查找可以读写的服务handler.postDelayed(new Runnable() {@Overridepublic void run() {//延迟一秒,否则扫描失败,没有onServicesDiscovered回调gatt.discoverServices();//扫描特征值}}, 1000);return;}// 断开连接或未连接成功if (newState == BluetoothProfile.STATE_DISCONNECTED) {LogUtils.d("断开接连");return;}// 避免其他情况出现,不满足条件的都断开连接gatt.disconnect();gatt.close();}@Overridepublic void onServicesDiscovered(BluetoothGatt gatt, int status) {super.onServicesDiscovered(gatt, status);if (status == BluetoothGatt.GATT_SUCCESS) { //BLE服务发现成功List<BluetoothGattService> services = gatt.getServices();for (BluetoothGattService service : services) {JsCreateGetBLEDeviceServicesBean.DataBean dataBean = new JsCreateGetBLEDeviceServicesBean.DataBean();//服务的UUIDString uuid = service.getUuid().toString();//是否是主服务String isPrimary = service.getType() == BluetoothGattService.SERVICE_TYPE_PRIMARY;} }}});

六、获取蓝牙设备某个服务中所有特征值

BluetoothDevice remoteDevice = bluetoothAdapter.getRemoteDevice(deviceId);remoteDevice.connectGatt(activity, false, new BluetoothGattCallback() {@Overridepublic void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {super.onConnectionStateChange(gatt, status, newState);LogUtils.d("onConnectionStateChange");// 已连接状态,表明连接成功if (newState == BluetoothProfile.STATE_CONNECTED) {// 连接到蓝牙后查找可以读写的服务handler.postDelayed(new Runnable() {@Overridepublic void run() {//延迟一秒,否则扫描失败,没有onServicesDiscovered回调gatt.discoverServices();//扫描特征值}}, 1000);return;}// 断开连接或未连接成功if (newState == BluetoothProfile.STATE_DISCONNECTED) {return;}// 避免其他情况出现,不满足条件的都断开连接gatt.disconnect();gatt.close();}@Overridepublic void onServicesDiscovered(BluetoothGatt gatt, int status) {super.onServicesDiscovered(gatt, status);gatt.requestMtu(mtu);LogUtils.d("onServicesDiscovered");if (status == BluetoothGatt.GATT_SUCCESS) { //BLE服务发现成功List<BluetoothGattService> services = gatt.getServices();for (BluetoothGattService service : services) {if (service.getUuid().toString().equals(serviceId)) {BluetoothGattService gattService = gatt.getService(UUID.fromString(serviceId));if (gattService != null) {//设备的特征值列表List<BluetoothGattCharacteristic> characteristics = gattService.getCharacteristics();for (BluetoothGattCharacteristic characteristic : characteristics) {LogUtils.d("找到对应可读写特征");String uuid = characteristic.getUuid().toString();String properties;switch (characteristic.getProperties()) {case BluetoothGattCharacteristic.PROPERTY_READ:properties = "read";break;case BluetoothGattCharacteristic.PROPERTY_WRITE:properties = "write";break;case BluetoothGattCharacteristic.PROPERTY_NOTIFY:properties = "notify";break;case BluetoothGattCharacteristic.PROPERTY_INDICATE:properties = "indicate";break;default:break;} }}}}} }});

七、接收通知消息,订阅特征值

BluetoothDevice remoteDevice = bluetoothAdapter.getRemoteDevice(deviceId);remoteDevice.connectGatt(activity, false, new BluetoothGattCallback() {@Overridepublic void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {super.onConnectionStateChange(gatt, status, newState);LogUtils.d("onConnectionStateChange");// 已连接状态,表明连接成功if (newState == BluetoothProfile.STATE_CONNECTED) {// 连接到蓝牙后查找可以读写的服务handler.postDelayed(new Runnable() {@Overridepublic void run() {//延迟一秒,否则扫描失败,没有onServicesDiscovered回调gatt.discoverServices();//扫描特征值}}, 1000);return;}// 断开连接或未连接成功if (newState == BluetoothProfile.STATE_DISCONNECTED) {return;}// 避免其他情况出现,不满足条件的都断开连接gatt.disconnect();gatt.close();}@Overridepublic void onServicesDiscovered(BluetoothGatt gatt, int status) {super.onServicesDiscovered(gatt, status);if (status == BluetoothGatt.GATT_SUCCESS) { //BLE服务发现成功BluetoothGattService gattService = gatt.getService(UUID.fromString(serviceId));if (gattService != null) {//设备的特征值列表List<BluetoothGattCharacteristic> characteristics = gattService.getCharacteristics();for (BluetoothGattCharacteristic characteristic : characteristics) {if (characteristic.getUuid().toString().equals(characteristicId)) {//启动特征值通知gatt.setCharacteristicNotification(characteristic, true);byte[] value = state ? BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE : BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE;BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString(characteristicId));if (descriptor == null) {descriptor = new BluetoothGattDescriptor(UUID.fromString(characteristicId),BluetoothGattDescriptor.PERMISSION_WRITE);}descriptor.setValue(value);gatt.writeDescriptor(descriptor);}}}} }@Overridepublic void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {super.onCharacteristicChanged(gatt, characteristic);//当我们决定用通知的方式获取外设特征值的时候,每当特征值发生变化,程序就会回调到此处。//特征值最新的值byte[] value = characteristic.getValue();}});

八、写入低功耗蓝牙设备特征值二进制数据

String deviceId = data.deviceId;String characteristicId = characteristicId;String serviceId = data.serviceId;byte[] bytes = data.value;BluetoothDevice remoteDevice = bluetoothAdapter.getRemoteDevice(deviceId);remoteDevice.connectGatt(activity, false, new BluetoothGattCallback() {@Overridepublic void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {super.onCharacteristicChanged(gatt, characteristic);//特征值最新的值byte[] value = characteristic.getValue();}@Overridepublic void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {super.onConnectionStateChange(gatt, status, newState);LogUtils.d("onConnectionStateChange");// 已连接状态,表明连接成功if (newState == BluetoothProfile.STATE_CONNECTED) {LogUtils.d("连接成功");// 连接到蓝牙后查找可以读写的服务handler.postDelayed(new Runnable() {@Overridepublic void run() {//延迟一秒,否则扫描失败,没有onServicesDiscovered回调gatt.discoverServices();//扫描特征值}}, 1000);return;}// 断开连接或未连接成功if (newState == BluetoothProfile.STATE_DISCONNECTED) {LogUtils.d("断开接连");return;}// 避免其他情况出现,不满足条件的都断开连接gatt.disconnect();gatt.close();}@Overridepublic void onServicesDiscovered(BluetoothGatt gatt, int status) {super.onServicesDiscovered(gatt, status);gatt.requestMtu(mtu);LogUtils.d("onServicesDiscovered");if (status == BluetoothGatt.GATT_SUCCESS) { //BLE服务发现成功BluetoothGattService gattService = gatt.getService(UUID.fromString(serviceId));if (gattService != null) {BluetoothGattCharacteristic characteristic = gattService.getCharacteristic(UUID.fromString(characteristicId));if (characteristic != null) {characteristic.setValue(bytes);gatt.writeCharacteristic(characteristic);LogUtils.d("writeData:写了一次数据!");}}} }@Overridepublic void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {super.onCharacteristicWrite(gatt, characteristic, status);if (characteristic.getUuid().toString().equals(serviceId)) {byte[] value = characteristic.getValue();}});

九、读取低功耗蓝牙设备特征值二进制数据

String deviceId = data.deviceId;String characteristicId = data.characteristicId;String serviceId = data.serviceId;byte[] bytes = data.value;BluetoothDevice remoteDevice = bluetoothAdapter.getRemoteDevice(deviceId);remoteDevice.connectGatt(activity, false, new BluetoothGattCallback() {@Overridepublic void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {super.onCharacteristicChanged(gatt, characteristic);//特征值最新的值byte[] value = characteristic.getValue();}@Overridepublic void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {super.onConnectionStateChange(gatt, status, newState);LogUtils.d("onConnectionStateChange");// 已连接状态,表明连接成功if (newState == BluetoothProfile.STATE_CONNECTED) {LogUtils.d("连接成功");// 连接到蓝牙后查找可以读写的服务handler.postDelayed(new Runnable() {@Overridepublic void run() {//延迟一秒,否则扫描失败,没有onServicesDiscovered回调gatt.discoverServices();//扫描特征值}}, 1000);return;}// 断开连接或未连接成功if (newState == BluetoothProfile.STATE_DISCONNECTED) {LogUtils.d("断开接连");return;}// 避免其他情况出现,不满足条件的都断开连接gatt.disconnect();gatt.close();}@Overridepublic void onServicesDiscovered(BluetoothGatt gatt, int status) {super.onServicesDiscovered(gatt, status);gatt.requestMtu(mtu);LogUtils.d("onServicesDiscovered");if (status == BluetoothGatt.GATT_SUCCESS) { //BLE服务发现成功BluetoothGattService gattService = gatt.getService(UUID.fromString(serviceId));if (gattService != null) {BluetoothGattCharacteristic characteristic = gattService.getCharacteristic(UUID.fromString(characteristicId));if (characteristic != null) {gatt.readCharacteristic(characteristic);LogUtils.d("readData:读了一次数据!");}}} }@Overridepublic void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {super.onCharacteristicRead(gatt, characteristic, status);if (characteristic.getUuid().toString().equals(serviceId)) {byte[] value = characteristic.getValue();}}});

十、设置蓝牙最大传输单元

最大传输单元(22,512) 区间内,单位 bytes。

BluetoothDevice remoteDevice = bluetoothAdapter.getRemoteDevice(deviceId);remoteDevice.connectGatt(activity, false, new BluetoothGattCallback() {@Overridepublic void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {super.onConnectionStateChange(gatt, status, newState);// 已连接状态,表明连接成功if (newState == BluetoothProfile.STATE_CONNECTED) {// 连接到蓝牙后查找可以读写的服务handler.postDelayed(new Runnable() {@Overridepublic void run() {//延迟一秒,否则扫描失败,没有onServicesDiscovered回调gatt.discoverServices();//扫描特征值}}, 1000);return;}// 断开连接或未连接成功if (newState == BluetoothProfile.STATE_DISCONNECTED) {return;}// 避免其他情况出现,不满足条件的都断开连接gatt.disconnect();gatt.close();}@Overridepublic void onServicesDiscovered(BluetoothGatt gatt, int status) {super.onServicesDiscovered(gatt, status);//在这设置gatt.requestMtu(mtu);}});

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。