当前位置: 首页 > 知识库问答 >
问题:

通过蓝牙低能(BLE)设备获得通知的步骤是什么?

蔚学真
2023-03-14

我正在开发一款蓝牙低能耗(BLE)应用程序。我有一个可测量重量的仪器(秤)。我可以连接这个设备。但我不知道如何从中读取数据(重量值)。

我想知道我的应用程序是否连接到任何BLE设备,那么需要采取哪些步骤才能获得设备通知以获取更新的数据。

好的,下面是我正在使用的活动。。

public class BlogBLEActivity extends Activity implements OnItemClickListener
{
    private final static String TAG = BlogBLEActivity.class.getSimpleName();

    private BluetoothAdapter bluetoothAdapter;
    BluetoothManager bluetoothManager;

    boolean hasBleFeature = false;

    TextView tvMessage;
    int messageId = R.string.doesnt_support_ble;
    int colorId = android.R.color.holo_red_light;

    private boolean mScanning;
    private Handler handler = new Handler();

    private static final long SCAN_PERIOD = 10000;
    private static final int REQUEST_ENABLE_BT = 1209;

    ListView listView;
    ArrayList<BluetoothDevice> listDevices;

    BleDeviceAdapter bleDeviceAdapter;

    TextView tvHumidity;
    TextView tvTemperature;
    TextView tvPressure;

