最近做了有关安卓BLE蓝牙开发的东西,所以在这里记录一下,是一些入门的知识。希望能帮到正需要学习安卓ble蓝牙开发的同学。
-
介绍:安卓 4.3(API 18)为 BLE 的核心功能提供平台支持和 API,App 可以利用它来发现设 备、查询服务和读写特性。相比传统的蓝牙,BLE 更显著的特点是低功耗。这一优 点使 Android App 可以与具有低功耗要求的 BLE 设备通信,如近距离传感器、心脏 速率监视器、健身设备等。
-
角色和责任 :
以下是 Android 设备与 BLE 设备交互时的角色和责任:
中央 VS 外围设备。 适用于 BLE 连接本身。中央设备扫描,寻找广播;外 围设备发出广播。 GATT 服务端 VS GATT 客户端。决定了两个设备在建立连接后如何互相交 流。为了方便理解,想象你有一个 Android 手机和一个用于活动跟踪 BLE 设备,手机支 持中央角色,活动跟踪器支持外围(为了建立 BLE 连接你需要注意两件事,只支持 外围设备的两方或者只支持中央设备的两方不能互相通信)。 当手机和运动追踪器建立连接后,他们开始向另一方传输 GATT 数据。哪一方作为 服务器取决于他们传输数据的种类。例如,如果运动追踪器想向手机报告传感器数 据,运动追踪器是服务端。如果运动追踪器更新来自手机的数据,手机会作为服务 端。
代码编写:
- 权限部分:我开发过程中要了以下几个权限,才能正常使用相应功能。有些运行时申请的权限请各位读者自行申请权限。
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
2. 第一步:检查设备是否支持BLE
private void check()//检查设备是否支持BLE
{
if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION); }
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE))
{
Toast.makeText(this, "此设备不支持BLE功能", Toast.LENGTH_SHORT).show();
finish();
}
}
3. 第二步:开启BLE蓝牙
mBluetoothAdapter 是蓝牙设配器在整个蓝牙开发中有重要功能,后续也会用到这个对象,所以这里我们先初始化它。
private void bleTurnOn()//开启BLE蓝牙
{
final BluetoothManager bluetoothManager =(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
// 确保蓝牙在设备上可以开启
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled())
{
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
}
4. 开启/停止扫描蓝牙设备:
mBluetoothAdapter这里充当了开启/停止蓝牙扫描的功能。
private void scanLeDevice(final boolean enable)
{
if(enable){
//时间超出预定扫描时间后,停止扫描。
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
if(mScanning) {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
}
},SCAN_PERIOD);
mScanning = true;
mBluetoothAdapter.startLeScan(mLeScanCallback);
}else{
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
}
5.扫描的回调可以在这里连接设备
private BluetoothAdapter.LeScanCallback mLeScanCallback =new
BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord)
{
if(device.getName()!=null&&device.getName().equals(bleName)){
connect(device);
}
Log.d("scanResult","扫描到了一个BLE设备"+device.getName());
runOnUiThread(new Runnable() {
@Override
public void run(){
Toast.makeText(MainActivity.this,"扫描到"+device.getName(),Toast.LENGTH_SHORT).show();
}
});
}
};
6.我们在这里看一下
mGattCallback
的代码。这也是BLE蓝牙开发的重要核心。
连接成功时,发现服务,写入数据....,都会回调
mGattCallback
的相应方法。
private BluetoothGattCallback mGattCallback= new BluetoothGattCallback() {
// 连接状态改变的回调
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState) {
};
// 发现服务回调
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
};
@Override
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
// 由mBluetoothGatt.readRemoteRssi()调用得到,可不停刷新rssi信号强度
}
// 写描述信息回调
@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor
descriptor, int status) {
};
// 写操作回调
@Override
public void onCharacteristicWrite(BluetoothGatt gatt,BluetoothGattCharacteristic
characteristic, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
}
};
// 读操作回调
@Override
public void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic
characteristic, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
}
}
// 数据改变回调(接收BLE设备发送的数据)
@Override
public void onCharacteristicChanged(BluetoothGatt gatt,BluetoothGattCharacteristic
characteristic) {
};
};
}
7.连接设备
这里我们首先停止扫描蓝牙,然后用device.connectGatt()连接蓝牙设备。
private void connect(BluetoothDevice device)
{
mBluetoothAdapter.stopLeScan(mLeScanCallback);
mBluetoothGatt=device.connectGatt(MainActivity.this,false,mGattCallback);
mScanning=false;
}
8.扫描服务:我们可以在
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState) {
};
里先判断连接是否成功然后使用
mBluetoothGatt.discoverServices();
扫描设备的服务。这里给出一个例子代码:
public void onConnectionStateChange(final BluetoothGatt gatt, int status, int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {//当前蓝牙设备已经连接
intentAction = ACTION_GATT_CONNECTED;
mConnectionState = STATE_CONNECTED;//记录连接状态的
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this,gatt.getDevice().getName()+"设备已经连接",Toast.LENGTH_SHORT).show();
}
});
mBluetoothGatt.discoverServices();
Log.i("connected", "Connected to GATT server.");
Log.i("serviceFinding", "Attempting to start service discovery:" + mBluetoothGatt.discoverServices());
}
}
}
扫描到服务回调onServicesDiscovered(...)方法。
这里给出示例代码:
public void onServicesDiscovered(BluetoothGatt gatt, int status){
if (status == BluetoothGatt.GATT_SUCCESS) {
List<BluetoothGattService> serviceList= gatt.getServices();//获取服务列表
}
}
9.针对一个服务我们可以获取它的特征列表。然后对相应特征进行读写操作。
List<BluetoothGattCharacteristic> mlist=service.getCharacteristics();
10.读取特征数据
mBluetoothGatt.readCharacteristic(Characteristic a);
//使用mBluetoothGatt的readCharacteristic()进行读取即可。
11.写入特征数据
private void writeData(byte hexData[], BluetoothGattCharacteristic characteristic){
characteristic.setValue(hexData);//先设置值,再写入。数据是比特数组。
mBluetoothGatt.writeCharacteristic(characteristic);
}
12.注意要想写入之后收到BLE设备的通知应该设置接受通知。示例代码如下:
public void setCharacteristicNotification() {
BluetoothGattDescriptor descriptor = readCharacteristic.getDescriptors().get(0);
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
mBluetoothGatt.setCharacteristicNotification(readCharacteristic, true);
}
13.备注:
所有关于FTPClient的操作都要异步执行,否则就会出现错误。