Android蓝牙le gatt特征通知问题

时间:2015-06-27 11:01:25

标签: android bluetooth-lowenergy

我有一个带电池,健康温度计服务(HTS)的硬件。电池是读取特性,健康温度计是特征通知。首先,我针对HTS特征通知。我写了下面的代码。在服务发现之后,它来到enableNextSensor。它进入NOTIFY部分,但根本没有调用onCharacteristicChanged方法。我在这里做错了什么?

public class MainActivity extends ActionBarActivity implements BluetoothAdapter.LeScanCallback {
    private static final String TAG="MainActivity";

    private BluetoothAdapter mBluetoothAdapter;
    private BluetoothGatt mConnectedGatt;
    BluetoothDevice device;
    Handler mHandler;
    TextView hello;

    /* Client Configuration Descriptor */
    private static final UUID CONFIG_DESCRIPTOR = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");

    /** Health Thermometer service UUID */
    public final static UUID HT_SERVICE_UUID = UUID.fromString("00001809-0000-1000-8000-00805f9b34fb");
    /** Health Thermometer Measurement characteristic UUID */
    private static final UUID HT_MEASUREMENT_CHARACTERISTIC_UUID = UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb");


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mHandler = new Handler();
        hello = (TextView) findViewById(R.id.Temperature);
         /*
         * Bluetooth in Android 4.3 is accessed via the BluetoothManager, rather than
         * the old static BluetoothAdapter.getInstance()
         */
        BluetoothManager manager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
        mBluetoothAdapter = manager.getAdapter();
        startScan();

    }
    @Override
    protected void onResume() {
        super.onResume();
        /*
         * We need to enforce that Bluetooth is first enabled, and take the
         * user to settings to enable it if they have not done so.
         */
        if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
            //Bluetooth is disabled
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivity(enableBtIntent);
            finish();
            return;
        }

        /*
         * Check for Bluetooth LE Support.  In production, our manifest entry will keep this
         * from installing on these devices, but this will allow test devices or other
         * sideloads to report whether or not the feature exists.
         */
        if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
            Toast.makeText(this, "No LE Support.", Toast.LENGTH_SHORT).show();
            finish();
            return;
        }

        //Begin scanning for LE devices
        startScan();
    }

    private Runnable mStopRunnable = new Runnable() {
        @Override
        public void run() {
            stopScan();
        }
    };
    private Runnable mStartRunnable = new Runnable() {
        @Override
        public void run() {
            startScan();
        }
    };

    private void startScan() {
        //Scan for devices advertising the thermometer service
        mBluetoothAdapter.startLeScan(new UUID[] {HT_SERVICE_UUID}, this);
        mHandler.postDelayed(mStopRunnable, 5000);
    }

    private void stopScan() {
        mBluetoothAdapter.stopLeScan(this);
        mHandler.postDelayed(mStartRunnable, 2500);
    }

    @Override
    protected void onPause() {
        super.onPause();
        //Make sure dialog is hidden
        //mProgress.dismiss();
        //Cancel any scans in progress
        mHandler.removeCallbacks(mStopRunnable);
        mHandler.removeCallbacks(mStartRunnable);
        mBluetoothAdapter.stopLeScan(this);
    }

    @Override
    protected void onStop() {
        super.onStop();
        //Disconnect from any active tag connection
        if (mConnectedGatt != null) {
            mConnectedGatt.close();
            mConnectedGatt.disconnect();
            mConnectedGatt = null;
        }
    }

    private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
        /* State Machine Tracking */
        private int mState = 0;

        private void reset() { mState = 0; }

        private void advance() { mState++; }

        private String connectionState(int status) {
            switch (status) {
                case BluetoothProfile.STATE_CONNECTED:
                    return "Connected";
                case BluetoothProfile.STATE_DISCONNECTED:
                    return "Disconnected";
                case BluetoothProfile.STATE_CONNECTING:
                    return "Connecting";
                case BluetoothProfile.STATE_DISCONNECTING:
                    return "Disconnecting";
                default:
                    return String.valueOf(status);
            }
        }

        /*
         * Send an enable command to each sensor by writing a configuration
         * characteristic.  This is specific to the SensorTag to keep power
         * low by disabling sensors you aren't using.
         */
        private void enableNextSensor(BluetoothGatt gatt) {
            Log.i(TAG,"******************************************************************enableNextSensor");
            BluetoothGattCharacteristic characteristic;
            characteristic = gatt.getService(HT_SERVICE_UUID)
                            .getCharacteristic(HT_MEASUREMENT_CHARACTERISTIC_UUID);
            // Check characteristic property
            final int properties = characteristic.getProperties();

            if ((properties | BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
                Log.i(TAG,"**************************READ");
                // If there is an active notification on a characteristic, clear
                // it first so it doesn't update the data field on the user interface.
                /*if (mNotifyCharacteristic != null) {
                    mBluetoothLeService.setCharacteristicNotification(
                            mNotifyCharacteristic, false);
                    mNotifyCharacteristic = null;
                }
                mBluetoothLeService.readCharacteristic(characteristic);*/
            }
            if ((properties | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
                Log.i(TAG,"**************************NOTIFY");
               //mNotifyCharacteristic = characteristic;
                gatt.setCharacteristicNotification(
                        characteristic, true);

                BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
                        CONFIG_DESCRIPTOR);
                descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                gatt.writeDescriptor(descriptor);
            }

        }

        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            Log.i(TAG,"*********************************************************onCharacteristicWrite****************************");
            //After writing the enable flag, next we read the initial value
            readNextSensor(gatt);
        }

        /*
         * Read the data characteristic's value for each sensor explicitly
         */
        private void readNextSensor(BluetoothGatt gatt) {
            BluetoothGattCharacteristic characteristic;
            characteristic = gatt.getService(HT_SERVICE_UUID)
                            .getCharacteristic(HT_MEASUREMENT_CHARACTERISTIC_UUID);
            gatt.readCharacteristic(characteristic);
        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            //For each read, pass the data up to the UI thread to update the display
            if (HT_MEASUREMENT_CHARACTERISTIC_UUID.equals(characteristic.getUuid())) {
                //mHandler.sendMessage(Message.obtain(null, MSG_HUMIDITY, characteristic));
                //  updateTemperatureValue(characteristic);
                Log.i(TAG,"*********************************************************onCharacteristicRead****************************");
            }

            //After reading the initial value, next we enable notifications
            setNotifyNextSensor(gatt);
        }

        @Override
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            //Once notifications are enabled, we move to the next sensor and start over with enable
            advance();
            enableNextSensor(gatt);
        }

        private void setNotifyNextSensor(BluetoothGatt gatt) {
            BluetoothGattCharacteristic characteristic;
            characteristic = gatt.getService(HT_SERVICE_UUID)
                            .getCharacteristic(HT_MEASUREMENT_CHARACTERISTIC_UUID);
            Log.i(TAG,"******************setNotify");

            //Enable local notifications
            gatt.setCharacteristicNotification(characteristic, true);
            //Enabled remote notifications
            BluetoothGattDescriptor desc = characteristic.getDescriptor(CONFIG_DESCRIPTOR);
            desc.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
            gatt.writeDescriptor(desc);
        }

        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            Log.d(TAG, "******************************************************************Connetion State change =>" + status + "<= " + connectionState(newState));
            Log.d(TAG, "******************************************************************Gatt success =>" + BluetoothGatt.GATT_SUCCESS + "<= ");
            Log.d(TAG, "******************************************************************Connetion State connect =>" + BluetoothProfile.STATE_CONNECTED + "<= ");
            if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_CONNECTED) {
                //hello.setText("Device Connected");
                Log.d(TAG,"***********************GATT_SUCCESS");
                /*
                 * Once successfully connected, we must next discover all the services on the
                 * device before we can read and write their characteristics.
                 */
                gatt.discoverServices();

            } else if (status != BluetoothGatt.GATT_SUCCESS) {
                //hello.setText("Gatt Disconnected");
                /*
                 * If there is a failure at any stage, simply disconnect
                 */
                gatt.close();
                gatt.disconnect();
            }
        }
        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            Log.d(TAG, "Services Discovered: "+status);

            //hello.setText("Services Discovered");

            //if(status == BluetoothGatt.GATT_SUCCESS)
            //mHandler.sendMessage(Message.obtain(null, MSG_PROGRESS, "Enabling Sensors..."));
        /*
         * With services discovered, we are going to reset our state machine and start
         * working through the sensors we need to enable
         */
            reset();
            enableNextSensor(gatt);
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {

            Log.i(TAG,"*********************************************************onCharacteristicChanged**** I am here************************");
            /*
             * After notifications are enabled, all updates from the device on characteristic
             * value changes will be posted here.  Similar to read, we hand these up to the
             * UI thread to update the display.
             */
            if (HT_MEASUREMENT_CHARACTERISTIC_UUID.equals(characteristic.getUuid())) {
               // mHandler.sendMessage(Message.obtain(null, MSG_HUMIDITY, characteristic));
                Log.i(TAG,"*********************************************************onCharacteristicChanged****************************");
            }

        }
    };

    /* BluetoothAdapter.LeScanCallback */

    @Override
    public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
        Log.i(TAG, "New LE Device: " + device.getName() + " @ " + rssi);

        if(device.getName() !=  null && device.getName().equals("TC-Geetha")) {
            Log.i(TAG,"*******Inside connectGatt");
            /*
             * Make a connection with the device using the special LE-specific
             * connectGatt() method, passing in a callback for GATT events
             */

            mConnectedGatt = device.connectGatt(this, false, mGattCallback);
        }
        /*
         * We need to parse out of the AD structures from the scan record
         */
       /* List<AdRecord> records = AdRecord.parseScanRecord(scanRecord);
        if (records.size() == 0) {
            Log.i(TAG, "Scan Record Empty");
        } else {
            Log.i(TAG, "Scan Record: "
                    + TextUtils.join(",", records));
        }*/

        /*
         * Create a new beacon from the list of obtains AD structures
         * and pass it up to the main thread
         */
        //TemperatureBeacon beacon = new TemperatureBeacon(records, device.getAddress(), rssi);
        //mHandler.sendMessage(Message.obtain(null, 0, beacon));
    }



    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

