Home Articles

android到android的通信结束了

Asked
Viewed 1337 times
0

我目前正在开发一个项目,通过蓝牙LE从android到android交换小值 . 我使用nexus9作为android外设,Moto G作为中心 . 完美的中央扫描外围设备和外围设备的服务正在增加,现在我需要在外设上写入特性,然后外围设备会将其识别到中央但发生的事情是外设发送某些字节到中央而不是读取中心特性,即使这个中心工作正常ios外围 . 这是我的android中心代码

private void startScanning() {
        if ((btAdapter != null) && (!isScanning)) {
            if (scanner == null) {
                Log.d(TAG, "scanner was null");
                scanner = btAdapter.getBluetoothLeScanner();
            }
            if (scanCallback == null)
                setScanCallback(null);

            scanner.startScan(createScanFilters(), createScanSettings(), scanCallback);
            isScanning = true;
            Log.d(TAG, "in startScanning");
            //Toast.makeText(context, context.getString(R.string.scan_started), Toast.LENGTH_SHORT).show();
        }
    }


public void setScanCallback(final ScanCallback callback) {

    scanCallback = new ScanCallback() {
        @Override
        public void onScanResult(int callbackType, ScanResult scanResult) {
            super.onScanResult(callbackType, scanResult);
            Log.d(TAG, scanResult.getDevice().getName() + " ");

            deviceNames.add(scanResult.getDevice().getName());
            deviceRSSIs.add(String.valueOf(scanResult.getRssi()));
            adapter.notifyDataSetChanged();

            scanResult.getDevice().connectGatt(context, false, new BluetoothGattCallback() {


                @Override
                public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
                    super.onConnectionStateChange(gatt, status, newState);


                    Set<BluetoothGattCharacteristic> characteristicSet;

                    switch (newState) {
                        case BluetoothProfile.STATE_DISCONNECTING:

                            break;

                        case BluetoothProfile.STATE_DISCONNECTED:
                            Log.d(TAG, gatt.getDevice().getName() + " is disconnected");
                            //gatt.close();

                            break;

                        case BluetoothProfile.STATE_CONNECTED:
                            Log.d(TAG, gatt.getDevice().getName() + " is connected");
                            gatt.discoverServices();

                            break;

                    }
                }

                @Override
                public void onServicesDiscovered(BluetoothGatt gatt, int status) {
                    if (status == BluetoothGatt.GATT_SUCCESS) {
                        Log.d(TAG, "Discovered services central");
                        // TODO: Keep this here to examine characteristics
                        // eventually we should get rid of the discoverServices step
                        boolean foundService = false;
                        try {
                            List<BluetoothGattService> serviceList = gatt.getServices();
                            for (BluetoothGattService service : serviceList) {
                                if (service.getUuid().equals(serviceUUID)) {

                                    foundService = true;
                                    HashSet<BluetoothGattCharacteristic> characteristicSet = new HashSet<>();
                                    characteristicSet.addAll(service.getCharacteristics());
                                    discoveredCharacteristics.put(gatt.getDevice().getAddress(), characteristicSet);

                                    for (BluetoothGattCharacteristic characteristic : characteristicSet) {
                                        if (characteristic.getUuid().equals(characteristicUUID)) {
                                            characteristic.setValue(dataToSend.getBytes());
                                            boolean chr =  gatt.writeCharacteristic(characteristic);
                                            characteristic = gatt.getService(serviceUUID).getCharacteristic(characteristicUUID);
                                            gatt.setCharacteristicNotification(characteristic, true);
                                            BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CLIENT_CHARACTERISTIC_CONFIG);
                                            descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                                            boolean desc = gatt.writeDescriptor(descriptor);
                                            //    setIndictaionSubscription(gatt, characteristic, true);
                                        }

                                    }
                                }
                            }


                        } catch (Exception e) {
                            Log.d(TAG, "Exception analyzing discovered services " + e.getLocalizedMessage());
                            e.printStackTrace();
                        }
                        if (!foundService)
                            Log.d(TAG, "Could not discover chat service!");
                    } else
                        Log.d(TAG, "Discovered services appears unsuccessful with code " + status);
                    super.onServicesDiscovered(gatt, status);
                }

                @Override
                public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
                    Log.d(TAG, "onDescriptorWrite");
                }


                @Override
                public void onCharacteristicChanged(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
                    Log.d(TAG, "onCharacteristicChanged");
                    if (!characteristic.getValue().toString().isEmpty()) {
                        MainActivity.this.runOnUiThread(new Runnable() {

                            public void run() {
                                Toast.makeText(getBaseContext(), new String(characteristic.getValue()), Toast.LENGTH_LONG).show();
                                gatt.readRemoteRssi();

                            }
                        });
                    }

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

                    Log.d(TAG, "onCharacteristicWrite");
                    Exception exception = null;
                    if (status != BluetoothGatt.GATT_SUCCESS) {

                        String msg = "Write was not successful with code " + status;
                        Log.d(TAG, msg);
                        exception = new UnknownServiceException(msg);

                    }
                }


                @Override
                public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
                    Log.i("RSSIValue", gatt.getDevice().getName() + " " + String.valueOf(rssi) + " " + String.valueOf(status));
                    super.onReadRemoteRssi(gatt, rssi, status);
                }

            });


        }

    };

}

这是我的外围代码 .

