关于BLE开发,网上相关的资料其实也不少,大多数资料介绍的还是很不错,不过我这边资料,主要侧重代码方便的介绍及使用。
1 我的这边是基于Android6.0以上版本开发的所以首先就得获取授权:
//请求蓝牙权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
}
}
2 从系统这边获取BluetoothManager服务:
BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
拿到BluetoothManager服务后获取适配器
BluetoothAdapter mBluetoothAdapter = bluetoothManager.getAdapter();
3 通过BluetoothAdapter我们可以做接下来的扫描蓝牙的操作
mBluetoothAdapter.startLeScan(mLeScanCallback);
在这个startLeScan()方法里面是有一个扫描后的结果回调的,扫描结果的返回就在这个LeScanCallBack里面:
// Device scan callback.
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, final int rssi, byte[] scanRecord) {
runOnUiThread(new Runnable() {
@Override
public void run() {
if (!TextUtils.isEmpty(device.getName()) && device.getName().contains("AAA")){
mLeDeviceListAdapter.addDevice(device);
}
Log.d(TAG, " rssi = " + rssi + "addr = " + device.getAddress());
if(device.getUuids() == null)
Log.d(TAG, "uuid = null rssi = " + rssi);
else
Log.d(TAG, "uuid = " + device.getUuids().toString() + " rssi = " + rssi);
mLeDeviceListAdapter.notifyDataSetChanged();
}
});
}
};
onLeScan()这个函数的回调注意下,是在子线程里面,我这边操作用到了UI,所以我的线程就得切换到UI线程,主要用到了列表展示搜索到蓝牙名称。到这里我们基本蓝牙的搜索就走完了,接下来就得看看如何通过蓝牙建立连接传输数据。
4 建立连接:这个步骤需要一个核心的BluetoothDevice 类,这个类怎么来的,细心的同学估计看到了,就在onLeScan(final BluetoothDevice device, final int rssi, byte[] scanRecord)回调函数里面,我这边是用一个listview展示,点击某一个蓝牙的建立连接,接下来就看他的核心方法。
BluetoothGatt bluetoothGatt = mDevice.connectGatt(this, false, mGattCallback);
通过BluetoothDevice.connectGatt()建立连接,里面有三个参数,第一参数是上下文环境,第二个参数是第一连接失败后,是否接着连接,第三个参数是建立连接后回调。而传输数据这块就跟这个回调有着千丝万缕的联系。细看这个回调函数:
// 参数连接状态回调
private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
//连接状态改变的回调
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
// 连接成功后启动服务发现
bluetoothGatt.discoverServices();
}
};
//发现服务的回调
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.e(TAG, "成功发现服务");
List list = gatt.getServices();
for (int i = 0; i < list.size(); i++) {
Log.e("--->",list.get(i).toString());
BluetoothGattService service = list.get(i);
Log.e("1-->Service UUID",service.getUuid()+"");
List data = list.get(i).getCharacteristics();
for (int j = 0; j < data.size(); j++) {
BluetoothGattCharacteristic bluetoothGattCharacteristic = data.get(j);
// bluetoothGattCharacteristic.getValue();
Log.e("2-->Characteristic UUID",bluetoothGattCharacteristic.getUuid()+"");
Log.e("--->",data.get(j).toString());
}
}
} else {
Log.e(TAG, "服务发现失败,错误码为:" + status);
}
};
//写操作的回调
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
String s = new String(characteristic.getValue());
Log.e(TAG, "写入成功" + characteristic.getUuid().toString()
+"length ="+ characteristic.getValue().length
+"content=" + s);
}
};
//读操作的回调
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
String s = new String(characteristic.getValue());
Log.e(TAG, "读取成功" + characteristic.getValue().toString()
+"length =="+ characteristic.getValue().length
+ s );
}
}
//数据返回的回调(此处接收BLE设备返回数据)
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
Log.e(TAG,"--->onCharacteristicChanged");
};
};
这个BluetoothGattCallback连接参数状态的回调是很有重要性的,当与设备建立连接的时候会在onConnectionStateChange()回调,然后在这个回调里面进行bluetoothGatt.discoverServices();这个是发现服务的核心启动方法,然后在onServicesDiscovered()回调出来,这个时候在这里进行BluetoothGattService获取以及BluetoothGattCharacteristic获取,这样蓝牙的真正的链路打算打通,后面两个回调也是很重要的,bluetoothGatt进行读写操作的回调,这个是跟业务层有着重要联系,在这一层可以很好的掌控读写。其实BluetoothGattCallback回调里面不止这些的,还有其他的回调,比如很重要的一个回调的就是设置MTU的回调,这是蓝牙读写开始限制是20个字节,设置mtu后最大可支持到512的字节。但这个设置需要在onConnectionStateChange()里面进行操作。前提条件是:AndroidAPI要在21以上。
boolean mtu = bluetoothGatt.requestMtu(512);
@Override
public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
super.onMtuChanged(gatt, mtu, status);
Log.e(TAG, "启动服务发现:" + service);
Log.e("-->onMtuChanged","长度:"+mtu);
}
5.传输数据
传输数据这块其实就是很简单的,这里面我就直接上代码了
读的操作:
characteristic.getValue();
bluetoothGatt.readCharacteristic(characteristic);
写的操作:
characteristic.setValue("要写入的内容");
bluetoothGatt.writeCharacteristic(characteristic);
这里主要注意的一点就是characteristic 不要被我传入所迷惑,characteristic就是BluetoothGattCharacteristic,每个蓝牙都有能读写的characteristic这个获取就是onServicesDiscovered回调里获取的,心细的同学估计都看到了,我在这个函数回调里进行了打印,其实这就是需要处理的,我这是和我的嵌入式同事协定好用一个协定的服务。
从获取授权,拿到系统服务,扫描蓝牙,建立连接,传输数据这一整个蓝牙开发流程就走了,如有不对的地方欢迎指教,谢谢!