上一篇讲到连接设备,这一篇讲蓝牙设备通讯。
主要用到以下几个类。
BluetoothGattService:(蓝牙服务)一台蓝牙设备上最少有1个或一个以上服务。
BluetoothGattCharacteristic:(蓝牙特性)一个服务里最少有1个及以上的特性。
UUID:每个服务和特性都有一个特定的UUID类似于身份证号的意思。
代码:在连接成功中去寻找服务:
case BluetoothGatt.STATE_CONNECTED://已连接
Log.e("lee", "已连接");
//去寻找服务
bluetoothGatt.discoverServices();
break;
//当服务被找到时回调此方法。
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
if (status == BluetoothGatt.GATT_SUCCESS) {//寻找服务成功。
//或许该设备下的所有服务(每个服务都有自己的UUID)
List<BluetoothGattService> services = gatt.getServices();
for (BluetoothGattService service : services) {
//获取该服务下的所有的特性
List<BluetoothGattCharacteristic> characteristics = service.getCharacteristics();
for (BluetoothGattCharacteristic characteristic : characteristics) {
//此处可以和蓝牙设备的硬件工程师交流 哪个特征值是对应的什么效果。 然后通过调用
if (characteristic.getUuid().equals("00000")) {//(此处我就瞎写一个) 通过UUID来获取硬件工程师告诉你的特征
characteristic.setValue(new byte[]{0x05});//(这个也是我瞎写的 需要蓝牙硬件工程师告诉你)
//调用了这个setValue()方法写入对应的数据,就能调用蓝牙设备的该特性了。
}
}
}
}
}
当然这里setValue()方法一般都是写在某个按钮的点击事件中,所以需要把
characteristic抽出来赋值成一个成员变量。
以上就完成了App去控制蓝牙设备的功能。
if (characteristic.getUuid().equals("11111")) {//(此处我就瞎写一个) 获取设备控制App的命令
//调用此方法获取设备的通知
characteristic.notify();//(这个也是我瞎写的)
}
//当特征值改变时回调此方法。
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
//通过判断characteristic的UUID和我们下面的那个11111的UUid是不是一样的 是一样的就可以做对应的操作了。
if (characteristic.getUuid().equals("11111")){
//获取characteristic中的值
byte[] value = characteristic.getValue();
//转化成16进制
String s = bytesToHex(value);
if (s.equals("0x55")){
//执行对应的操作
}
}
}
以上就完成了蓝牙设备控制手机。
当需要一直读取设备上的某个信息时需要用到read方法
if (characteristic.getUuid().equals("22222")) {//(此处我就瞎写一个) 获取设备的电量
//调用此方法获取设备的通知 读取到时会回调
gatt.readCharacteristic(characteristic);
}
//当读取到设备的信息时回调此方法
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
if (status == BluetoothGatt.GATT_SUCCESS) {//读取成功
if (characteristic.getUuid().equals("22222")) {
byte[] value = characteristic.getValue();
}
}
}
以下就是全部代码
package com.demo.ibeacondemo;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private BluetoothAdapter mBluetoothAdapter;
private static final int REQUEST_COARSE_LOCATION = 0;
private List<BluetoothDevice> devices = new ArrayList<>();
private BluetoothGatt bluetoothGatt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
isLocationOpen();
BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
Intent enableBluetooth = new Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBluetooth, 1);
}
mBluetoothAdapter.startLeScan(mLeScanCallback);
}
static final char[] hexArray = "0123456789ABCDEF".toCharArray();
private void isLocationOpen() {
//清单文件里面也需要配置
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.CAMERA,}, 0);
}
}
//系统方法,从requestPermissions()方法回调结果
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
//确保是我们的请求
if (requestCode == REQUEST_COARSE_LOCATION) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "权限被授予", Toast.LENGTH_SHORT).show();
} else if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "权限被拒绝", Toast.LENGTH_SHORT).show();
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
private static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) {
if (!devices.contains(device)) {
}
bluetoothGatt = device.connectGatt(MainActivity.this, false, gattCallback);
}
};
private BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
//链接状态改变回调此方法。
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
switch (newState) {
case BluetoothGatt.STATE_CONNECTED://已连接
Log.e("lee", "已连接");
//去寻找服务
bluetoothGatt.discoverServices();
break;
case BluetoothGatt.STATE_CONNECTING://连接中
Log.e("lee", "连接中");
break;
case BluetoothGatt.STATE_DISCONNECTED://已断开
Log.e("lee", "已断开");
break;
case BluetoothGatt.STATE_DISCONNECTING://断开中
Log.e("lee", "断开中");
break;
}
}
//当读取到设备的信息时回调此方法
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
if (status == BluetoothGatt.GATT_SUCCESS) {//读取成功
if (characteristic.getUuid().equals("22222")) {
byte[] value = characteristic.getValue();
}
}
}
//当特征值改变时回调此方法。
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
//通过判断characteristic的UUID和我们下面的那个11111的UUid是不是一样的 是一样的就可以做对应的操作了。
if (characteristic.getUuid().equals("11111")){
//获取characteristic中的值
byte[] value = characteristic.getValue();
//转化成16进制
String s = bytesToHex(value);
if (s.equals("0x55")){
//执行对应的操作
}
}
}
//当服务被找到时回调此方法。
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
if (status == BluetoothGatt.GATT_SUCCESS) {//寻找服务成功。
//或许该设备下的所有服务(每个服务都有自己的UUID)
List<BluetoothGattService> services = gatt.getServices();
for (BluetoothGattService service : services) {
//获取该服务下的所有的特性
List<BluetoothGattCharacteristic> characteristics = service.getCharacteristics();
for (BluetoothGattCharacteristic characteristic : characteristics) {
//此处可以和蓝牙设备的硬件工程师交流 哪个特征值是对应的什么效果。 然后通过调用
if (characteristic.getUuid().equals("00000")) {//(此处我就瞎写一个) 通过UUID来获取硬件工程师告诉你的特征
characteristic.setValue(new byte[]{0x05});//(这个也是我瞎写的 需要蓝牙硬件工程师告诉你)
//调用了这个setValue()方法写入对应的数据,就能调用蓝牙设备的该特性了。
}
if (characteristic.getUuid().equals("11111")) {//(此处我就瞎写一个) 获取设备控制App的命令
//调用此方法获取设备的通知
characteristic.notify();//(这个也是我瞎写的)
}
if (characteristic.getUuid().equals("22222")) {//(此处我就瞎写一个) 获取设备的电量
//调用此方法获取设备的通知 读取到时会回调
gatt.readCharacteristic(characteristic);
}
}
}
}
}
};
}
总而言之当App主动联系设备时调用写入,当设备主动联系App是调用通知,当App可能长时间获取设备信息时用读取方法。(这些很多都要看设备的文档信息)