美文网首页
Android 蓝牙(BLE)通信简介

Android 蓝牙(BLE)通信简介

作者: Carrot_123 | 来源:发表于2019-02-28 16:57 被阅读0次

权限申请

在AndroidManifest.xml中加入:

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

在代码中动态申请权限,其中REQUEST_PERMISSION_ACCESS_LOCATION 为自定义int常量,

 private void requestPermission() {
        if (Build.VERSION.SDK_INT >= 23) {
            int checkAccessFinePermission = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
            if (checkAccessFinePermission != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                        REQUEST_PERMISSION_ACCESS_LOCATION);
                LogTool.e(TAG, "没有权限,请求权限");
                return;
            }
            LogTool.i(TAG, "已有定位权限");
        }
        //做下面该做的事
    }

重写onRequestPermissionsResult,验证获取权限结果,如下图:

 @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case REQUEST_PERMISSION_ACCESS_LOCATION:
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                } else {
                    Toast.makeText(this,"获取权限失败",Toast.LENGTH_SHORT).show();
                }
                break;
        }
    }

使能手机蓝牙

在使用蓝牙之前需要检查手机蓝牙是否开启,若未开启,需要提示将蓝牙开启

//获取蓝牙适配器实例
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
//若蓝牙未开启,则开启蓝牙
if (! bluetoothAdapter.isEnabled()) {
        //使能蓝牙
        bluetoothAdapter.enable();
}

扫描蓝牙设备

 private void startScan() {
        //SCAN_INTERVEL = 5000 毫秒后停止扫描
        postDelayed(new Runnable() {
            @Override
            public void run() {
                bluetoothAdapter.stopLeScan(leScanCallback);
            }
        }, SCAN_INTERVEL);
        //开始扫描
        bluetoothAdapter.startLeScan(leScanCallback);
    }

其中leScanCallback为扫描回调方法,定义如下:

final BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() {
        @Override
        public void onLeScan(BluetoothDevice bluetoothDevice, int i, byte[] bytes) {
            //这里当扫描到的设备,设备名不为null,就通过logi输出设备名和MAC地址。
            //这里也可以添加其他筛选条件,如特定设备名、或设备列表中是否已有。
            if(bluetoothDevice.getName() != null) {
            //这里可以将设备添加到列表中,并通过ListView显示出来
                 Log.i(TAG, "onLeScan: " + bluetoothDevice.getName() + " : " + bluetoothDevice.getAddress());
            }
        }
    };

连接扫描到的蓝牙设备

//MACADDR 为要连接的设备MAC地址,可以通过设备的getAddress()方法获取
BluetoothDevice bluetoothDevice = bluetoothAdapter.getRemoteDevice(MACADDR);
BluetoothGatt bluetoothGatt;
if(bluetoothDevice != null)
{
       bluetoothGatt = bluetoothDevice.connectGatt(context,true,gattCallback);
 }
 else{
      LogTool.i(TAG, "onItemClick: 没有该设备");
 }

定义gattCallback,并重写一系列方法,这些方法会在连接过程中被调用,可以在这里做一些连接状态的处理:

 BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
        //连接状态发生改变时调用
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            if(status == BluetoothGatt.GATT_SUCCESS) {
              if (newState == BluetoothProfile.STATE_CONNECTED) {
                    //建立连接
              } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                    //连接断开
              }
          }
        }
         
        //发现服务
        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
            //这里可以通过发送广播,接收到相应广播后,对服务做相应处理。
            LogTool.i(TAG, "onServicesDiscovered:status:" + status);
          } else {
            LogTool.w(TAG, "onServicesDiscovered received: " + status);
            System.out.println("onServicesDiscovered received: " + status);
          }
        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
           //读取到值,在这里读数据
          if (status == BluetoothGatt.GATT_SUCCESS) {
            //数据处理
          }
        }

        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            switch(status) {
            case BluetoothGatt.GATT_SUCCESS:
                LogTool.i(TAG, "write data success");
                break;
            case BluetoothGatt.GATT_FAILURE:
                LogTool.i(TAG, "write again");
                gatt.writeCharacteristic(characteristic);
                break;
            case BluetoothGatt.GATT_WRITE_NOT_PERMITTED:
                LogTool.i(TAG, "write not permitted");
                break;
        }

        super.onCharacteristicWrite(gatt,characteristic,status);
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            super.onCharacteristicChanged(gatt, characteristic);
        }
    };

服务和特征值获取

这里获取是继上述的回调函数onServicesDiscovered,在广播接受者中获取相应的服务和特征值:

        //写数据的服务和characteristic
        BluetoothGattService bluetoothGattService;
        BluetoothGattCharacteristic characteristicRead;
        BluetoothGattCharacteristic characteristicWrite;
        //获取服务
        bluetoothGattService = bluetoothGatt.getService(UUID.fromString("0000ffe0-0000-1000-8000-00805f9b34fb"));
        //获取读特征值
        characteristicRead = bluetoothGattService.getCharacteristic(UUID.fromString("0000ffe7-0000-1000-8000-00805f9b34fb"));
        //获取写特征值
        characteristicWrite = bluetoothGattService.getCharacteristic(UUID.fromString("0000ffe6-0000-1000-8000-00805f9b34fb"));
        //使能接收数据通知
        List<BluetoothGattDescriptor> descriptors = characteristicRead.getDescriptors();
        for (BluetoothGattDescriptor bgp : descriptors) {
            LogTool.i(TAG, "setCharacteristicNotification: " + bgp);
            bgp.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
            bluetoothGatt.writeDescriptor(bgp);
        }

数据的收发

接收数据

在上述的回调过程中,若特征值为读特征值,则此时可以从特征值中读取设备发送来的数据:

//这里例子里读特征值的UUID为0000ffe7-0000-1000-8000-00805f9b34fb,在实际应用中视实际情况而定。
if ( characteristic.getUuid().toString().equals("0000ffe7-0000-1000-8000-00805f9b34fb")){
            // For all other profiles, writes the data formatted in HEX.对于所有的文件,写入十六进制格式的文件
            //这里读取到数据,读取的数据为byte数组
            final byte[] data = characteristic.getValue();
            LogTool.i(TAG, "broadcastUpdate: data length = " + data.length);
        }

发送数据

//为写特征值设置要发送的数据,datas为byte数组
characteristicWrite.setValue(datas);
//gatt发送数据
bluetoothGatt.writeCharacteristic(characteristicWrite);

小结

BLE的使用主要难点在建立连接部分,需要在实际编程中理解连接过程以及相应
BluetoothGattCallback 回调调用过程。BluetoothGattCallback回调函数中不做实际的数据的处理,一般通过发送广播,在广播接受者中处理相应的过程和数据。

如果对您有所帮助请给在下点个赞

相关文章

网友评论

      本文标题:Android 蓝牙(BLE)通信简介

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