权限申请
在AndroidManifest.xml中加入:
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
在代码中动态申请权限,其中REQUEST_PERMISSION_ACCESS_LOCATION 为自定义int常量,
private void requestPermission() {
if (Build.VERSION.SDK_INT >= 23) {
int checkAccessFinePermission = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
if (checkAccessFinePermission != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_PERMISSION_ACCESS_LOCATION);
LogTool.e(TAG, "没有权限,请求权限");
return;
}
LogTool.i(TAG, "已有定位权限");
}
//做下面该做的事
}
重写onRequestPermissionsResult,验证获取权限结果,如下图:
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case REQUEST_PERMISSION_ACCESS_LOCATION:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
} else {
Toast.makeText(this,"获取权限失败",Toast.LENGTH_SHORT).show();
}
break;
}
}
使能手机蓝牙
在使用蓝牙之前需要检查手机蓝牙是否开启,若未开启,需要提示将蓝牙开启
//获取蓝牙适配器实例
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
//若蓝牙未开启,则开启蓝牙
if (! bluetoothAdapter.isEnabled()) {
//使能蓝牙
bluetoothAdapter.enable();
}
扫描蓝牙设备
private void startScan() {
//SCAN_INTERVEL = 5000 毫秒后停止扫描
postDelayed(new Runnable() {
@Override
public void run() {
bluetoothAdapter.stopLeScan(leScanCallback);
}
}, SCAN_INTERVEL);
//开始扫描
bluetoothAdapter.startLeScan(leScanCallback);
}
其中leScanCallback为扫描回调方法,定义如下:
final BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(BluetoothDevice bluetoothDevice, int i, byte[] bytes) {
//这里当扫描到的设备,设备名不为null,就通过logi输出设备名和MAC地址。
//这里也可以添加其他筛选条件,如特定设备名、或设备列表中是否已有。
if(bluetoothDevice.getName() != null) {
//这里可以将设备添加到列表中,并通过ListView显示出来
Log.i(TAG, "onLeScan: " + bluetoothDevice.getName() + " : " + bluetoothDevice.getAddress());
}
}
};
连接扫描到的蓝牙设备
//MACADDR 为要连接的设备MAC地址,可以通过设备的getAddress()方法获取
BluetoothDevice bluetoothDevice = bluetoothAdapter.getRemoteDevice(MACADDR);
BluetoothGatt bluetoothGatt;
if(bluetoothDevice != null)
{
bluetoothGatt = bluetoothDevice.connectGatt(context,true,gattCallback);
}
else{
LogTool.i(TAG, "onItemClick: 没有该设备");
}
定义gattCallback,并重写一系列方法,这些方法会在连接过程中被调用,可以在这里做一些连接状态的处理:
BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
//连接状态发生改变时调用
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if(status == BluetoothGatt.GATT_SUCCESS) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
//建立连接
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
//连接断开
}
}
}
//发现服务
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
//这里可以通过发送广播,接收到相应广播后,对服务做相应处理。
LogTool.i(TAG, "onServicesDiscovered:status:" + status);
} else {
LogTool.w(TAG, "onServicesDiscovered received: " + status);
System.out.println("onServicesDiscovered received: " + status);
}
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
//读取到值,在这里读数据
if (status == BluetoothGatt.GATT_SUCCESS) {
//数据处理
}
}
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
switch(status) {
case BluetoothGatt.GATT_SUCCESS:
LogTool.i(TAG, "write data success");
break;
case BluetoothGatt.GATT_FAILURE:
LogTool.i(TAG, "write again");
gatt.writeCharacteristic(characteristic);
break;
case BluetoothGatt.GATT_WRITE_NOT_PERMITTED:
LogTool.i(TAG, "write not permitted");
break;
}
super.onCharacteristicWrite(gatt,characteristic,status);
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
}
};
服务和特征值获取
这里获取是继上述的回调函数onServicesDiscovered,在广播接受者中获取相应的服务和特征值:
//写数据的服务和characteristic
BluetoothGattService bluetoothGattService;
BluetoothGattCharacteristic characteristicRead;
BluetoothGattCharacteristic characteristicWrite;
//获取服务
bluetoothGattService = bluetoothGatt.getService(UUID.fromString("0000ffe0-0000-1000-8000-00805f9b34fb"));
//获取读特征值
characteristicRead = bluetoothGattService.getCharacteristic(UUID.fromString("0000ffe7-0000-1000-8000-00805f9b34fb"));
//获取写特征值
characteristicWrite = bluetoothGattService.getCharacteristic(UUID.fromString("0000ffe6-0000-1000-8000-00805f9b34fb"));
//使能接收数据通知
List<BluetoothGattDescriptor> descriptors = characteristicRead.getDescriptors();
for (BluetoothGattDescriptor bgp : descriptors) {
LogTool.i(TAG, "setCharacteristicNotification: " + bgp);
bgp.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
bluetoothGatt.writeDescriptor(bgp);
}
数据的收发
接收数据
在上述的回调过程中,若特征值为读特征值,则此时可以从特征值中读取设备发送来的数据:
//这里例子里读特征值的UUID为0000ffe7-0000-1000-8000-00805f9b34fb,在实际应用中视实际情况而定。
if ( characteristic.getUuid().toString().equals("0000ffe7-0000-1000-8000-00805f9b34fb")){
// For all other profiles, writes the data formatted in HEX.对于所有的文件,写入十六进制格式的文件
//这里读取到数据,读取的数据为byte数组
final byte[] data = characteristic.getValue();
LogTool.i(TAG, "broadcastUpdate: data length = " + data.length);
}
发送数据
//为写特征值设置要发送的数据,datas为byte数组
characteristicWrite.setValue(datas);
//gatt发送数据
bluetoothGatt.writeCharacteristic(characteristicWrite);
小结
BLE的使用主要难点在建立连接部分,需要在实际编程中理解连接过程以及相应
BluetoothGattCallback 回调调用过程。BluetoothGattCallback回调函数中不做实际的数据的处理,一般通过发送广播,在广播接受者中处理相应的过程和数据。
网友评论