BLE使用笔记

来源:互联网 发布:怎么卸载mac软件 编辑:程序博客网 时间:2024/06/05 16:42

一、BLE概述

Android4.3以上加入了BLE——低功耗蓝牙。

使用低功耗蓝牙可以包括多个Profile,一个Profile中有多个Service,一个Service中有多个Characteristic,一个Characteristic中包括一个value和多个Descriptor。

二、BLE的使用

1.权限

和经典蓝牙一样,应用使用蓝牙,需要声明BLUETOOTH权限,如果需要扫描设备或者操作蓝牙设置,则还需要BLUETOOTH_ADMIN权限:

<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>


<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>

required为true时,则应用只能在支持BLE的Android设备上安装运行;required为false时,Android设备均可正常安装运行,需要在代码运行时判断设备是否支持BLE:

//  判断当前手机是否支持BLE

if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {    Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();    finish();}

2.使用步骤

2.1 初始化 BluetoothAdapter,用来判断设备是否支持蓝牙并打开蓝牙

// Initializes a Bluetooth adapter.  For API level 18 and above, get a reference to

finalBluetoothManager bluetoothManager =

(BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);

mBluetoothAdapter= bluetoothManager.getAdapter();

// 判断是否支持蓝牙

if(mBluetoothAdapter==null) {

return false;

}

//打开蓝牙

if(!mBluetoothAdapter.isEnabled()) {

ILog.e("蓝牙未打开");

Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);

}

2.2 扫描蓝牙设备

扫描指定UUID的设备,mLeScanCallback为扫描的回调接口

mBluetoothAdapter.startLeScan(UUID[],mLeScanCallback);

//回调接口

BluetoothAdapter.LeScanCallbackmLeScanCallback=newBluetoothAdapter.LeScanCallback() {

// 开始扫描和停止扫描都会调用此方法

@Override

public voidonLeScan(finalBluetoothDevice device,intrssi,byte[] scanRecord) {

//可通过对比当前扫描到的device的name与自己想查找到的设备name对比,来获取想连接的device信息

}

2.3 停止扫描

可以在扫描到自己需要的蓝牙后,停止扫描,注意:停止扫描和开始扫描的回调接口是同一个

mBluetoothAdapter.stopLeScan(mLeScanCallback);

2.4 连接设备

if(mBluetoothAdapter!=null) {

//  获取BluetoothGatt,连接设备,设为自动连接(即第二个参数为true),可能会存在问题,

mBluetoothGatt= device.connectGatt(context,false,BluetoothGattCallback callback); 


//连接后的回调接口

BluetoothGattCallback callback=new BluetoothGattCallback() {

// 若连接状态发生改变

@Override

public void onConnectionStateChange(BluetoothGatt gatt,intstatus,intnewState) {

//  status 表示相应的连接或断开操作是否完成,而不是指连接状态

if(newState == BluetoothProfile.STATE_CONNECTED) {

ILog.e("Connected to GATT server.");

}else if(newState == BluetoothProfile.STATE_DISCONNECTED) {

ILog.e("Disconnected from GATT server.");

}

@Override

public voidonServicesDiscovered(BluetoothGatt gatt,intstatus) {

Message msg = Message.obtain();

if(status == BluetoothGatt.GATT_SUCCESS) {

ILog.e("扫描到服务");

//  获取我们需要的服务

BluetoothGattService service =mBluetoothGatt.getService(SERVICE_UUID);

//  我需要得到的应该是一个特定的BluetoothGattCharacteristic,根据uuid获取

BluetoothGattCharacteristic mCharacteristic = service.getCharacteristic(CHARAC_READ_UUID);

}

//  接收到信息

@Override

public voidonCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {

readInfo(characteristic);

}

//信息写入成功回调

@Override

public voidonCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,intstatus) {

if(status == BluetoothGatt.GATT_SUCCESS) {

ILog.e("回调:信息写入成功");

}else{

ILog.e("回调:信息写入失败");

}

2.5 连接到设备后的处理

1.获取指定服务及特征值:在连接设备的回调接口中有扫描到服务的方法,可以在此方法中获取指定的BluetoothGattService,并且可以在该服务中获取指定的BluetoothGattCharacteristic,如果需要开启notify功能(此功能可以不用主动轮询消息,而是被动接收设备发来消息)

//  给设备设置notifity功能

// 如果设备主动给手机发信息,则可以通过notification的方式,这种方式不用手机去轮询地读设备上的数据

mBluetoothGatt.setCharacteristicNotification(mCharacteristic,true);

BluetoothGattDescriptor descripter = mCharacteristic.getDescriptor(UUID.fromString(CLIENT_CHARACTERISTIC_CONFIG));

if(descripter !=null) {

descripter.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);

mBluetoothGatt.writeDescriptor(descripter);

}

2.读取消息:由于BLE是低功耗的,每次可传输的字节数为20,所以读取消息需要进行拼接,这就需要发送的内容加前后缀,来判断是否拼接成了完整的数据

3.发送消息:确定扫描到服务之后才能进行数据发送,并且需要分包发送,我是开启线程,在线程中进行数据的分包,将分包的数据加入队列中,并轮询队列,有数据就发送

/**

* BLE数据发送对象

*/

public class BleSenderextendsThread {

public static final intMAX_LENGTH=18;

private BlockingQueuedatas;

private BluetoothGattmBluetoothGatt;

private booleanisRunning;

private booleanisExit;

publicBleSender() {

isRunning=false;

}

public void init(BluetoothGatt mBluetoothGatt) {

clearAllData();

datas=new ArrayBlockingQueue(100);

this.mBluetoothGatt= mBluetoothGatt;

isExit=false;

if(!isRunning) {

start();

}

}

public void addData(BluetoothGattCharacteristic characteristic, String data) {

if(TextUtils.isEmpty(data))

return;

//分包

byte[] bytes = data.getBytes();

intlength = bytes.length;

intnumber = length %MAX_LENGTH==0? length /MAX_LENGTH: length /MAX_LENGTH+1;

for(inti =0; i < number; i++) {

byte[] range = Arrays.copyOfRange(bytes, i *18, i == number -1? length : (i +1) *MAX_LENGTH);

try{

//  将分包后的每个包的信息都填加到队列中

datas.put(newBLEData(characteristic, range));

}catch(InterruptedException e) {

e.printStackTrace();

}

}

}

private void sendData(BLEData data) {

BluetoothGattCharacteristic characteristic = data.characteristic;

byte[] bytes = data.data;

if(characteristic ==null|| bytes ==null)

return;

characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);

characteristic.setValue(bytes);

mBluetoothGatt.writeCharacteristic(characteristic);

}

public void clearAllData() {

if(datas!=null)

datas.clear();

}

@Override

public void run() {

super.run();

isRunning=true;

while(!isExit) {

try{

BLEData data =datas.take();

Thread.sleep(20);

sendData(data);

}catch(Exception e) {

e.printStackTrace();

}

public void stopSend() {

isExit=true;

}

0 0