项目地址:
gitee.com/bluetooth
这个项目包含多个Android模块,其中的
test2
模块就是蓝牙Gatt功能。
此项目只是一个测试的
demo
,如果要测试
Gatt蓝牙连接
的代码可以看看。
一、蓝牙Gatt连接步骤:
当时不清楚Gatt连接的流程是什么,所以写了很多冗余代码,后面也没有抽出时间去优化。
在这里写一下核心的代码分析。(项目中的Gatt蓝牙连接代码是从网上的demo修改来的,
对蓝牙数据的处理部分是实际项目中的)。
数据处理部分:1.发送Gatt数据前字符串太长的话需要对字符串进行截取,分段发送。
2.每次得到返回的Gatt数据后需要获取其中的标志和有用信息保存起来
1.连接步骤:
0.确定要连接的蓝牙设备的
Mac地址
1.扫描到目标蓝牙设备,得到
BluetoothDevice mSelectedDevice
对象。
2.使用
mSelectedDevice.connectGatt(context,false,mGattCallback)
进行Gatt连接。
3.在
BluetoothGattCallback mGattCallback
里面获取
Gatt-Service服务
,从服务中获取
BluetoothGattCharacteristic mVIDPIDCharacteristic
Gatt特征值对象。
4.发送Gatt消息的时候使用
mBluetoothGatt.writeCharacteristic()
BluetoothGattCharacteristic RxChar...
RxChar.setValue()
mBluetoothGatt.writeCharacteristic(RxChar)
5.蓝牙设备返回的Gatt消息BluetoothGattCallback mGattCallback => onCharacteristicChanged
监听的方法中获取。
二.详细的Gatt核心代码逻辑
因为MainActivity
和TestActivity
中代码都比较多,都有一些必要的代码所以没有将两个代码放到一块。
1.代码逻辑
1.进入MainActivity
页面后,首先获取定位权限,打开手机蓝牙。定义目标蓝牙设备的Mac地址
private String MAC = "54:6C:0E:35:78:18"
2.点击开始搜索
按钮后,执行蓝牙扫描操作,注册广播监听蓝牙扫描回调。在扫描到蓝牙后判断是目标蓝牙后,携带BluetoothDevice device
参数跳转到TestActivity
页面。
3.在TestActivity
页面使用BluetoothDevice mSelectedDevice
接收传过来的蓝牙对象。在onResume
方法里面执行connectGatt逻辑
。需要定义Gatt服务的各个Id值
如:RX_SERVICE_UUID、RX_CHAR_UUID、RX_CHAR_UUID_DSC、RX_DESC_UUID、RX_DESC_UUID_DES
3.1使用mBluetoothGatt = mSelectedDevice.connectGatt(mContext, false, mGattCallback)
进行Gatt连接
3.2在BluetoothGattCallback mGattCallback
回调中获取Gatt连接信息
及真正的Gatt连接
操作。
3.2.1在onConnectionStateChange
方法判断Gatt连接状态if (status == BluetoothGatt.GATT_SUCCESS) {}
3.2.2在onServicesDiscovered
方法中获取Gatt-Service服务List<BluetoothGattService> services = gatt.getServices();
3.3.3在使用Gatt-Service的特征值连接时需要:ServiceId:RX_SERVICE_UUID
、CharaId:RX_CHAR_UUID_DSC
、DescriptorId:RX_CHAR_UUID_DSC
。最后取到BluetoothGattDescriptor descriptor
,使用mBluetoothGatt.writeDescriptor(descriptor);
进行真正的连接。
3.3.4在onDescriptorWrite
方法中监听连接状态,这里的连接成功才是真正的连接成功!
4.点击发送消息
按钮,处理数据后使用sendData(byte[] value)
方法执行发送Gatt数据的逻辑,在onCharacteristicWrite
回调方法中可以监听到发送的数据。在onCharacteristicRead
方法没有实际作用。
5.在onCharacteristicChanged
回调方法中获取从蓝牙设备返回的数据,对返回的数据做处理。
三.其他代码分析
如果要使用MainActivity
页面的一些代码,要注意的是:
在配置private String MAC = "54:6C:0E:35:78:18";
蓝牙Mac地址后,如果扫描到目标蓝牙会直接跳到TestActivity
的问题。
主要在MainActivity
中:
1.获取定位权限及回调
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);
Log.e(getPackageName(), "没有权限,请求权限");
return;
Log.e(getPackageName(), "已有定位权限");
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case 1: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.e(getPackageName(), "开启权限permission granted!");
} else {
Log.e(getPackageName(), "没有定位权限,请先开启!");
Toast.makeText(this, "权限没有开启!", Toast.LENGTH_SHORT).show();
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
2.打开蓝牙功能
private boolean openBluetooth(BluetoothAdapter blueToothClient) {
if (blueToothClient != null && !blueToothClient.isEnabled()) {
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, REQUEST_OPEN_BT_CODE);
return false;
return true;
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_OPEN_BT_CODE) {
Boolean success = resultCode == RESULT_OK;
showToast(success ? "打开蓝牙成功!" : "打开蓝牙失败!");
if (success) search(null);
if (success) getBindDevice(null);
3.对列表蓝牙操作弹窗DeviceActionFragment
4.点击蓝牙列表中的连接蓝牙,先进行蓝牙绑定
操作。
BleHelper.bond(device)
4.1在配对的情况下进行数据传输,这里使用蓝牙手机、蓝牙耳机测试一直有问题。
BleHelper.connectDevice(blueToothClient, device, MainActivity.this);
5.如果知道目标蓝牙的Pin码
的话,在上面绑定的过程中会拦截蓝牙Pin配对
过程直接使用代码进行配对连接。
6.蓝牙断开连接,在DeviceActionFragment
中。
Boolean remove = BleHelper.removeBonds(bluetoothDevice);
Toast.makeText(this.getActivity(), remove ? "断开成功!" : "断开失败!", Toast.LENGTH_SHORT).show();
跃跃2020
Android、前端菜鸟
粉丝