安卓BLE开发个人总结

来源:互联网 发布:虚拟漫游软件 编辑:程序博客网 时间:2024/05/18 02:54

用于做些记录以及供大家参考,有什么问题欢迎指出

  • BLE简介
  • 开发步骤
  • 6.0以上系统所需的特殊权限
  • 遇到的一些问题和解决方法

BLE简介

  • BLE(Bluetooth Low Energy),中文名称蓝牙低能耗,是蓝牙4.0以上的核心Profile,因其快速搜索、快速连接,以及超低功耗保持连接和数据通信的功能特点而被普遍应用于穿戴设备。Android4.3以上才支持BLE相关API,故欲调试本文中的代码,请将最低sdk版本设置为18或以上。
    sdk里相关操作方法都在bluetooth目录下:
    ble相关类

开发步骤

1、权限声明:
在AndroidManifest.xml中声明所需权限,6.0以上系统还需要动态请求一个特殊权限,这个后面会说到

BluetoothManager manager = (BluetoothManager)mActivity.getSystemService(Context.BLUETOOTH_SERVICE);mBluetoothAdapter = manager.getAdapter();if(mBluetoothAdapter == null){    showToast("当前蓝牙不可用");}else if(!mBluetoothAdapter.isEnabled()){    /**开启蓝牙**/    Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);    mActivity.startActivityForResult(enableIntent, REQUEST_TAG);}

2、蓝牙状态检查
首先要检查手机支不支持ble通信,如果支持,则进行蓝牙状态检查,若蓝牙未开启,则可执行蓝牙开启请求

BluetoothManager manager = (BluetoothManager)mActivity.getSystemService(Context.BLUETOOTH_SERVICE);mBluetoothAdapter = manager.getAdapter();if(mBluetoothAdapter == null){    showToast("当前蓝牙不可用");}else if(!mBluetoothAdapter.isEnabled()){    /**开启蓝牙**/    Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);    mActivity.startActivityForResult(enableIntent, REQUEST_TAG);}

3、设备搜索
设备搜索中加入蓝牙芯片厂商提供的UUID标识会提高处理效率,在搜到设备时会过滤掉不符合要求的蓝牙设备:

mBluetoothAdapter.startLeScan(new UUID[]{UUID.fromString(Constans.UUID.DISCOVERY)}, scanCallback); /*设备扫描回调*/ private BluetoothAdapter.LeScanCallback scanCallback =          new BluetoothAdapter.LeScanCallback(){               @Override               public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {                   /*发送设备发现广播*/                   broadcastDevices(device);                   isScaning = false;                   mBluetoothAdapter.stopLeScan(this);              }    };

4、设备连接
在搜到设备并确认符合要求时,则进行设备连接,如果要直接通过mac地址连接,mac地址必须大写,如00:11:22:33:AA:BB,当adapter确认设备可用时可进行连接。连接成功后会进入写好的回调接口,接下来就是服务获取了。

/*** 设备连接*/public void connectDevice(BluetoothDevice device){   if(mBluetoothGatt != null){       mBluetoothGatt.close();   }   final BluetoothDevice thisDevice = mBluetoothAdapter.getRemoteDevice(device.getAddress());   if (thisDevice == null) {       mLog.LogD("设备信息", "Device not found.  Unable to connect.");       return;   }   /**这里传false,则会在设备可用时再进行连接而不是直接进行连接**/   mBluetoothGatt = thisDevice.connectGatt(mActivity, false, callback);}/*** 连接状态的回调**/private BluetoothGattCallback callback = new BluetoothGattCallback() {      @Override          public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {          super.onConnectionStateChange(gatt, status, newState);          switch (newState){              case BluetoothAdapter.STATE_DISCONNECTED:                  showToast("连接已断开");                  mBluetoothGatt.close();                  mBluetoothGatt = null;                  break;              case BluetoothAdapter.STATE_CONNECTED:                  mBluetoothGatt.discoverServices();                  break;          }      }}

5、服务获取和数据监听开启
搜索成功后,就可以遍历获取到的服务集了,当遍历到UUID和厂家提供的READ_UUID一致时,我们需要对它进行监听注册。值得一提的是,光设置setCharacteristicNotification(characteristic, true)是没用的,需要获取到BluetoothGattCharacteristic对象中符合要求的BluetoothGattDescriptor对象,通过该对象向设备写入{0x01, 0x00},设备才会向手机发送数据并被我们监听到。设备发过来的消息可以在onCharacteristicChanged()中获取

