BLE使用

作者: 浅忆莹 | 来源:发表于2017-04-20 11:12 被阅读0次

    一、BLE概述

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

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

    二、BLE的使用

    1.权限

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

    除了蓝牙权限外,如果需要BLE feature则还需要声明uses-feature:

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

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

    if(!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {

    Message msg = Message.obtain();

    msg.what=MSG_WHAT_NO_SUPPORT_BLE;

    handler.sendMessage(msg);

    return false;

    }

    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) {

    Message msg = Message.obtain();

    msg.what=MSG_WHAT_NO_SUPPORT_BL;

    handler.sendMessage(msg);

    return false;

    }

    //打开蓝牙

    if(!mBluetoothAdapter.isEnabled()) {

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

    Message msg = Message.obtain();

    msg.what=MSG_WHAT_OPEN_BL;

    handler.sendMessage(msg);

    return false;

    }

    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;

    }

    相关文章

      网友评论

          本文标题:BLE使用

          本文链接:https://www.haomeiwen.com/subject/uvhzettx.html