Android 蓝牙开发
我们在进行蓝牙开发时首先要了解低功耗蓝牙、经典蓝牙、单模蓝牙、双模蓝牙之间的关系。
单模蓝牙:支持低功耗蓝牙
双模蓝牙:支持低功耗蓝牙和经典蓝牙
经典蓝牙:支持经典蓝牙
蓝牙开发大致分为这几步
前面需要定位权限和蓝牙权限的支持
发现设备:
经典蓝牙发现设备api
BluetoothAdapter.startDiscovery
听说可以同时发现经典蓝牙和低功耗蓝牙(BLE)。但我这没单模的蓝牙,所以没办法测试。
因为startDiscovery返回的是一个是否开始扫描设备,我们要获取蓝牙设备的信息需要注册一个 BroadcastReceiver 针对 ACTION_FOUND
Intent 会携带额外的字段 EXTRA_DEVICE 和 EXTRA_CLASS。这两者分别包含 BluetoothDevice 和 BluetoothClass。
var filter =IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver,filter);
val mReceiver = object :BroadcastReceiver(){
override fun onReceive(context: Context?, intent: Intent?) {
var action = intent?.action
if(BluetoothDevice.ACTION_FOUND == action){
var device = intent?.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE)
}
}
}
override fun onDestroy() {
super.onDestroy()
unregisterReceiver(mReceiver)
}
Ble发现设备api
BluetoothAdapter.getBluetoothLeScanner()
BluetoothLeScanner.startScan(ScanCallback callback)//扫描会在屏幕关闭时停止以节省电量。 再次打开屏幕时,将恢复扫描。 为避免这种情况,请使用下面两个
BluetoothLeScanner.startScan(List<ScanFilter> filters, ScanSettings settings, ScanCallback callback)
BluetoothLeScanner.startScan(List<ScanFilter> filters, ScanSettings settings, PendingIntent callbackIntent)
BluetoothLeScanner bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();
filters.add(new ScanFilter.Builder()
.setServiceUuid(ParcelUuid.fromString("0000000-0000-0000-0000-000000000000"))
.build());
bluetoothLeScanner.startScan(filters , new ScanSettings.Builder().build(),
new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Log.d(MainActivity.ACTIVITY_SERVICE, "onScanResult:"+
"\n Rssi() "+result.getRssi()+
"\n AdvertisingSid() "+result.getAdvertisingSid()+
"\n DataStatus() "+result.getDataStatus()+
"\n ScanRecord() "+result.getScanRecord().getBytes()+
"\n Address() "+result.getDevice().getAddress()+
"\n Address() "+result.getDevice().getName()
);
}
}
@Override
public void onBatchScanResults(List<ScanResult> results) {
super.onBatchScanResults(results);
}
@Override
public void onScanFailed(int errorCode) {
super.onScanFailed(errorCode);
}
}
);
建立连接:
在配对之前应该先cancelDiscovery()或者stopScan(callback),
然后根据获取到蓝牙Mac地址连接即可
BluetoothDevice device = bluetoothAdapter.getRemoteDevice(result.getDevice().getAddress());
device.connectGatt(MainActivity.this, false, new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
//status 连接或断开连接操作成功 BluetoothGatt.GATT_SUCCESS(0)
//newState 新的连接状态 BluetoothProfile.STATE_DISCONNECTED(0-断开状态) BluetoothProfile.STATE_CONNECTED(1-连接状态)
}
}
);
数据通信:ble写入操作
private BluetoothGattCallback bluetoothGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
//status 连接或断开连接操作成功 BluetoothGatt.GATT_SUCCESS(0)
//newState 新的连接状态 BluetoothProfile.STATE_DISCONNECTED(0-断开状态) BluetoothProfile.STATE_CONNECTED(1-连接状态)
//获取远程设备提供的服务以及它们的特征和描述符。这步很重要而且是一个异步操作(这里需要时间直接接在下面写不可取)
bluetoothGatt.discoverServices();
//获取蓝牙GATT服务
BluetoothGattService gattService = bluetoothGatt.getService(UUID.fromString("00000000-0000-0000-0000-000000000000"/*蓝牙协议*/));
//GATT特性:用于构建 GATT 服务的基本数据元素
BluetoothGattCharacteristic characteristic = gattService.getCharacteristic(UUID.fromString("00000000-0000-0000-0000-000000000000"));
//设置数据,这里是我加密后的数据所以看起来有点不习惯
byte[] data = {-27, 36, 65, -70, -8, 94, 18, -12, -56, 116, -68, -124, 92, -19, 94, -91 };
//设置此特性的本地存储值。
characteristic.setValue(data);
//写入到远程蓝牙设备
bluetoothGatt.writeCharacteristic(characteristic);
}
Ble通知读取操作
//通知UUID
BluetoothGattCharacteristic gattCharacteristic = gattService.getCharacteristic(UUID.fromString("00000000-0000-0000-0000-000000000000"));
enableNotification(bluetoothGatt,true,gattCharacteristic);
public void enableNotification(BluetoothGatt bluetoothGatt, boolean enable, BluetoothGattCharacteristic characteristic) {
if (bluetoothGatt == null || characteristic == null) {
return;
}
if (!bluetoothGatt.setCharacteristicNotification(characteristic, enable)) {
return;
}
//获取到Notify当中的Descriptor通道 然后再进行注册
List<BluetoothGattDescriptor> clientConfigs = characteristic.getDescriptors();
if (clientConfigs == null || clientConfigs.size() ==0) {
return;
}
if (enable) {
for (BluetoothGattDescriptor clientConfig: clientConfigs) {
clientConfig.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
bluetoothGatt.writeDescriptor(clientConfig);
}
} else {
for (BluetoothGattDescriptor clientConfig: clientConfigs) {
clientConfig.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
bluetoothGatt.writeDescriptor(clientConfig);
}
}
}