Android 蓝牙设备类型判断
Android 蓝牙设备有各种类型,比如蓝牙手机,蓝牙耳机,蓝牙手环,蓝牙鼠标键盘,蓝牙玩具,健康检测设备等等。
有些场景需要具体区分就需要进行判断了。一个是扫描到后图标显示设备类型,还是可能是具体处理的区别。
这些设备的类型,硬件设备本身其实是有定义的,
但是也不排除有些设备定义不正确,这些都是要我们开发者进行调试才清楚的。
BluetoothDevice bluetoothDevice; //蓝牙设备对象,怎么获取后面接收
int type = device.getType(); //(1)简单类型
BluetoothClass bluetoothClass = device.getBluetoothClass();
int deviceClassType = bluetoothClass.getDeviceClass(); //(2)clss tyep
int deviceType = bluetoothClass.getMajorDeviceClass(); //(3)具体类型
getMajorDeviceClass 才是详细类型的数值。
其实把这几个type 都打印出来就能看到数值了。
这个方法获取的是大致的类型。
具体类型的定义:
packages\modules\Bluetooth\framework\java\android\bluetooth\BluetoothDevice.java
/**
* Bluetooth device type, Unknown
*/
public static final int DEVICE_TYPE_UNKNOWN = 0;
/**
* Bluetooth device type, Classic - BR/EDR devices,经典-BR/EDR设备
*/
public static final int DEVICE_TYPE_CLASSIC = 1;
/**
* Bluetooth device type, Low Energy - LE-only,低能耗-仅限LE
*/
public static final int DEVICE_TYPE_LE = 2;
/**
* Bluetooth device type, Dual Mode - BR/EDR/LE,双模式-BR/EDR/LE
*/
public static final int DEVICE_TYPE_DUAL = 3;
Android13 的蓝牙源码是在这个目录,旧的源码是在framework 目录下的。
比如手机设备的值为3,蓝牙耳机、蓝牙鼠标键盘值为1;
但是这个不能区分具体类型比较。所以getType() 一般不怎么使用。
这个类型没怎么用过,网上也没几个人用。
因为他定义的类型代码中并未进行分类,需要自己去蓝牙相关协议对比确认。
具体类型的定义:
packages\modules\Bluetooth\framework\java\android\bluetooth\BluetoothClass.java
/**
* Return the (major and minor) device class component of this
* {@link BluetoothClass}.
* Values returned from this function can be compared with the
* public constants in {@link BluetoothClass.Device} to determine which
* device class is encoded in this Bluetooth class.
*
* @return device class component
*/
public int getDeviceClass() {
return (mClass & Device.BITMASK);
}
/**
* Return the Bluetooth Class of Device (CoD) value including the
* {@link BluetoothClass.Service}, {@link BluetoothClass.Device.Major} and
* minor device fields.
*
*
This value is an integer representation of Bluetooth CoD as in
* Bluetooth specification.
*
* @see https://www.bluetooth.com/specifications/assigned-numbers/baseband
*
* @hide
*/
@TestApi //这个是隐藏的,也是蓝牙设备类型的COD数值。
public int getClassOfDevice() {
return mClass;
}
这里看不出啥,但是可以知道与蓝牙的COD数值相关,COD 具体类型的定义有兴趣的可以自己搜索。
下面的 getMajorDeviceClass 方法的值也是基于 蓝牙COD的。
从后面日志看 getDeviceClass 方法还更具体一些。
这个类型是在 DeviceClass 对象基础上的类型!
下面的代码类型定义都是在 BluetoothClass.java 这个类里面。
具体类型的定义:
//获取具体类型
public int getMajorDeviceClass() {
return (mClass & Device.Major.BITMASK);
}
//内部类定义具体数据
public static class Device {
private static final int BITMASK = 0x1FFC;
/**
* Defines all major device class constants.
* See {@link BluetoothClass.Device} for minor classes.
*/
public static class Major {
private static final int BITMASK = 0x1F00;
public static final int MISC = 0x0000;
public static final int COMPUTER = 0x0100; //电脑设备
public static final int PHONE = 0x0200; //手机设备
public static final int NETWORKING = 0x0300; //网络设备 ,不清楚什么设备
public static final int AUDIO_VIDEO = 0x0400; //音频视频设备,蓝牙耳机音响
public static final int PERIPHERAL = 0x0500; //外部设备,比如蓝牙鼠标键盘,蓝牙遥控器
public static final int IMAGING = 0x0600; //影像设备
public static final int WEARABLE = 0x0700; //穿戴设备
public static final int TOY = 0x0800; //玩具设备
public static final int HEALTH = 0x0900; //健康检测设备
public static final int UNCATEGORIZED = 0x1F00;
}
。。。
}
注意这里是16进制的数值,日志打印中是十进制的数,需要转换后对比。
//监听各种蓝牙广播
public void registerBroadcast(Context context) {
DebugLog.debug("");
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED);
intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
intentFilter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);
intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
context.registerReceiver(mReceiver, intentFilter);
}
//打印广播后的日志
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
DebugLog.info("action = " + action);
if (action == null) {
DebugLog.error("action == null!");
return;
}
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (device == null) {
DebugLog.error("device == null!");
return;
}
int type = device.getType();
int getDeviceClassType = device.getBluetoothClass().getDeviceClass();
int getMajorDeviceClassType = device.getBluetoothClass().getMajorDeviceClass();
DebugLog.info("device = " + device);
DebugLog.info("getAlias = " + device.getAlias());
DebugLog.info("type = " + type);
DebugLog.info("getDeviceClassType = " + getDeviceClassType);
DebugLog.info("getMajorDeviceClassType = " + getMajorDeviceClassType);
}
};
这里有蓝牙手机、耳机、音箱、鼠标、键盘、遥控器。
具体日志打印如下:
//普通手机
action = android.bluetooth.device.action.ACL_CONNECTED
device = F0:5C:77:F4:5E:65
getAlias = Pixel 4
type = 1(最开始打印这个) --》 type = 3(后面打印这个)
getDeviceClassType = 524 // -->0x20c
getMajorDeviceClassType = 512 // -->0x200
//蓝牙耳机
action = android.bluetooth.device.action.BOND_STATE_CHANGED//其他广播也打印,这边不一一写
device = 0D:3F:91:E2:FF:D3
getAlias = Y-12
type = 1
getDeviceClassType = 1028 // -->0x404
getMajorDeviceClassType = 1024 // -->0x400
//蓝牙音箱,和耳机一样
action = android.bluetooth.device.action.BOND_STATE_CHANGED
device = 11:75:58:11:AC:7C
getAlias = A19
type = 1
getDeviceClassType = 1028
getMajorDeviceClassType = 1024
//蓝牙鼠标
action = android.bluetooth.device.action.ACL_CONNECTED
device = 34:88:5D:AC:32:D1
getAlias = Bluetooth Mouse M336/M337/M535
type = 1
getDeviceClassType = 1408 // -->0x580
getMajorDeviceClassType = 1280 // -->0x500
//蓝牙键盘
action = android.bluetooth.device.action.PAIRING_REQUEST
device = 34:88:5D:C1:4A:9D
getAlias = Keyboard K380
type = 1
getDeviceClassType = 1344 // -->0x540
getMajorDeviceClassType = 1280
//蓝牙遥控器
action = android.bluetooth.device.action.BOND_STATE_CHANGED
device = 54:03:84:90:FB:72
getAlias = Horion control FB72
type = 2
getDeviceClassType = 1292// -->0x50c
getMajorDeviceClassType = 1280
Android系统代码蓝牙连接界面上也是使用的 getMajorDeviceClassType 返回的值,显示对应的图标。
上面也看到了 getDeviceClassType 可以具体区分蓝牙键盘和鼠标。
其他没遇见的类型可以自己打印这些数据查看一下信息即可。
类型判断参考:
https://www.codenong.com/js12b69fe68246/
从上面日志看 getMajorDeviceClassType 很多蓝牙设备会相同,但是 getDeviceClassType 不一样。
getDeviceClassType 类型还更详细!
看起来 getDeviceClassType 是在 getMajorDeviceClassType 的类型上加上具体类型值。
蓝牙类型 SOD相关值介绍:
https://blog.csdn.net/Atlas12345/article/details/104872833
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); //发现设备广播
filter.addAction(BluetoothDevice.ACTION_DISCOVERY_FINISHED));//搜索结束广播
...
private BroadcastReceiver receiver = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent){
String action = intent.getAction();
if(BluetoothDevice.ACTION_FOUND.equals(action)){//发现蓝牙设备
BluetoothDevice device0 =intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
} else if (action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) {//蓝牙绑定状态改变
BluetoothDevice device1 =intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
}else if (action.equals(BluetoothDevice.ACTION_ACL_CONNECTED)) {//蓝牙耳机连接状态
BluetoothDevice device3 =intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
}else if (action.equals(BluetoothDevice.ACTION_PAIRING_REQUEST)) {//蓝牙配对请求状态
}
...//还有其他蓝牙相关广播
}
};
这里可以看到蓝牙相关的广播都是会有蓝牙对象回调的!
// LocalBluetoothManager 是SettingsLib里面的类,估计要源码应用或者导入SettingsLib包的应用才能获取到这个类。
LocalBluetoothManager mBluetoothManager = LocalBluetoothManager.getInstance(context, mOnInitCallback);
//已连接/绑定设备列表
Set bondedDevices = mBluetoothManager.getBluetoothAdapter().getBondedDevices();
LogUtil.debug("bondedDevices size = " + bondedDevices.size());
//未从已连接设备列表中找到断开的api,从所有的设备列表中进行判断连接状态后断开
Collection cachedDevices = mBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy();
LogUtil.debug("cachedDevices size = " + cachedDevices.size());
这个方法,普通应用是无法调用到的!
普通应用只能扫描发现蓝牙,把搜索的蓝牙放到列表中进行判断处理!
BluetoothDevice bluetoothDevice; //蓝牙设备对象
int type = device.getType(); //(1)功耗类型
BluetoothClass bluetoothClass = device.getBluetoothClass();
int deviceClassType = bluetoothClass.getDeviceClass(); //(2)更细的具体类型,系统代码中未定义相关数值
int deviceType = bluetoothClass.getMajorDeviceClass(); //(3)主要使用的具体类型,能简单区分类别
系统应用中也是使用 getMajorDeviceClass 进行判断的。
BluetoothClass.java 这个类里面。
//获取具体类型
public int getMajorDeviceClass() {
return (mClass & Device.Major.BITMASK);
}
//内部类定义具体数据
public static class Device {
private static final int BITMASK = 0x1FFC;
/**
* Defines all major device class constants.
* See {@link BluetoothClass.Device} for minor classes.
*/
public static class Major {
private static final int BITMASK = 0x1F00;
public static final int MISC = 0x0000;
public static final int COMPUTER = 0x0100; //电脑设备,对应10进制 256
public static final int PHONE = 0x0200; //手机设备,512
public static final int NETWORKING = 0x0300; //网络设备 ,不清楚什么设备,768
public static final int AUDIO_VIDEO = 0x0400; //音频视频设备,蓝牙耳机音响,1024
public static final int PERIPHERAL = 0x0500; //外部设备,比如蓝牙鼠标键盘,蓝牙遥控器,1280
public static final int IMAGING = 0x0600; //影像设备,1536
public static final int WEARABLE = 0x0700; //穿戴设备,1792
public static final int TOY = 0x0800; //玩具设备,2048
public static final int HEALTH = 0x0900; //健康检测设备,2304
public static final int UNCATEGORIZED = 0x1F00;
}
。。。
}