美文网首页简述
简述Android Bluetooth Low Energy

简述Android Bluetooth Low Energy

作者: 萌码象C | 来源:发表于2017-08-14 00:24 被阅读0次

    目录
    [TOC]

    Bluetooth Low Energy

    • 简介:
      • 与传统蓝牙相比,低功耗蓝牙的设计对电量消耗更低。
      • 只支持Android 4.3以上的系统版本,即 API Level>=18。

    蓝牙开发对象

    • BluetoothManager

      • 获取对象:

          BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        
      • 注意:BluetoothManager仅在Android4.3以上的系统版本支持,即 API Level>=18。

    • BluetoothAdapter

      • 获取对象:

          BluetoothAdapter mBluetoothAdapter = BluetoothManager.getAdapter();
          // 或者
          BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        
        • 注意:一个Android系统只有一个BluetoothAdapter。
      • 方法描述:

        • 蓝牙状态
          • isEnabled()
            • 判断系统蓝牙是否打开
          • disable()
            • 隐式关闭系统蓝牙
          • enable()
            • 隐式打开系统蓝牙
        • 蓝牙设备搜索
          • startDiscovery()/cancelDiscovery()
            • 开始/取消搜索设备(经典蓝牙 和 低功耗蓝牙)
            • 执行过程(耗时12秒):
              1. 系统发送 BluetoothAdapter.ACTIOIN_DISCOVERY_STARTED 的广播
              2. 搜索蓝牙设备...
              3. 只要找到一个设备就发送一个 BluetoothDevice.ACTION_FOUND 的广播
              4. 从广播接收器中就可以得到这个BluetoothDevice对象
              5. 系统发送 BluetoothAdapter.ACTION_FINISHED 的广播
          • startLeScan()/stopLeScan()
            • 开始/取消搜索设备(低功耗蓝牙)
            • 注意:
              • 在API Level-21以上被标记废弃使用
    • BluetoothLeScanner

      • 获取对象:

          BluetoothLeScanner mBluetoothLeScanner= BluetoothAdapter.getBluetoothLeScanner();
        
      • 方法描述:

        • startScan()/stopScan()
          • 开始/取消搜索设备(低功耗蓝牙)
          • 注意:
            • 在API Level-21以上使用
    • BluetoothDevice

      • 代表了一个远程的蓝牙设备, 通过这个类可以查询远程设备的物理地址, 名称, 连接状态等信息,
      • 获取对象:
        • 物理地址对应的Device:

            BluetoothAdapter.getRemoteDevice(address);
          
        • 已经配对的Device集合:

            BluetoothAdapter.getBoundedDevices();
          
        • 扫描结果回调中的Device:

            BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() {
                @Override
                public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
                }
            };
          
    • BluetoothGatt

      • BluetoothGatt继承BluetoothProfile,
      • 通过BluetoothGatt可以连接设备(connect),发现服务(discoverServices),并把相应地属性返回到 BluetoothGattCallback,
      • 获取对象:
        • BluetoothGattCallback回调方法中获取。
    • BluetoothProfile

      • 一个通用的规范,按照这个规范来收发数据。
    • 连接成功后,我们首先需要获得服务,然后是该服务所包含的特征,最后是特征的描述符。

    • 服务(Service):

      • BluetoothGattService
        • 一个 Service 可以包含多个 Characteristic,
        • 获取对象:
          • 通过指定的 UUID 从 BluetoothGatt 实例中获得:

              BluetoothGattService service = BluetoothGatt.getService(UUID.fromString(BLE_SERVICE));
            
    • 特征(Characteristic):

      • BluetoothGattCharacteristic
        • 一个 Characteristic 包含一个 Value 和多个 Descriptor,
        • 相当于一个数据类型,它包括一个value和0~n个value的描述(Descriptor),
        • 获取对象:
          • 通过指定的 UUID 从 BluetoothGattService 中得到:

              BluetoothGattCharacteristic characteristic = BluetoothGattService.getCharacteristic(UUID.fromString(BLE_CHARACTERISTIC))
            
    • 描述符(Descriptor):

      • BluetoothGattDescriptor
        • 一个 Descriptor 包含一个 Value,
        • 对 Characteristic 的描述,包括范围、计量单位等,
        • 获取对象:
          • 通过指定的 UUID 从 BluetoothGattCharacteristic 对象中获得:

              List<BluetoothGattDescriptor> descriptorList = BluetoothGattCharacteristic.getDescriptors();
              // 或者
              BluetoothGattDescriptor descriptor = BluetoothGattCharacteristic.getDescriptor(UUID.fromString("BLE_DESCRIPTOR"));
            

    低功耗蓝牙开发基本流程

    • 申请权限

      • 基础权限:

          <!-- 执行所有的蓝牙通信,如请求连接,接受连接和传输数据 -->
          <uses-permission android:name="android.permission.BLUETOOTH"/>
          <!-- 初始化设备发现或者操纵蓝牙设置 -->
          <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
        
      • 注意:

        • 如果应用仅支持低功耗蓝牙
          • 在 AndroidManifest.xml 添加以下声明:

              <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
            
          • 动态判断:

              if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
                  Toast.makeText(this, "该设备不支持低功耗蓝牙", Toast.LENGTH_SHORT).show();
              }  
            
        • 在 Android 6.0 及以上的系统版本,需动态申请位置权限。
          如果应用没有位置权限,蓝牙扫描功能不能使用(其它蓝牙操作例如连接蓝牙设备和写入数据不受影响)。
          • 在 AndroidManifest.xml 添加以下声明:

            <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
            或
            <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
            
          • 动态申请:

            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}, PERMISSION_REQUEST_COARSE_LOCATION);
                }
            }
            
            @Override
            public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
                switch (requestCode) {
                    case PERMISSION_REQUEST_COARSE_LOCATION:
                        if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                            // 权限申请成功,处理业务逻辑
                        }
                        break;
                    default:
                        break;
                }
            }
            
    • 是否支持蓝牙

        BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        
        if (bluetoothManager.getAdapter() == null) {
            Toast.makeText(Context, "没有发现蓝牙模块", Toast.LENGTH_SHORT).show();
        }
      
    • 开启/关闭蓝牙

      • 检查蓝牙是否开启

          BluetoothAdapter.isEnabled();
        
      • 开启

        • 隐式开启

            BluetoothAdapter.enable();
          
          • 注意:
            • 需要注册权限:

                <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
              
            • 在 Android 6.0 及以上的系统版本,隐式开启依旧会提示用户。

        • 显示开启

            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUESTCODE_BLUETOOTH);
          
          • 确认结果:

            • 方法一:注册广播

                IntentFilter intentFilter = new IntentFilter();  
                intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);//蓝牙状态
                intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);// 扫描开始
                intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);// 扫描结束
                registerReceiver(new BluetoothReceiver(), intentFilter);
              
                private class BluetoothReceiver extends BroadcastReceiver {
              
                    @Override
                    public void onReceive(Context context, Intent intent) {
              
                        String action = intent.getAction();
                        if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
                            switch (BluetoothAdapter.getDefaultAdapter().getState()) {
                                case BluetoothAdapter.STATE_ON:// 打开
                                    break;
                                case BluetoothAdapter.STATE_OFF:// 关闭
                                    break;
                                case BluetoothAdapter.STATE_TURNING_OFF:// 蓝牙处于关闭过程中
                                    break;
                                case BluetoothAdapter.STATE_TURNING_ON:// 蓝牙处于打开过程中
                                    break;
                                default:
                                    break;
                            }
                        }
                    }
                }
              
            • 方法二:重写onActivityResult()

                @Override
                protected void onActivityResult(int requestCode, int resultCode, Intent data) {
                    super.onActivityResult(requestCode, resultCode, data);
                    if (resultCode == RESULT_OK) {//蓝牙开启成功
                        switch (requestCode) {
                            case REQUESTCODE_BLUETOOTH:
                                break;
                            default:
                                break;
                        }
                    } else if (resultCode == RESULT_CANCELED) {//蓝牙开启失败
                        ToastUtils.showShort("蓝牙开启失败,请手动开启蓝牙");
                    }
                }
              
          • 前往系统设置界面

              startActivity(new Intent(Settings.ACTION_BLUETOOTH_SETTINGS));
            
      • 关闭

        • 隐式关闭

            BluetoothAdapter.disable();
          
        • 前往系统设置界面

            startActivity(new Intent(Settings.ACTION_BLUETOOTH_SETTINGS));
          
    • 扫描蓝牙设备

      • 开启/关闭扫描设备
        • 开启

          • 扫描全部蓝牙设备

              BluetoothAdapter.startLeScan(BluetoothAdapter.LeScanCallback callback)
            
          • 只扫描含有特定 UUID Service 的蓝牙设备

              BluetoothAdapter.startLeScan(UUID[] serviceUuids, BluetoothAdapter.LeScanCallback callback)
            
        • 关闭

            BluetoothAdapter.stopLeScan(BluetoothAdapter.LeScanCallback callback)
          
    • 连接设备

        BluetoothGatt BluetoothDevice.connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback) {}
      
      • autoConnect:表示是否需要自动连接。
        • 设置为 true 表示如果设备断开了,会不断的尝试自动连接。
        • 设置为 false 表示只进行一次连接尝试。
      • BluetoothGattCallback:表示连接后进行的一系列操作的回调,共计9个回调方法,以下列举常用的5个。
        • 连接状态变化

            void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {}
          
        • 执行BluetoothGatt.discoverServices();后回调,发现服务

            void onServicesDiscovered(BluetoothGatt gatt, int status) {}
          
        • 执行BluetoothGatt.writeCharacteristic();后回调,写入数据执行结果

            void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {}
          
        • 执行BluetoothGatt.setCharacteristicNotification();后回调,Characteristic值发生改变

            void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {}
          
        • 执行BluetoothGatt.writeDescriptor();后回调

            void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {}
          
    • 发现服务

      • 在onConnectionStateChange()中,判断连接状态,连接成功,搜索连接设备所支持的service

          @Override
          public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
              super.onConnectionStateChange(gatt, status, newState);
        
              if (newState == BluetoothGatt.STATE_CONNECTED) {//连接成功
        
                  gatt.discoverServices();//搜索连接设备所支持的service
        
              } else if (newState == BluetoothGatt.STATE_DISCONNECTED) {//连接断开
              }
          }
        
      • discoverServices()被执行后,在onServicesDiscovered()中,获取指定UUID Service,存下BluetoothGatt对象

          @Override
          public void onServicesDiscovered(BluetoothGatt gatt, int status) {
              super.onServicesDiscovered(gatt, status);
        
              BluetoothGattService service = gatt.getService(UUID.fromString(BLE_SERVICE));
        
              if (service != null) {
                  mBluetoothGatt = gatt;
              }
          }
        
    • 读写数据

      • 写:
        • 获取指定 UUID Serivce 的 BluetoothGattService 对象,

        • 从而得到指定 UUID Characteristic 的 BluetoothGattCharacteristic 对象,将数据设置进去,

        • 最后用 BluetoothGatt 对象向蓝牙设备写入数据

            public void writeCharacteristic() {
                
                byte[] data = {0x00};//封包数据,根据硬件协议填写
                
                BluetoothGattCharacteristic characteristic = mBluetoothGatt.getService(UUID.fromString(BLE_SERVICE)).getCharacteristic(UUID.fromString(BLE_WRITE));
                characteristic.setValue(data);//设置数据
          
                mBluetoothGatt.writeCharacteristic(characteristic);//写入设备
            }
          
      • 读:
        • writeCharacteristic() 调用后,

        • 会走 onCharacteristicChanged() 回调,

        • BluetoothGattCharacteristic 对象中获取蓝牙设备传回的数据,

        • 通过蓝牙硬件协议判断并做出相应处理。

            @Override
            public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
                super.onCharacteristicChanged(gatt, characteristic);
                
                byte[] value = characteristic.getValue();
          
                switch (value[0]) {//判断协议,对应处理
                    case 0x00:
                        break;
                    default:
                        break;
                }
            }
          
    • 断开连接

        BluetoothGatt.disconnect();
        BluetoothGatt.close();

    相关文章

      网友评论

        本文标题:简述Android Bluetooth Low Energy

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