在写《Android蓝牙开发系列文章-蓝牙音箱连接》时,计划细化出一篇讲解蓝牙设备类型的文章,现在它来了~

阅读其他内容,可以点击《Android蓝牙开发系列文章-策划篇》,或者扫描文章下方的二维码关注我个人的公众号哈~

为什么要讲解蓝牙设备的分类?

设备的类型是表征设备能力的属性,设备类型的不同决定了UI中图标显示、扫描设备过程中的过滤以及在连接过程中通过什么类型的Profile进行连接。

细一点讲:

不同的蓝牙设备类型在UI中会有不同的UI显示,例如,鼠标设备显示为鼠标图标,音箱设备会显示音箱图标,耳机设备会显示耳机图标。

在扫描过程中,我们需要搜索到目标设备,这个设备类型往往是其中的一个匹配项,只有配对上了,我们才认为这个设备是我们的目标设备,才会对该设备进行下一步的流程:配对、连接等等。

在连接过程中,我们需要针对设备类型不同,通过不同的Profile发起连接,例如,对于音箱设备,我们需要通过A2DP Profile进行连接(如果忘记了,可以回头再看一下《Android蓝牙开发系列文章-蓝牙音箱连接》),对于鼠标设备,我们需要通过Input profile进行连接。

其他需求也可能会用到设备的类型。

目录

1.通过COD进行设备类型区分

2.Demo演示


1.通过COD进行设备类型区分

我们在扫描到设备后,可以通过mac地址构造一个BluetoothDevice对象,然后调用getBluetoothClass()方法获取其设备类型。

1227    /**
1228     * Get the Bluetooth class of the remote device.
1229     *
1230     * @return Bluetooth class object, or null on error
1231     */
1232    @RequiresPermission(Manifest.permission.BLUETOOTH)
1233    public BluetoothClass getBluetoothClass() {
1234        final IBluetooth service = sService;
1235        if (service == null) {
1236            Log.e(TAG, "BT not enabled. Cannot get Bluetooth Class");
1237            return null;
1238        }
1239        try {
1240            int classInt = service.getRemoteClass(this);
1241            if (classInt == BluetoothClass.ERROR) return null;
1242            return new BluetoothClass(classInt);
1243        } catch (RemoteException e) {
1244            Log.e(TAG, "", e);
1245        }
1246        return null;
1247    }

BluetoothClass类持有一个mClass变量,我们利用该变量来分辨设备类型。

从代码的注释,我们可以看到该变量就是蓝牙设备的COD,这个变量是三个部分组成的。

 private final int mClass;
282    /**
283     * Return the Bluetooth Class of Device (CoD) value including the
284     * {@link BluetoothClass.Service}, {@link BluetoothClass.Device.Major} and
285     * minor device fields.
286     *
287     * <p>This value is an integer representation of Bluetooth CoD as in
288     * Bluetooth specification.
289     *
290     * @see <a href="Bluetooth CoD">https://www.bluetooth.com/specifications/assigned-numbers/baseband</a>
291     *
292     * @hide
293     */
294    public int getClassOfDevice() {
295        return mClass;
296    }

这个32位变量用固定的某些位表示service Class/Major Class/Minor Class。为了表述更清晰一点,我画了一个图,如下所示。

第2位到12位表示Major和Minor Class的组合,第8位到第12位表示Major Class,第14位到第23位表示Service Class。

这里提到了三个名词,下面分别进行解释:

 Service Class:

service class类型有如下几种,一个service表示蓝牙的一个能力,例如,蓝牙设备支持A2DP Service,则表示这个蓝牙设备可以作为一个音箱设备使用。