private AdvertiseCallback mAdvCallback = new AdvertiseCallback() {
        @Override
        public void onStartSuccess(AdvertiseSettings settingsInEffect) {
            if (settingsInEffect != null) {
                Log.d(TAG, "Advertise success TxPowerLv="
                        + settingsInEffect.getTxPowerLevel()
                        + " mode=" + settingsInEffect.getMode());
            } else {
                Log.d(TAG, "Advertise success");
            }
        }

        @Override
        public void onStartFailure(int errorCode) {
            Log.d(TAG, "Advertising failed with code " + errorCode);
        }
    };


    private AdvertiseData createAdvData() {
        AdvertiseData.Builder dataBuilder = new AdvertiseData.Builder();
        dataBuilder.addServiceUuid(new ParcelUuid(serviceUUID));
        dataBuilder.setIncludeTxPowerLevel(false);
        dataBuilder.setIncludeDeviceName(true);
//        builder.setManufacturerData(0x1234578, manufacturerData);
        return dataBuilder.build();
    }

    private AdvertiseSettings createAdvSettings() {
        AdvertiseSettings.Builder builder = new AdvertiseSettings.Builder();
        builder.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH);
        builder.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_BALANCED);
        builder.setConnectable(false);
        return builder.build();
    }

    private void stopAdvertising() {
        if (isAdvertising) {
            gattServer.close();
            advertiser.stopAdvertising(mAdvCallback);
            isAdvertising = false;
        }
    }


    public void createMessage() {

        // Chop Message!  You can only advertise 20 bytes at a time through ble
        byte[] message = ("my text need to send").getBytes();
        mDataToSend = new ArrayList<>();
        dataToSendIndex = 0;

        for(int i=0;i<Math.ceil((float)message.length/(float)20);i++) {

            byte[] slice = new byte[20];

            for(int ii=0;ii<slice.length && i*20 + ii < message.length;ii++) {
                slice[ii] = message[i*20 + ii];
            }

            mDataToSend.add(slice);

        }

        // Start sending the message
        sendMessage();
    }

    public void sendMessage() {

        if(dataToSendIndex >= mDataToSend.size()) {  // If we have incremented through the message, the message is sent
            Log.d("auto", "PeripheralActivity > sendMessage() > Message Sent");
            // Done Sending!
            return;
        }

        // Set the value of the characteristic to the next data to send
        mCharacteristic.setValue(mDataToSend.get(dataToSendIndex));
        // Notify the subscriber you have changed the value
        gattServer.notifyCharacteristicChanged(btClient, mCharacteristic, true);

        // Increment index
        dataToSendIndex ++;
    }

    BluetoothGattServerCallback gattCallback = new BluetoothGattServerCallback() {
        @Override
        public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
            super.onConnectionStateChange(device, status, newState);
        }

//        @Override
//        public void onServiceAdded(int status, BluetoothGattService service) {
//            super.onServiceAdded(status, service);
//        }

        @Override
        public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {
            super.onCharacteristicReadRequest(device, requestId, offset, characteristic);
            Log.d(TAG, characteristic.toString());
        }

        @Override
        public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
            super.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value);
            btClient = device;

            gattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value);
            createMessage();

        }

        @Override
        public void onDescriptorReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattDescriptor descriptor) {
            super.onDescriptorReadRequest(device, requestId, offset, descriptor);
        }

        @Override
        public void onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
            super.onDescriptorWriteRequest(device, requestId, descriptor, preparedWrite, responseNeeded, offset, value);

            btClient = device;

            gattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
            createMessage();
        }

//        @Override
//        public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) {
//            super.onExecuteWrite(device, requestId, execute);
//        }

        @Override
        public void onNotificationSent(BluetoothDevice device, int status) {
            super.onNotificationSent(device, status);
            sendMessage();
        }

//        @Override
//        public void onMtuChanged(BluetoothDevice device, int mtu) {
//            super.onMtuChanged(device, mtu);
//        }
    };
    private void startGattServer() {
        // Create GATT Service
        service = new BluetoothGattService(serviceUUID , BluetoothGattService.SERVICE_TYPE_PRIMARY);


        // Create Config Descriptor
        BluetoothGattDescriptor dataDescriptor = new BluetoothGattDescriptor(CLIENT_CHARACTERISTIC_CONFIG, BluetoothGattDescriptor.PERMISSION_WRITE | BluetoothGattDescriptor.PERMISSION_READ);


        // Add Descriptor
        mCharacteristic.addDescriptor(dataDescriptor);
                        BluetoothGattDescriptor.PERMISSION_WRITE | BluetoothGattCharacteristic.PERMISSION_READ);

        // Add Characteristic
        service.addCharacteristic(mCharacteristic);

        gattServer = manager.openGattServer(this, gattCallback);
        gattServer.addService(service);


    }

P.S:可能存在一个我无法察觉的基本错误,任何帮助都会非常明显:)

1 Answer

  • 0

    我知道这是一个相当“老”的问题,但也许这个答案可以帮助其他人:

    当您与GATT服务器通信时,尽量不要堆叠查询,但总是读/写一次并等待答案,否则服务器可能会忽略您发送给它的所有内容 .

    所以在你的情况下它会

    boolean chr =  gatt.writeCharacteristic(characteristic);
    
    • 等待 onCharacteristicWrite()

    然后做

    descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
    boolean desc = gatt.writeDescriptor(descriptor);
    gatt.setCharacteristicNotification(characteristic, true);`
    
    • 等待 onDescriptorWrite()

    这样做有点麻烦,但发送多个查询会更加可靠 . 希望有所帮助 .

Related