    boolean isConnected = false;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.blog_ble);

        initParameters();
        initViews();

        scanLeDevice(true);
    }

    @SuppressLint("NewApi")
    void initParameters()
    {
        hasBleFeature = getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE);
        Log.i(TAG, "hasBleFeature : " + hasBleFeature);

        if (hasBleFeature)
        {
            messageId = R.string.supports_ble;
            colorId = android.R.color.holo_blue_light; 
        } else
        {
            messageId = R.string.doesnt_support_ble;
            colorId = android.R.color.holo_red_light;
        }

        bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        bluetoothAdapter = bluetoothManager.getAdapter();// BluetoothAdapter.getDefaultAdapter();

        if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled())
        {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
        }

        listDevices = new ArrayList<BluetoothDevice>();
        bleDeviceAdapter = new BleDeviceAdapter(this, listDevices);
    }

    void initViews()
    {
        tvHumidity = (TextView) findViewById(R.id.blog_ble_tv_humidity);
        tvTemperature = (TextView) findViewById(R.id.blog_ble_tv_temprature);
        tvPressure = (TextView) findViewById(R.id.blog_ble_tv_pressure);

        tvMessage = (TextView) findViewById(R.id.blog_ble_tv_message);
        tvMessage.setText(getResources().getString(messageId));
        tvMessage.setTextColor(getResources().getColor(colorId));

        listView = (ListView) findViewById(R.id.blog_ble_list_view);
        listView.setAdapter(bleDeviceAdapter);
        listView.setOnItemClickListener(this);
    }

    @SuppressLint("NewApi")
    void scanLeDevice(final boolean enable)
    {
        if (enable)
        {
            handler.postDelayed(new Runnable()
            {
                @SuppressLint("NewApi")
                @Override
                public void run()
                {
                    mScanning = false;
                    bluetoothAdapter.stopLeScan(leScanCallback);
                }
            }, SCAN_PERIOD);

            mScanning = false;
            bluetoothAdapter.startLeScan(leScanCallback);
        } else
        {
            mScanning = false;
            bluetoothAdapter.stopLeScan(leScanCallback);
        }
    }

    @SuppressLint("NewApi")
    private BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback()
    {
        @Override
        public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord)
        {
            runOnUiThread(new Runnable()
            {
                @Override
                public void run()
                {
                    if (device != null)
                    {
                        bleDeviceAdapter.add(device);
                        bleDeviceAdapter.notifyDataSetChanged();
                    }
                }
            });
        }
    };

    class BleDeviceAdapter extends ArrayAdapter<BluetoothDevice>
    {
        public BleDeviceAdapter(Context context, List<BluetoothDevice> objects)
        {
            super(context, R.layout.row_ble_device, R.id.row_ble_device_tv_name, objects);
        }

        @SuppressLint("NewApi")
        @Override
        public View getView(int position, View convertView, ViewGroup parent)
        {
            View row = super.getView(position, convertView, parent);
            ViewHolder holder = (ViewHolder) row.getTag();
            if (holder == null)
            {
                holder = new ViewHolder(row);
                row.setTag(holder);
            }

            BluetoothDevice device = getDevice(position);
            holder.tvName.setText("" + device.getName());

            Log.i(TAG, "" + device.getName());
            return row;
        }
    }

    BluetoothDevice getDevice(int position)
    {
        return (BluetoothDevice) listView.getAdapter().getItem(position);
    }

    @SuppressLint("NewApi")
    @Override
    public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3)
    {
        BluetoothDevice device = getDevice(position);
        Toast.makeText(this, "" + device.getName(), Toast.LENGTH_SHORT).show();
        BluetoothGatt connectGatt = device.connectGatt(this, false, mGattCallback);

    }

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

    private static final UUID KITCHEN_SCALE_SERVICE = UUID.fromString("0000780a-0000-1000-8000-00805f9b34fb");
    private static final UUID KITCHEN_SCALE_FEATURE_CHAR = UUID.fromString("00008aa0-0000-1000-8000-00805f9b34fb");
    private static final UUID KITCHEN_SCALE_MEASUREMENT_CHAR = UUID.fromString("00008aa1-0000-1000-8000-00805f9b34fb");
    private static final UUID KITCHEN_SCALE_INTERMEDIATE_CHAR = UUID.fromString("00008aa2-0000-1000-8000-00805f9b34fb");

    /*
     * In this callback, we've created a bit of a state machine to enforce that
     * only one characteristic be read or written at a time until all of our
     * sensors are enabled and we are registered to get notifications.
     */
    @SuppressLint("NewApi")
    private BluetoothGattCallback mGattCallback = new BluetoothGattCallback()
    {

        /* State Machine Tracking */
        private int mState = 0;

        private void reset()
        {
            mState = 0;
        }

        private void advance()
        {
            mState++;
        }

        /*
         * 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)
        {
            BluetoothGattCharacteristic characteristic;
            switch (mState)
            {
            case 0:
                Log.i(TAG, "Enabling weight scale");
                characteristic = gatt.getService(KITCHEN_SCALE_SERVICE).getCharacteristic(KITCHEN_SCALE_FEATURE_CHAR);
                Log.i(TAG, "Feature Properties : "+characteristic.getProperties());
                characteristic.setValue(new byte[]
                { 0x09 });
                break;

            default:
                mHandler.sendEmptyMessage(MSG_DISMISS);
                Log.i(TAG, "All Sensors Enabled");
                return;
            }

            gatt.writeCharacteristic(characteristic);
        }

        /*
         * Read the data characteristic's value for each sensor explicitly
         */
        private void readNextSensor(BluetoothGatt gatt)
        {
            BluetoothGattCharacteristic characteristic;
            switch (mState)
            {
            case 0:
                Log.i(TAG, "Reading weight cal");
                characteristic = gatt.getService(KITCHEN_SCALE_SERVICE).getCharacteristic(KITCHEN_SCALE_MEASUREMENT_CHAR);
                break;

            default:
                mHandler.sendEmptyMessage(MSG_DISMISS);
                Log.i(TAG, "All Sensors Enabled");
                return;
            }

            gatt.readCharacteristic(characteristic);
        }

        /*
         * Enable notification of changes on the data characteristic for each
         * sensor by writing the ENABLE_NOTIFICATION_VALUE flag to that
         * characteristic's configuration descriptor.
         */
        private void setNotifyNextSensor(BluetoothGatt gatt)
        {
            BluetoothGattCharacteristic characteristic;
            switch (mState)
            {
            case 0:
                Log.i(TAG, "Set notify weight ");
                characteristic = gatt.getService(KITCHEN_SCALE_SERVICE).getCharacteristic(KITCHEN_SCALE_MEASUREMENT_CHAR);
                break;

            default:
                mHandler.sendEmptyMessage(MSG_DISMISS);
                Log.i(TAG, "All Sensors Enabled");
                return;
            }

            // 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.i(TAG, "Connection State Change: " + status + " -> " + connectionState(newState));
            if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_CONNECTED)
            {
                /*
                 * Once successfully connected, we must next discover all the
                 * services on the device before we can read and write their
                 * characteristics.
                 */
                gatt.discoverServices();
                mHandler.sendMessage(Message.obtain(null, MSG_PROGRESS, "Discovering Services..."));
            } else if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_DISCONNECTED)
            {
                /*
                 * If at any point we disconnect, send a message to clear the
                 * weather values out of the UI
                 */

                mHandler.sendEmptyMessage(MSG_CLEAR);
            } else if (status != BluetoothGatt.GATT_SUCCESS)
            {
                /*
                 * If there is a failure at any stage, simply disconnect
                 */
                gatt.disconnect();
            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status)
        {
            Log.i(TAG, "Services Discovered: " + status);
            if (status == BluetoothGatt.GATT_SUCCESS)
            {
                Log.i(TAG, "No of services discovered: " + gatt.getServices().size());
                mHandler.sendMessage(Message.obtain(null, MSG_PROGRESS, "No of services discovered: " + gatt.getServices().size()));

                List<BluetoothGattService> services = gatt.getServices();
                for (BluetoothGattService bluetoothGattService : services)
                {
                    UUID uuid = bluetoothGattService.getUuid();
                    Log.e(TAG, ""+uuid.toString());
                    List<BluetoothGattCharacteristic> characteristics = bluetoothGattService.getCharacteristics();
                    for (BluetoothGattCharacteristic bluetoothGattCharacteristic : characteristics)
                    {
                        UUID uuidC = bluetoothGattCharacteristic.getUuid();
                        Log.i(TAG, "Gatt Properties : "+bluetoothGattCharacteristic.getProperties());
                        Log.i(TAG, ""+uuidC.toString());
                        CharacteristicHelper helper = new CharacteristicHelper(bluetoothGattCharacteristic);
                        Log.i(TAG, "isRead : "+helper.isRead());
                        Log.i(TAG, "isWrite : "+helper.isWrite());
                        Log.i(TAG, "isNotify : "+helper.isNotify());
                        Log.i(TAG, "isWriteNoResponse : "+helper.isWriteNoResponse());
                    }
                }
            }
            // 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 onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status)
        {
            Log.i(TAG, "onCharacteristicRead");
            // For each read, pass the data up to the UI thread to update the
            // display
            /**methodToUpdateUI().*/

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

        @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);
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic)
        {
            Log.i(TAG, "onCharacteristicChanged");
            /*
             * 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.
             */
        }

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

        @Override
        public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status)
        {
            Log.i(TAG, "Remote RSSI: " + rssi);
        }

        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);
            }
        }
    };

    /*
     * We have a Handler to process event results on the main thread
     */
    private static final int MSG_PROGRESS = 201;
    private static final int MSG_DISMISS = 202;
    private static final int MSG_CLEAR = 301;
    private Handler mHandler = new Handler()
    {
        @SuppressLint("NewApi")
        @Override
        public void handleMessage(Message msg)
        {
            BluetoothGattCharacteristic characteristic;
            switch (msg.what)
            {
            case MSG_PROGRESS:
                tvMessage.setText((String) msg.obj);
                break;
            case MSG_DISMISS:
                tvMessage.setText("Service Enabled");
                break;
            case MSG_CLEAR:
                tvMessage.setText("");
                break;
            }
        }
    };
}