以上代码记录:

35    testbluetooth I/MainActivity﹕ New LE Device: TC@ -54
345    testbluetooth I/MainActivity﹕ *******Inside connectGatt
345    testbluetooth D/BluetoothGatt﹕ connect() - device: E9:E3:17:4F:F5:2B, auto: false
345    testbluetooth D/BluetoothGatt﹕ registerApp()
345    testbluetooth D/BluetoothGatt﹕ registerApp() - UUID=ad176678-32ad-4212-9822-fd34b2005bcd
345    testbluetooth D/BluetoothGatt﹕ onClientRegistered() - status=0 clientIf=5
415    testbluetooth D/BluetoothGatt﹕ onClientConnectionState() - status=0 clientIf=5 device=E9:E3:17:4F:F5:2B
415    testbluetooth D/MainActivity﹕ ******************************************************************Connetion State change =>0<= Connected
415    testbluetooth D/MainActivity﹕ ******************************************************************Gatt success =>0<=
415    testbluetooth D/MainActivity﹕ ******************************************************************Connetion State connect =>2<=
415    testbluetooth D/MainActivity﹕ ***********************GATT_SUCCESS
415    testbluetooth D/BluetoothGatt﹕ discoverServices() - device: E9:E3:17:4F:F5:2B
646    testbluetooth D/BluetoothAdapter﹕ stopLeScan()
766    testbluetooth D/BluetoothGatt﹕ onGetService() - Device=E9:E3:17:4F:F5:2B UUID=00001800-0000-1000-8000-00805f9b34fb
766    testbluetooth D/BluetoothGatt﹕ onGetService() - Device=E9:E3:17:4F:F5:2B UUID=00001801-0000-1000-8000-00805f9b34fb
776    testbluetooth D/BluetoothGatt﹕ onGetService() - Device=E9:E3:17:4F:F5:2B UUID=00001809-0000-1000-8000-00805f9b34fb
776    testbluetooth D/BluetoothGatt﹕ onGetService() - Device=E9:E3:17:4F:F5:2B UUID=00001809-0000-1000-8000-00805f9b34fb
776    testbluetooth D/BluetoothGatt﹕ onGetService() - Device=E9:E3:17:4F:F5:2B UUID=0000180f-0000-1000-8000-00805f9b34fb
776    testbluetooth D/BluetoothGatt﹕ onGetService() - Device=E9:E3:17:4F:F5:2B UUID=0000180a-0000-1000-8000-00805f9b34fb
776    testbluetooth D/BluetoothGatt﹕ onGetCharacteristic() - Device=E9:E3:17:4F:F5:2B UUID=00002a00-0000-1000-8000-00805f9b34fb
776    testbluetooth D/BluetoothGatt﹕ onGetCharacteristic() - Device=E9:E3:17:4F:F5:2B UUID=00002a01-0000-1000-8000-00805f9b34fb
776    testbluetooth D/BluetoothGatt﹕ onGetCharacteristic() - Device=E9:E3:17:4F:F5:2B UUID=00002a04-0000-1000-8000-00805f9b34fb
786    testbluetooth D/BluetoothGatt﹕ onGetCharacteristic() - Device=E9:E3:17:4F:F5:2B UUID=00002a1c-0000-1000-8000-00805f9b34fb
786    testbluetooth D/BluetoothGatt﹕ onGetCharacteristic() - Device=E9:E3:17:4F:F5:2B UUID=00002a1c-0000-1000-8000-00805f9b34fb
796    testbluetooth D/BluetoothGatt﹕ onGetCharacteristic() - Device=E9:E3:17:4F:F5:2B UUID=00002a19-0000-1000-8000-00805f9b34fb
796    testbluetooth D/BluetoothGatt﹕ onGetCharacteristic() - Device=E9:E3:17:4F:F5:2B UUID=00002a29-0000-1000-8000-00805f9b34fb
796    testbluetooth D/BluetoothGatt﹕ onGetCharacteristic() - Device=E9:E3:17:4F:F5:2B UUID=00002a24-0000-1000-8000-00805f9b34fb
796    testbluetooth D/BluetoothGatt﹕ onGetCharacteristic() - Device=E9:E3:17:4F:F5:2B UUID=00002a23-0000-1000-8000-00805f9b34fb
806    testbluetooth D/BluetoothGatt﹕ onGetDescriptor() - Device=E9:E3:17:4F:F5:2B UUID=00002902-0000-1000-8000-00805f9b34fb
806    testbluetooth D/BluetoothGatt﹕ onGetDescriptor() - Device=E9:E3:17:4F:F5:2B UUID=00002902-0000-1000-8000-00805f9b34fb
806    testbluetooth D/BluetoothGatt﹕ onGetDescriptor() - Device=E9:E3:17:4F:F5:2B UUID=00002902-0000-1000-8000-00805f9b34fb
806    testbluetooth D/BluetoothGatt﹕ onSearchComplete() = Device=E9:E3:17:4F:F5:2B Status=0
806    testbluetooth D/MainActivity﹕ Services Discovered: 0
806    testbluetooth I/MainActivity﹕ ******************************************************************enableNextSensor
806    testbluetooth I/MainActivity﹕ **************************READ
806    testbluetooth I/MainActivity﹕ **************************NOTIFY
806    testbluetooth D/BluetoothGatt﹕ setCharacteristicNotification() - uuid: 00002a1c-0000-1000-8000-00805f9b34fb enable: true
806    testbluetooth D/BluetoothGatt﹕ writeDescriptor() - uuid: 00002902-0000-1000-8000-00805f9b34fb
826    testbluetooth D/BluetoothGatt﹕ onDescriptorWrite() - Device=E9:E3:17:4F:F5:2B UUID=00002a1c-0000-1000-8000-00805f9b34fb
826    testbluetooth I/MainActivity﹕ ******************************************************************enableNextSensor
826    testbluetooth I/MainActivity﹕ **************************READ
826    testbluetooth I/MainActivity﹕ **************************NOTIFY
826    testbluetooth D/BluetoothGatt﹕ setCharacteristicNotification() - uuid: 00002a1c-0000-1000-8000-00805f9b34fb enable: true
826    testbluetooth D/BluetoothGatt﹕ writeDescriptor() - uuid: 00002902-0000-1000-8000-00805f9b34fb
37.178    testbluetooth D/BluetoothAdapter﹕ startLeScan(): [Ljava.util.UUID;@426bb628
37.188    testbluetooth D/BluetoothAdapter﹕ onClientRegistered() - status=0 clientIf=4
38.840    testbluetooth D/BluetoothAdapter﹕ stopLeScan()
41.353    testbluetooth D/BluetoothAdapter﹕ startLeScan(): [Ljava.util.UUID;@426a4288
41.363    testbluetooth D/BluetoothAdapter﹕ onClientRegistered() - status=0 clientIf=4
42.194    testbluetooth D/BluetoothAdapter﹕ stopLeScan()
44.706    testbluetooth D/BluetoothAdapter﹕ startLeScan(): [Ljava.util.UUID;@42699148
44.726    testbluetooth D/BluetoothAdapter﹕ onClientRegistered() - status=0 clientIf=4
45.307    testbluetooth D/BluetoothAdapter﹕ stopLeScan()
45.327    testbluetooth D/BluetoothGatt﹕ close()

1 个答案:

答案 0 :(得分:0)

是。我解决了这个问题。它没有通知其指示。

我将属性检查的条件修改为以下。

if ((properties & BluetoothGattCharacteristic.PROPERTY_INDICATE) != 0) {
     setCharacteristicIndication(BluetoothGattCharacteristic characteristic, true);
}

public void setCharacteristicIndication(
    BluetoothGattCharacteristic characteristic,boolean enabled) {

        mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);

        BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
        UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
        Log.d(TAG, "**********************************************************************************************is Descriptor null=>" + descriptor);
        if(descriptor != null) {
        descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
        Log.v(TAG, "Enabling indications for " + characteristic.getUuid());
        Log.d(TAG, "gatt.writeDescriptor(" + SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG + ", value=0x02-00)");
        mBluetoothGatt.writeDescriptor(descriptor);

        } else {
        Log.d(TAG,"****************************Descriptor Null :"+descriptor);
        Log.v(TAG, "Could not enable indications for " + characteristic.getUuid());
        }
}