Android-BLE蓝牙开发学习记录

Android开发并非我擅长,最近刚好又做回蓝牙业务了,iOS搞完了看了下Android的,似乎区别不大,唯一比iOS多了一个descriptor,那就顺便把Android蓝牙也搞搞吧,本文仅做学习记录完成过程以及中途遇到的坑。代码是否规范不重要哈!

1.申请权限

首先在第一步我就遇到了坑,Android蓝牙开发需要申请地理位置权限,位置权限是敏感权限,高版本Android需要动态申请,最开始我只在AndroidManifest添加了权限申请,结果就是不管用旧的API还是最新的API扫描,都不走扫描结果回调!注意避坑!!!
AndroidManifest中申请以下权限

    
    

    
    
    

然后在代码中动态申请,这里写一个requestPermission方法申请

 private void requestPermission() {
        //动态申请
        if (Build.VERSION.SDK_INT < 23) {
            return;
        }
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
        }
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
        }
    }

2.初始化蓝牙

  private void initBluetooth() {
        mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = mBluetoothManager.getAdapter();
        mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
        if (mBluetoothAdapter == null) {
            Log.d(TAG, "蓝牙不支持");
        } else {
            int status = mBluetoothAdapter.getState();
            if (status == BluetoothAdapter.STATE_OFF) {
                mBluetoothAdapter.enable();
            }else {
                Log.d(TAG, "蓝牙可用");
            }
        }
    }

3.开始扫描

扫描的方式可以用BluetoothAdapter.startLeScan扫描,但谷歌已经不建议用该方法扫描了,那就用最新的BluetoothLeScanner的方式扫描吧,在需要扫描的地方添加下面的代码,扫描可以根据服务UUID扫描固定一类蓝牙设备,也可以不过滤扫描所有设备,我这里根据服务UUID过滤(Android除了UUID过滤扫描,还有其他的,比如name等,没仔细研究,iOS过滤条件目前就只有UUID)

        List bleScanFilters = new ArrayList<>();
        bleScanFilters.add(new ScanFilter.Builder().setServiceUuid(ParcelUuid.fromString("你的蓝牙设备UUID")).build());
        ScanSettings scanSetting = new ScanSettings.Builder().setScanMode(SCAN_MODE_LOW_LATENCY).setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES).setMatchMode(ScanSettings.MATCH_MODE_STICKY).build();
        mBluetoothLeScanner.startScan(bleScanFilters, scanSetting, callback);
        Log.d(TAG, "开始扫描");

4.扫描回调并连接

因为我是根据UUID只扫描一类设备,为了省电扫描到后我直接停止扫描,然后连接第一个扫描到的设备

final ScanCallback stopCallback = new ScanCallback() {
    };

final ScanCallback callback = new ScanCallback() {
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            super.onScanResult(callbackType, result);
            Log.d(TAG, "扫描到设备");
            BluetoothDevice btDevice = result.getDevice();
            mBluetoothLeScanner.stopScan(stopCallback);
            btDevice.connectGatt(MainActivity.this,true, connectCallBack);
        }

        @Override
        public void onBatchScanResults(List results) {
            super.onBatchScanResults(results);
            Log.d(TAG, "onBatchScanResults");
        }

        @Override
        public void onScanFailed(int errorCode) {
            super.onScanFailed(errorCode);
            Log.d(TAG, "扫描出错");
        }
    };

5.连接回调,发现服务,发现特征值,监听蓝牙发过来的数据,发送数据

    final  BluetoothGattCallback connectCallBack = new BluetoothGattCallback(){
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            super.onConnectionStateChange(gatt, status, newState);
            if (newState == BluetoothProfile.STATE_CONNECTED){
                Log.d(TAG, "连接成功");
                gatt.discoverServices();
            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            super.onServicesDiscovered(gatt, status);
            Log.d(TAG, "发现服务");
            BluetoothGattService service = gatt.getService(UUID.fromString("蓝牙设备服务uuid"));
            if (service != null){
                Log.d(TAG, "有服务");
                BluetoothGattCharacteristic notyChara = service.getCharacteristic(UUID.fromString("蓝牙设备可监听征值uuid"));
                if (notyChara != null){
                    Log.d(TAG, "有特征值");
                    boolean success = gatt.setCharacteristicNotification(notyChara,true);
                    Log.i("监听结果: "+success);
                    BluetoothGattDescriptor descriptor = notyChara.getDescriptor(UUID.fromString("蓝牙设备描述uuid"));
                    if (descriptor != null){
                        descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
                        gatt.writeDescriptor(descriptor);
                    }
                }
                //发送数据
                BluetoothGattCharacteristic writeChar = service.getCharacteristic(UUID.fromString("蓝牙设备可写特征值的UUID"));
                writeChar.setValue(TAG.getBytes());
                gatt.writeCharacteristic(writeChar);
            }
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            super.onCharacteristicChanged(gatt, characteristic);
            Log.d(TAG, "收到数据");
        }
    };

值得一提的是,为了省电,在不需要监听数据后需要设置停止监听,也可以用readCharacteristic读取单条数据

gatt.setCharacteristicNotification(chara,false);
descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);

在不需要蓝牙后应该调用gatt的disconnect方法断开设备,因为有最大连接数限制,还需要调用gatt的close方法释放当前连接个数计数。

你可能感兴趣的:(Android-BLE蓝牙开发学习记录)