109    /**
110     * Defines all service class constants.
111     * <p>Each {@link BluetoothClass} encodes zero or more service classes.
112     */
113    public static final class Service {
114        private static final int BITMASK = 0xFFE000;
115
116        public static final int LIMITED_DISCOVERABILITY = 0x002000;
117        public static final int POSITIONING = 0x010000;
118        public static final int NETWORKING = 0x020000;
119        public static final int RENDER = 0x040000;
120        public static final int CAPTURE = 0x080000;
121        public static final int OBJECT_TRANSFER = 0x100000;
122        public static final int AUDIO = 0x200000;
123        public static final int TELEPHONY = 0x400000;
124        public static final int INFORMATION = 0x800000;
125    

我们可以利用hasService(int)来判断是否支持对于的service。

127    /**
128     * Return true if the specified service class is supported by this
129     * {@link BluetoothClass}.
130     * <p>Valid service classes are the public constants in
131     * {@link BluetoothClass.Service}. For example, {@link
132     * BluetoothClass.Service#AUDIO}.
133     *
134     * @param service valid service class
135     * @return true if the service class is supported
136     */
137    public boolean hasService(int service) {
138        return ((mClass & Service.BITMASK & service) != 0);
139    }
140

Major Class:

Major Class表示设备的大类型,这个区分粒度相对来说比较大,通过查看代码,我们可以看到蓝牙设备分为了Computer、Phone等几大类。

151    public static class Device {
152        private static final int BITMASK = 0x1FFC;
153
154        /**
155         * Defines all major device class constants.
156         * <p>See {@link BluetoothClass.Device} for minor classes.
157         */
158        public static class Major {
159            private static final int BITMASK = 0x1F00;
160
161            public static final int MISC = 0x0000;
162            public static final int COMPUTER = 0x0100;
163            public static final int PHONE = 0x0200;
164            public static final int NETWORKING = 0x0300;
165            public static final int AUDIO_VIDEO = 0x0400;
166            public static final int PERIPHERAL = 0x0500;
167            public static final int IMAGING = 0x0600;
168            public static final int WEARABLE = 0x0700;
169            public static final int TOY = 0x0800;
170            public static final int HEALTH = 0x0900;
171            public static final int UNCATEGORIZED = 0x1F00;
172        }
........

确定蓝牙设备属于哪个蓝牙类型大类可以调用如下接口:

256
257    /**
258     * Return the major device class component of this {@link BluetoothClass}.
259     * <p>Values returned from this function can be compared with the
260     * public constants in {@link BluetoothClass.Device.Major} to determine
261     * which major class is encoded in this Bluetooth class.
262     *
263     * @return major device class component
264     */
265    public int getMajorDeviceClass() {
266        return (mClass & Device.Major.BITMASK);
267    }

每个蓝牙设备大类可以进行进一步细化,例如,Computer大类可以进一步划分为如下几个小类:

174        // Devices in the COMPUTER major class
175        public static final int COMPUTER_UNCATEGORIZED = 0x0100;
176        public static final int COMPUTER_DESKTOP = 0x0104;
177        public static final int COMPUTER_SERVER = 0x0108;
178        public static final int COMPUTER_LAPTOP = 0x010C;
179        public static final int COMPUTER_HANDHELD_PC_PDA = 0x0110;
180        public static final int COMPUTER_PALM_SIZE_PC_PDA = 0x0114;
181        public static final int COMPUTER_WEARABLE = 0x0118;

综上,我们可以先用判断service class的方式来判断设备的能力,如果满足我们的要求,再进一步判断一下设备的Major Class,如果通过Major Class还不能定位到你的设备,则再进一步确定设备的小类。

2.Demo演示

我们利用《Android蓝牙开发系列文章-蓝牙音箱连接》中的demo为基础,来看一下我们的音箱是否支持a2dp profile以及它的Major Class是否为AUDIO_VIDEO。

在设备扫描到S7音箱后,判断一下是否满足a2dp Profile和Major Class,如果满足预期,则对这个设备发起配对、连接,如果不满足,则继续搜索设备。

 public void onReceive(Context context, Intent intent) {final String action = intent.getAction();Log.d(TAG, "onReceive intent = " + action);if(action.equals(BluetoothDevice.ACTION_FOUND)) {BluetoothDevice btdevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);final String address = btdevice.getAddress();final String deviceName = btdevice.getName();Log.d(TAG, "onReceive found device, deivce address = " + address + ",deviceName = " + deviceName);if(isTargetDevice(btdevice)) {BluetoothClass btClass = btdevice.getBluetoothClass();if(btClass.hasService(BluetoothClass.Service.AUDIO)) {Log.d(TAG, "btdevice: " + btdevice + "support a2dp profile");} else {Log.d(TAG, "btdevice: " + btdevice + "not support a2dp profile");return;}int majorClass = btClass.getMajorDeviceClass();Log.d(TAG, "btClass: " + btClass + "majorClass = " + majorClass);stopScan();mHandler.sendEmptyMessageDelayed(MSG_PAIR, DELAYT_TIMES);}}

相关日志打印如下,我们可以看到该音箱的确支持A2dp Profile,且其Major Class为1024,转换成16进制数为0x400,等于AUDIO_VIDEO类型。

 --------- beginning of system
03-15 10:53:03.305 1311-1311/com.atlas.btdemo D/MainActivity: onReceive intent = android.bluetooth.device.action.FOUND
03-15 10:53:03.309 1311-1311/com.atlas.btdemo D/MainActivity: onReceive found device, deivce address = FC:58:FA:B4:45:EA,deviceName = S7
03-15 10:53:03.318 1311-1311/com.atlas.btdemo D/MainActivity: deivce :S7is target device
03-15 10:53:03.320 1311-1311/com.atlas.btdemo D/MainActivity: btdevice: FC:58:FA:B4:45:EAsupport a2dp profile
03-15 10:53:03.320 1311-1311/com.atlas.btdemo D/MainActivity: btClass: 260404majorClass = 1024
03-15 10:53:03.331 1311-1311/com.atlas.btdemo D/MainActivity: stop scan device
03-15 10:53:03.832 1311-1311/com.atlas.btdemo D/MainActivity: dispatchMessage, msg.what = 1
03-15 10:53:03.832 1311-1311/com.atlas.btdemo D/MainActivity: start pair device = FC:58:FA:B4:45:EA

这里想再补充一点,最后不要只根据Major Class来进行设备类型的判断,因为有些设备制作的不标准,即虽然是一个蓝牙音箱,但是它的Major Class却不是0x400。

那应该怎么判断呢?其实我们只需要通过Service Class来判断就行了,因为一个蓝牙设备支持了A2dp Profile,则它就具有了作为音箱的能力,我们完全可以认为它就是一个音箱,不需要其他的条件判断了~

好了,本篇文章就到了这里,主要讲了BluetoothClass这个类型以及结合经验给大家一点判断设备类型的建议~

如果想持续关注本博客内容,请扫描关注个人微信公众号,或者微信搜索:万物互联技术。

Android蓝牙开发系列文章-蓝牙设备类型知多少?相关推荐

  1. Android蓝牙开发系列文章-蓝牙mesh(一)

    在<Android蓝牙开发系列文章-策划篇>中我们对蓝牙专题的内容进行整体规划,现在让我们一点点揭开他的面纱~ 本文是关于蓝牙mesh的首篇文章,由好友CSDN博主yk150915提供,在 ...

  2. Android蓝牙开发系列文章-蓝牙音箱连接

    经过一段时间的折腾,我的Android Studio终于可以正常工作了,期间遇到的坑记录在了文章<创建Android Studio 3.5第一个工程遇到的坑>. 我们在<Androi ...

  3. Android蓝牙开发系列文章-扫不到蓝牙设备,你的姿势对了吗?

    在写<Android蓝牙开发系列文章-蓝牙音箱连接>时,计划细化出两篇文章,分别是: 关于蓝牙设备类型分类的,这个已经完成了,阅读请点击<Android蓝牙开发系列文章-蓝牙设备类型 ...

  4. Android蓝牙开发系列文章-其实你的手机可以变成一个蓝牙音箱

    本文是蓝牙音频相关的第3篇文章,查阅其他内容,请点击<Android蓝牙开发系列文章-策划篇>. 目前a2dp相关的内容有: <Android蓝牙开发系列文章-AudioTrack播 ...

  5. Android蓝牙开发系列文章-玩转BLE开发(一)

    我们在<Android蓝牙开发系列文章-策划篇>中计划讲解一下蓝牙BLE,现在开始第一篇:Android蓝牙开发系列文章-玩转BLE开发(一).计划要写的BLE文章至少分四篇,其他三篇分别 ...

  6. Qt for Bluetooth 蓝牙开发系列文章总纲

    文章目录 叙述 大纲 金典蓝牙开发篇 低功耗蓝牙开发篇 双十一,九折优惠券在线地址获取:购课优惠券 欢迎大家关注公众号,可获取pdf等相关demo下载资源 叙述   此套蓝牙开发主要针对win平台和a ...

  7. android 相机编程,Android相机开发系列

    Android Camera Develop Series 简介 Android相机开发系列文章循序渐进,教你从一个没有任何功能的相机APP开始,逐步完善实现一般相机APP的各种功能,甚至还能拿来做图 ...

  8. Android 蓝牙开发(一) -- 传统蓝牙聊天室

    Android 蓝牙开发(一) – 传统蓝牙聊天室 Android 蓝牙开发(三) – 低功耗蓝牙开发 项目工程BluetoothDemo 一.蓝牙概览 以下是蓝牙的介绍,来自维基百科: 蓝牙(英语: ...

  9. Android 蓝牙开发(三) -- 低功耗蓝牙开发

    Android 蓝牙开发(一) – 传统蓝牙聊天室 Android 蓝牙开发(三) – 低功耗蓝牙开发 项目工程BluetoothDemo 前面已经学习了经典蓝牙开发,学习了蓝牙的配对连接和通信,又通 ...

最新文章

  1. 何时开学?教育部最新回应:满足三个条件可开学
  2. Asp.net MVC 4新项目中创建area的后续操作
  3. mybatisplus查询今天的数据_Spring系列——MybatisPlus
  4. 拿来就用:11款不容错过的 Node.js 框架
  5. 【PAT乙】1003 我要通过! (20分) 字符串条件判定
  6. Spark sql优化
  7. 编写高质量代码改善C#程序的157个建议[泛型集合、选择集合、集合的安全]
  8. 系统字体服务器,把字体放到服务器
  9. 元数据、数据元、资源目录
  10. java面试题及答案2020 阿里(八)
  11. 109-gamp与rtklib精度对比
  12. 中国主要山脉及山峰分布
  13. HTML5 之 Link 标签
  14. Linux 中的 -rwxr-xr-x 权限代表什么意思 Linux 中的权限
  15. jadx卡死解决方案
  16. acwing1113 红与黑
  17. 微信小程序如何实现切换主题(更改皮肤)
  18. 《Java 开发手册》读后感
  19. 【转】如何确定我的测试用例覆盖全面-测试面试题
  20. 细胞分类 识别 系统

热门文章

  1. jsp通过<%@include file=“bottom.txt“ %>指令引入txt乱码的解决方法
  2. ECharts数据可视化项目
  3. 如何查找国内各大学本科学位论文?
  4. 请提前为你的眼泪找一个合适的借口
  5. C# thread和delegate lambda函数结合的一段code
  6. IEEE 802.3标准就是ISO 802.3标准
  7. el-cascader级联选择器,解决最后一级空白过滤掉空的children,并且使用props设置children等参数
  8. aardio - 虚表库全新升级,支持图片系列专题
  9. oracle系统监控工具oswatch简介!
  10. 海外服务器的3种体系架构:SMP、NUMA、MPP