@Overridepublic void onServicesDiscovered(BluetoothGatt gatt, int status) {    if (status == BluetoothGatt.GATT_SUCCESS) {        getServices();    } else {        showToast("操作失败,请稍后再试");        mLog.LogD("服务获取失败", "onServicesDiscovered received: " + status);    }} /** * 开启数据监听 */ private void beginListen(){     BluetoothGattCharacteristic characteristic = null;     out:for(BluetoothGattService service : mBluetoothLeServices) {         List<BluetoothGattCharacteristic> characteristics = service.getCharacteristics();         for (int i = 0; i < characteristics.size(); i++) {             characteristic = characteristics.get(i);             if (characteristic.getUuid().toString().equalsIgnoreCase(Constans.UUID.READ)) {                 setCharacteristicNotification(characteristic, true);                 break out;             }         }     } }/***设置通知机制**/public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic,                                              boolean enabled) {        if (mBluetoothAdapter == null || mBluetoothGatt == null) {            mLog.LogD("BluetoothAdapter", " not initialized");            return;        }        mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);        BluetoothGattDescriptor descriptor = characteristic.getDescriptor(                UUID.fromString(Constans.UUID.CLIENT_CHARACTERISTIC_CONFIG));        descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);        mBluetoothGatt.writeDescriptor(descriptor);    }  /**  *数据监听的回调方法  **/ @Override public void onCharacteristicChanged(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic) {      super.onCharacteristicChanged(gatt, characteristic);      mLog.LogD("onDescriptorRead读取到的信息", Tool.byteToHexString(descriptor.getValue()));  }

6、信息发送
这一步须在开启监听之后,否则本次数据发送的返回结果你就看不到了~~同样的,也是遍历服务集,获取到UUID符合要求的BluetoothGattCharacteristic对象,然后进行数据发送。数据发送结果会在onCharacteristicWrite查看。

/*** 信息发送*/private void senMsg() {   boolean sendSuccess = false;   if (mBluetoothGatt != null) {       BluetoothGattCharacteristic characteristic = null;       out: for (BluetoothGattService service : mBluetoothLeServices) {           List<BluetoothGattCharacteristic> characteristics = service.getCharacteristics();           for (int i = 0; i < characteristics.size(); i++) {               characteristic = characteristics.get(i);               if (characteristic.getUuid().equals(UUID.fromString(Constans.UUID.WRITE))) {                   characteristic.setValue(mBytes);                   boolean success = mBluetoothGatt.writeCharacteristic(characteristic);                   mLog.LogD("写入数据", Tool.byteToHexString(mBytes) + ";  长度为:" + mBytes.length + ";是否成功:" + success);                   sendSuccess = success;                   break out;               }           }       }   }   if (!sendSuccess){       handler.post(new Runnable() {           @Override           public void run() {               mActivity.showToast("操作失败,请稍后再试");           }       });   }}/***数据写入回调**/@Overridepublic void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {    super.onCharacteristicWrite(gatt, characteristic, status);    showToast(status == BluetoothGatt.GATT_SUCCESS ? "操作成功" : "操作失败");    mLog.LogD("信息发送", status == BluetoothGatt.GATT_SUCCESS ? "成功" : "失败:" + status);}

7、断开连接
如果公司只有一个调试设备且多个人一起调试,这一步不做的后果。。。

/***断开连接**/ private void disconnect(){    mBluetoothGatt.disconnect();    mBluetoothGatt.close();    mBluetoothGatt = null;}

6.0以上系统所需的特殊权限

当我同事告诉我他的手机用不了我的App时,我的内心已经有了一丝猜测,好在他也好说话,二话不说就把全新的edge7给我调试了(感人),然后发现在6.0以上的系统运行时还需要动态请求一个权限才能使用ble蓝牙操作,为什么要请求定位操作我也不太清楚,各位看官可以指点一下迷津:

/*** 6.0以上权限获取 */private void checkPermission(){    if (Build.VERSION.SDK_INT >= 23) {        int checkLocationPermission = ContextCompat.checkSelfPermission(mActivity, Manifest.permission.CALL_PHONE);        if(checkLocationPermission != PackageManager.PERMISSION_GRANTED){            ActivityCompat.requestPermissions(mActivity, new String[]{Manifest.permission.ACCESS_FINE_LOCATION                    , Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST);            return;        }else{            mTool.scanDevice(true);        }    } else {        mTool.scanDevice(true);    }}@Overridepublic void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {     switch (requestCode) {         case PERMISSION_REQUEST:             if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {                 mTool.scanDevice(true);             } else {                 showToast("操作被拒绝");             }             break;         default:             super.onRequestPermissionsResult(requestCode, permissions, grantResults);     } }

遇到的一些问题和解决方法

1、死活收不到数据
从搜索到连接到发数据都没出现什么问题,但到接收数据时,着实卡了我很久(怪自己没有好好看官方文档),厂家提供了搜索、读、写三个UUID,我一开始以为是通过readCharacteristic()方法读取数据,然后在onCharacteristicRead()中查看读取到的数据的,使用厂家提供的READ_UUID收不到任何数据。然后我以为是UUID的问题,于是遍历UUID,只要符合
(characteristic.getProperties() &BluetoothGattCharacteristic.PROPERTY_READ) == 0
的UUID我都会进行readCharacteristic()操作,然后发现数据是能读到了,但不论发什么,都只能收到一条一模一样的数据,然后我遍历了所有写的通道进行了写操作,数据是会变了,但却都是我发出去的数据。。。我想应该是我自己发的。之后才知道压根不是这样读数据的,正确的姿势已经在上面了。
2、数据监听成功但发送不成功
这个是刚注册了监听立马就发数据导致的,做个100毫秒的延时处理就好了。
3、数据接收有延时
讲道理BLE传输速率可以达到5.9kb/s,但我收到数据总是要50ms以上,也就19字节的数据而已。这个我还不知道什么原因。。。

4 0
原创粉丝点击