美文网首页
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