在我的活动中,首先我要扫描所有可用的设备

如果有人对此有任何想法,请帮助我。

共有3个答案

薛鹏飞
2023-03-14

您必须区分值是通知还是指示,并使用描述符设置相应的值。设置值。如果设置错误,将无法获得值。

伊裕
2023-03-14

请参考开发者门户网站上提供的示例应用程序“Bluetoothlegatt”的源代码。

样本服务:http://developer.android.com/samples/BluetoothLeGatt/src/com.example.android.bluetoothlegatt/BluetoothLeService.html

使用服务:http://developer.android.com/samples/BluetoothLeGatt/src/com.example.android.bluetoothlegatt/DeviceControlActivity.html

示例包含具有读取和通知属性的特征。所以你一定能找到解决办法。请用下面的代码进入部分:(你可能会弄明白)

public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
        if (mBluetoothAdapter == null || mBluetoothGatt == null) {
            Log.w(TAG, "BluetoothAdapter not initialized");
            return;
        }
        mBluetoothGatt.readCharacteristic(characteristic);
    }
曾歌者
2023-03-14

有一个装置需要我使用

descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE)

而不是

descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE)

正如在这个问题中所解释的

Android BLE API:未收到GATT通知

 类似资料:
  • 我正在尝试制作一个应用程序,它使用Android的新蓝牙低能耗API。为此,我从API Level18附带的BLE示例开始。 当我读到Android不能充当外围设备时,我将Android手机置于中央模式,扫描周围的BLE设备。为此,我用一个模拟心脏传感器的北欧平台做了一些测试。一切都以完美的方式运作! 多谢了。 编辑:经过一些艰苦的测试,我在AOSP页面上提出了一个问题。这里可以查

  • 我正在创建一个Qt应用程序,在这里我将iOS与BLE板连接起来。 在阅读了near中的ble组件后,我像这样连接Android设备: 我在Android系统上找到了Mac地址 QBluetoothDeviceInfo 但是iOS没有从布尔那里得到苹果电脑地址,只有UUID。我试着在doc上在线搜索,但是我没有找到关于通过uuid连接ios和蓝牙服务的东西。 有一个模式转换uuid在mac地址或有一

  • 我想通过iPhone(5s)上的应用程序,在50-100米半径范围内同时跟踪大量信标(~500)。我已经看过了规范和在线版本,我看不出使用BLE一次可以跟踪的信标数量是否有任何限制。有人知道你可以跟踪的信标数量是否有限制,或者iphone5s是否能够完成跟踪那么多信标的任务?

  • 我正在开发一个与硬件设备连接的BLE(蓝牙LE)应用程序。我能够发现并连接到设备,从设备读取数据,将数据写入设备。 我在苹果的BLE文档中找不到的是,当你靠近一台设备时,当应用程序关闭时,如何获得通知。 我知道如何注册到特征通知,但此通知仅在应用程序位于后台时发生。 我知道可以在应用程序关闭时检测蓝牙,并发送通知,但我想在设备发现具有的特定BLE时收到通知。 iBeacon正在将BLE与UUID、

  • 我制作了一个android应用程序来扫描蓝牙设备,并向我的服务器发送一个HTTP请求,这样我就可以检测它们是开着还是关着。我已经用我的带有蓝牙适配器的台式电脑测试过了,效果很好。当检测到电脑上的蓝牙功能时,它显示电脑是打开的,当我关闭电脑上的蓝牙功能时,它是关闭的。现在,我需要使用这个应用程序的设备有:雅伯投影仪、Bose SoundLink和JBL耳机,但我遇到了一些问题。 首先,投影仪似乎无法

  • 我的应用程序应连接到蓝牙LE设备。通常使用mBluetoothAdapter执行设备扫描。Stratescan(mLeScanCallback) 。回调为您提供有关可用设备的信息。 如果要连接到专用设备,请执行以下操作 然后 在我看来,连接到BLE设备的唯一需要是知道BLE地址,然后通过以上两个步骤连接到它。因此,如果我已经知道一个BLE地址(例如,它写在BLE设备的标签上),我就不需要执行BLE