Android蓝牙健康设备开发:Health Device Profile(HDP)

本文介绍了如何使用Android蓝牙开发包与经典蓝牙设备(如血压计)通过Health Device Profile (HDP)进行通信。文章详细阐述了HDP的概念,通信协议栈,以及Android蓝牙API的使用步骤。通过一个简单的项目示例,展示了从获取蓝牙代理对象、注册应用程序配置、建立通信通道到读取和解析数据的全过程。最后,文章提到了读取数据的关键在于遵循IEEE 11073协议标准。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近按导师的要求做了个小项目:用Android手机跟蓝牙血压计通信。在网上查了很多资料,发现有许多文章是讲解Android蓝牙开发,但是在中文社区缺少针对实现HDP profile的蓝牙健康设备的文章,所以整理了相关知识和代码做一个总结。做了一点微小的贡献,谢谢大家。
1、相关概念
HDP:Health Device Profile顾名思义是针对蓝牙健康设备(如蓝牙血压计、蓝牙体重秤)的一个profile,由蓝牙技术联盟(Bluetooth SIG)发布。并不是所有蓝牙设备都可以采用HDP,只有经典蓝牙(BR/EDR)设备才可以。低功耗蓝牙设备,即蓝牙4.0及以上,采用的是GATT等profile。

上图是HDP的协议栈。在通信时,蓝牙健康设备作为source,Android手机作为sink。图中L2CAP、SDP、MCAP是蓝牙通信的底层协议,中间是IEEE11073协议。11073是IEEE发布的一个健康设备的协议簇,其下包含了许多不同种类的健康设备协议,如11073-10407是血压计的协议。在数据传输时,手机与健康设备根据此协议来发送请求、解析数据等。最上层的application在本文中自然指的就是Android app。
Android蓝牙模块:android.bluetooth是蓝牙的开发包,里面包含了所有蓝牙相关的类,无论是经典蓝牙还是低功耗蓝牙。其中,本文重点关注的是BluetoothHealth这个类,还用到了一些蓝牙基础类BluetoothAdapter BluetoothDevice等,在这里就不展开介绍了。BluetoothHealth是在API14时引入的,所以系统版本高于14的Android手机都可以与采用HDP的健康设备通信。BluetoothHealth中包括了与HDP设备建立通信的API,具体请参见官方文档。在官方文档中有一个建立通信的流程:
1、调用getProfileProxy(Context, BluetoothProfile.ServiceListener, int)来获取代理对象的连接。
2、创建BluetoothHealthCallback回调,调用registerSinkAppConfiguration(String, int, BluetoothHealthCallback)注册一个sink端的应用程序配置。
3、将手机与健康设备配对,这一步一般在手机的“设置”中完成。
4、使用connectChannelToSource(BluetoothDevice, BluetoothHealthAppConfiguration)来建立一个与健康设备的通信channel。有的设备会自动建立通信,不需要在代码中调用这个方法。第二步中的回调会指示channel的状态变化。
5、用ParcelFileDescriptor来读取健康设备传来的数据,并根据IEEE 11073来解析数据。
6、通信结束后,关闭通信channel,注销应用程序配置。
看完这个流程是不是一脸懵逼?不要慌,这里官方文档实在太抽象了,必须要配合实际的代码才能看懂。
2、demo代码
项目的目标是与经典蓝牙血压计进行通信,获取血压计测量的数值和日期。这里血压计的型号是A&D UA-767PBT-C。项目中的代码是以github上这个项目为基础,根据需求进行修改而实现的。

项目结构

上图是项目的结构,非常简单,只有一个activity和一个service。activity与用户交互,service绑定在activity中与蓝牙血压计建立通信、交换数据。
首先AndroidManifest.xml中注册蓝牙权限:

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

MainActivity

主要作用是显示血压计传过来的数据,以及绑定服务。
activity的布局如下:

demo.png

上半部分是一个ArrayList,用于显示手机所配对的蓝牙设备的名称和Mac地址。下半部分会显示一次血压测量的参数:收缩压、舒张压、心率、测量时间。

在MainActivity中一些重要私有变量:

private static final int REQUEST_ENABLE_BT = 1;  //用于打开手机蓝牙
private static final int HEALTH_PROFILE_SOURCE_DATA_TYPE = 0x1007;  //IEEE 11073中规定的血压数据类型
private BluetoothAdapter mBluetoothAdapter;
private Messenger mHealthService;  //用于与service通信
private boolean mHealthServiceBound; //用于判断service是否与此activity绑定

打开蓝牙:


       if (!mBluetoothAdapter.isEnabled()) {
            Intent enableIntent = new Intent(
                    BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
        } else {
            initialize();
        }

启动服务:

            // Sets up communication with HDPService.
            private ServiceConnection mConnection = new ServiceConnection() {
                public void onServiceConnected(ComponentName name, IBinder service) {
                    mHealthServiceBound = true;
                    Message msg = Message.obtain(null,
                            HDPService.MSG_REG_CLIENT);
                    msg.replyTo = mMessenger;
                    mHealthService = new Messenger(service);
                    try {
                        mHealthService.send(msg);
                        //register blood pressure data type
                        sendMessage(HDPService.MSG_REG_HEALTH_APP,
                                HEALTH_PROFILE_SOURCE_DATA_TYPE);
                    } catch (RemoteException e) {
                        Log.w(TAG, "Unable to register client to service.");
                        e.printStackTrace();
                    }
                }

                public void onServiceDisconnected(ComponentName name) {
                    mHealthService = null;
                    mHealthServiceBound = false;
                }
            };
    private void initialize() {
        // Starts health service.
        Intent intent = new Intent(this, HDPService.class);
        //startService(intent);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

用handler和message来实现activity与service的通信:

    private Handler mIncomingHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
              ......
            }
        }
    };

    private final Messenger mMessenger = new Messenger(mIncomingHandler);

HDPService

这个service是核心部分,手机与蓝牙血压计的通信就是在此实现的。
service中部分重要私有变量:

    private BluetoothHealthAppConfiguration mHealthAppConfig; //BluetoothHealthAppConfiguration
    pr
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值