方法不完整,仅是个人学习笔记。
1、前期准备
在Android应用中,BluetoothAdapter.getDefaultAdapter()
是一个静态方法,用于获取当前设备默认的蓝牙适配器实例。这个方法在蓝牙相关的操作中非常常用,因为它提供了访问蓝牙功能和设置的基础。
//如果设备支持蓝牙,这个方法将返回一个 BluetoothAdapter 对象。如果设备不支持蓝牙,这个方法将返回 null。
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter != null) {
// 蓝牙适配器可用,可以继续进行蓝牙相关的操作
} else {
// 蓝牙适配器不可用,可能需要通知用户或采取其他措施
}
注册蓝牙广播
public static final String ACTION_NAME_CHANGED = "android.bluetooth.device.action.NAME_CHANGED";
private static final String HID_BROADCAST_RECEIVER_ACTION =
"android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED";
public static final String ACTION_HF_INDICATORS_VALUE_CHANGED =
"android.bluetooth.headset.action.HF_INDICATORS_VALUE_CHANGED";
public static final String EXTRA_HF_INDICATORS_IND_ID =
"android.bluetooth.headset.extra.HF_INDICATORS_IND_ID";
public static final String EXTRA_HF_INDICATORS_IND_VALUE =
"android.bluetooth.headset.extra.HF_INDICATORS_IND_VALUE";
public static final String ACTION_PLAYING_STATE_CHANGED =
"android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED";
public final static int HF_INDICATOR_BATTERY_LEVEL_STATUS = 2;
public static final int BATTERY_LEVEL_UNKNOWN = -1;
public static final String VENDOR_SPECIFIC_HEADSET_EVENT_XEVENT = "+XEVENT";
public static final String VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV = "+IPHONEACCEV";
public static final String VENDOR_SPECIFIC_HEADSET_EVENT_XEVENT_BATTERY_LEVEL = "BATTERY";
public static final int VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV_BATTERY_LEVEL = 1;
private static final int HID_DEVICE_TYPE = 1280;
private static final int A2DP_DEVICE_TYPE = 1024;
private void registerBluetoothBroadcast() {
IntentFilter intentFilter = new IntentFilter();
//当蓝牙适配器的状态发生变化时触发,例如蓝牙被开启或关闭
intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
//当蓝牙设备的名称发生变化时触发
intentFilter.addAction(ACTION_NAME_CHANGED);
//当蓝牙适配器开始搜索新设备时触发
intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
//当蓝牙适配器完成搜索新设备时触发
intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
//当发现新的蓝牙设备时触发
intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
//当蓝牙设备请求配对时触发
intentFilter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);
//当蓝牙设备的配对状态发生变化时触发
intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
//当蓝牙音频设备的连接状态发生变化时触发
intentFilter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
//用于监听HID(人机界面设备)相关的广播
intentFilter.addAction(HID_BROADCAST_RECEIVER_ACTION);
//当蓝牙耳机设备的特定事件发生时触发
intentFilter.addAction(BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT);
//用于监听HF(免提)指示器值的变化
intentFilter.addAction(ACTION_HF_INDICATORS_VALUE_CHANGED);
//蓝牙音频流的播放状态发生变化时被触发
intentFilter.addAction(ACTION_PLAYING_STATE_CHANGED);
//用于过滤特定品牌的蓝牙耳机事件
intentFilter.addCategory(BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY + "."
+ BluetoothAssignedNumbers.PLANTRONICS);
//用于过滤特定品牌的蓝牙耳机事件
intentFilter.addCategory(BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY + "."
+ BluetoothAssignedNumbers.APPLE);
mContext.registerReceiver(bluetoothBroadcastReceiver,intentFilter);
}
a2dp连接器
public class A2dpConnector {
private Context mContext;
private BluetoothDevice mDevices;
private BluetoothA2dp mA2dpProfile;
public A2dpConnector(Context context) {
mContext = context;
}
public void a2dpConnect(BluetoothDevice device) {
mDevices = device;
BluetoothAdapter.getDefaultAdapter().getProfileProxy(mContext, connect, BluetoothProfile.A2DP);
}
public void a2dpDisconnect(BluetoothDevice device) {
mDevices = device;
BluetoothAdapter.getDefaultAdapter().getProfileProxy(mContext, disconnect, BluetoothProfile.A2DP);
}
public void setPriority(BluetoothDevice device, int priority) {
if (mA2dpProfile == null) {
return;
}
mA2dpProfile.setPriority(device,priority);
}
private BluetoothProfile.ServiceListener connect = new BluetoothProfile.ServiceListener() {
@Override
public void onServiceDisconnected(int profile) {
mDevices = null;
}
@Override
public void onServiceConnected(int profile, BluetoothProfile proxy) {
mA2dpProfile = (BluetoothA2dp) proxy;
if (mDevices == null) {
return;
}
setPriority(mDevices,100);
mA2dpProfile.connect(mDevices);
}
};
private BluetoothProfile.ServiceListener disconnect = new BluetoothProfile.ServiceListener() {
@Override
public void onServiceDisconnected(int profile) {
mDevices = null;
}
@Override
public void onServiceConnected(int profile, BluetoothProfile proxy) {
mA2dpProfile = (BluetoothA2dp) proxy;
if (mDevices == null) {
return;
}
setPriority(mDevices,0);
mA2dpProfile.disconnect(mDevices);
}
};
}
2、打开/关闭蓝牙开关
当蓝牙开关时,去获取当前蓝牙状态,更新界面上的蓝牙开关控件的选中状态。
//打开蓝牙
bluetoothAdapter.enable()
//关闭蓝牙
bluetoothAdapter.disable()
收蓝牙状态改变广播
//关于广播接收后续就省略写下边两条了
String action = intent.getAction();
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
case BluetoothAdapter.ACTION_STATE_CHANGED:
//获取蓝牙适配器的新状态
int blueState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,0);
switch (blueState) {
case BluetoothAdapter.STATE_TURNING_ON:
//蓝牙适配器正在开启
break;
case BluetoothAdapter.STATE_ON:
//蓝牙适配器开启
//设置蓝牙设备的名称
BluetoothLocalAdapter.getInstance().
setName(XXX);
mBluetoothPairedInfoList.clear();
mBluetoothPairedDevicesList.clear();
Set<BluetoothDevice> pairedDevices = BluetoothLocalAdapter.getInstance().getBondedDevices();
if(pairedDevices != null && pairedDevices.size()>0){
for(BluetoothDevice device:pairedDevices) {
BluetoothDeviceInfo bluetoothDeviceInfo = new BluetoothDeviceInfo();
bluetoothDeviceInfo.setDeviceName(device.getName());
bluetoothDeviceInfo.setDeviceMacAddress(device.getAddress());
bluetoothDeviceInfo.setDeviceConnectStatus(BluetoothProfile.STATE_DISCONNECTED);
bluetoothDeviceInfo.setDeviceAddDate(getSavePairedDeviceInfo(mContext,device.getAddress()
));
mBluetoothPairedInfoList.add(bluetoothDeviceInfo);
mBluetoothPairedDevicesList.add(device);
}
onPairedBluetoothDeviceCallback(mBluetoothPairedInfoList, mBluetoothPairedDevicesList);
}
//开始搜索新设备(如果蓝牙已开启)
bluetoothAdapter.startScanning();
//设置蓝牙设备的可见性超时时间
bluetoothAdapter.setDiscoverableTimeout(0);
//设置蓝牙设备的扫描模式。这个方法接受两个参数:第一个参数是扫描模式,第二个参数是可见性超时时间。
//BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE表示设备在搜索其他设备的同时也允许被其他设备搜索。
//这意味着设备将广播其存在,并且可以接收其他设备的连接请求。
bluetoothAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE,0);
//更新蓝牙开关状态ui
updateBluetoothSwitchStatus(true);
//保存蓝牙状态,方便后续相关业务
SharedPreferencesUtil.getInstance(mContext).
saveBtSwitchStatus(KEY_BLUETOOTH_SWITCH, true);
break;
case BluetoothAdapter.STATE_TURNING_OFF:
//蓝牙适配器正在关闭
break;
case BluetoothAdapter.STATE_OFF:
//蓝牙适配器关闭
bluetoothAdapter.setDiscoverableTimeout(0);
//设置蓝牙设备的扫描模式。
//BluetoothAdapter.SCAN_MODE_CONNECTABLE表示设备在搜索其他设备的同时只允许被其他设备搜索,而不会主动搜索其他设备。
bluetoothAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE,0);
//清除“可用设备”
clearAvailableDevice();
updateBluetoothSwitchStatus(false);
SharedPreferencesUtil.getInstance(mContext).
saveBtSwitchStatus(KEY_BLUETOOTH_SWITCH, false);
break;
default:
break;
}
break;
3、扫描相关
//开始扫描
bluetoothLocalAdapter.startScanning()
case BluetoothAdapter.ACTION_DISCOVERY_STARTED:
//清空蓝牙可用设备列表,为新的搜索做准备
mBluetoothAvailableDevicesList.clear();
break;
case BluetoothAdapter.ACTION_DISCOVERY_FINISHED:
break;
4、可用设备
case BluetoothDevice.ACTION_FOUND:
//检查新发现的设备对象device是否不为null,并且设备的蓝牙类(BluetoothClass)也不为null
if (device != null && device.getBluetoothClass() != null) {
//从设备的蓝牙类中获取主要设备类别
int iBluetoothDeviceType = device.getBluetoothClass().getMajorDeviceClass();
//检查设备的主要类别是否为HID(人机界面设备)类型或A2DP(高级音频分布配置文件)类型
if (iBluetoothDeviceType == HID_DEVICE_TYPE || iBluetoothDeviceType == A2DP_DEVICE_TYPE) {
//用于标记新发现的设备是否已经存在于可用设备列表中
boolean isExist = false;
if (mBluetoothAvailableDevicesList != null) {
for (int i = 0; i < mBluetoothAvailableDevicesList.size(); i++) {
if (device.getAddress().equals(mBluetoothAvailableDevicesList.get(i).getAddress())) {
isExist = true;
break;
}
}
}
if (!isExist) {
mBluetoothAvailableDevicesList.add(device);
}
//已配对设备就不显示在可用设备里了
if (mBluetoothPairedDevicesList != null && mBluetoothPairedDevicesList.size() > 0) {
for (int i = 0; i < mBluetoothPairedDevicesList.size(); i++) {
if (bluetoothDevice.getAddress().equals(mBluetoothPairedDevicesList.get(i).getAddress())) {
mBluetoothAvailableDevicesList.remove(device);
}
}
}
onAvailableBluetoothDeviceCallback(mBluetoothAvailableDevicesList);
}
}
break;
5、配对
public void startPairing(BluetoothDevice device) {
//检查当前蓝牙适配器是否正在进行设备发现(discovery)过程
if (bluetoothAdapter.isDiscovering()) {
//取消搜索
bluetoothAdapter.cancelDiscovery();
}
if (device!= null) {
device.createBond()
}
}
case BluetoothDevice.ACTION_BOND_STATE_CHANGED:
if (device == null) {
break;
}
switch (device.getBondState()) {
case BluetoothDevice.BOND_BONDING:
//当设备正在配对
break;
case BluetoothDevice.BOND_BONDED:
//当设备已配对
//用于标记设备地址是否已经在已配对设备列表中
boolean addBondedAddressEqual = false;
if (mBluetoothPairedDevicesList != null && mBluetoothPairedDevicesList.size()>0) {
for (int i = 0; i < mBluetoothPairedDevicesList.size(); i++) {
if (device.getAddress() != null) {
if (device.getAddress().equals(mBluetoothPairedDevicesList.get(i).getAddress())) {
addBondedAddressEqual = true;
}
}
}
}
if (!addBondedAddressEqual) {
//设备地址不在已配对设备列表中
BluetoothDeviceInfo bluetoothDeviceInfo = new BluetoothDeviceInfo();
bluetoothDeviceInfo.setDeviceName(bluetoothDevice.getName());
bluetoothDeviceInfo.setDeviceMacAddress(bluetoothDevice.getAddress());
bluetoothDeviceInfo.setDeviceConnectStatus(BluetoothProfile.STATE_DISCONNECTED);
mBluetoothPairedInfoList.add(bluetoothDeviceInfo);
mBluetoothPairedDevicesList.add(bluetoothDevice);
}
onPairedBluetoothDeviceCallback(mBluetoothPairedInfoList, mBluetoothPairedDevicesList);
//在可用设备list里remove此设备
if (mBluetoothAvailableDevicesList != null && mBluetoothAvailableDevicesList.size() > 0) {
mBluetoothAvailableDevicesList.remove(device);
}
onAvailableBluetoothDeviceCallback(mBluetoothAvailableDevicesList);
if (device.getBluetoothClass() != null) {
int iBluetoothDeviceType = device.getBluetoothClass().getMajorDeviceClass();
if (iBluetoothDeviceType == A2DP_DEVICE_TYPE) {
//如果设备的主要类别是A2DP,则调用mBluetoothA2dpConnector的a2dpConnect方法,并传入设备对象。
//尝试连接到支持A2DP的蓝牙音频设备,如蓝牙耳机或扬声器。
mA2dpConnector.a2dpConnect(device);
} else if (iBluetoothDeviceType == HID_DEVICE_TYPE) {
//如果设备的主要类别是HID,则调用mBluetoothHidConnector的hidConnect方法,并传入设备对象。
//尝试连接到支持HID的蓝牙设备,如蓝牙键盘或鼠标。
mHidConnector.hidConnect(device);
}
}
break;
case BluetoothDevice.BOND_NONE:
//设备未配对
break;
default:
break;
}
break;
6、连接
//连接a2dp
A2dpConnector.a2dpConnect(bluetoothDevice);
//断连a2dp
A2dpConnector.a2dpDisconnect(bluetoothDevice);
case BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED:
if (device == null || device.getBluetoothClass() == null) {
break;
}
int a2dpState = intent.getIntExtra(BluetoothA2dp.EXTRA_STATE, BluetoothA2dp.STATE_DISCONNECTED);
int iA2dpDeviceType = device.getBluetoothClass().getMajorDeviceClass();
switch (a2dpState) {
case BluetoothA2dp.STATE_DISCONNECTED:
//a2dp连接断开
break;
case BluetoothA2dp.STATE_CONNECTING:
//a2dp连接中
break;
case BluetoothA2dp.STATE_CONNECTED:
//a2dp连接成功
break;
case BluetoothA2dp.STATE_DISCONNECTING:
//a2dp断连中
break;
default:
break;
}
break;
8、蓝牙耳机指示器值变化
case ACTION_HF_INDICATORS_VALUE_CHANGED:
if (device == null) {
break;
}
//指示器的ID
int indicatorId = intent.getIntExtra(EXTRA_HF_INDICATORS_IND_ID, -1);
//指示器的值
int indicatorValue = intent.getIntExtra(EXTRA_HF_INDICATORS_IND_VALUE, -1);
//检查指示器的ID是否为电池电量指示器
if (indicatorId == HF_INDICATOR_BATTERY_LEVEL_STATUS ) {
updateBatteryLevel(device, indicatorValue);
}
break;
case BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT:
if (device == null) {
break;
}
String cmd = intent.getStringExtra(BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD);
if (cmd == null) {
return;
}
int cmdType = intent.getIntExtra(
BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE, -1);
if (cmdType != BluetoothHeadset.AT_CMD_TYPE_SET) {
return;
}
Object[] args = (Object[]) intent.getExtras().get(
BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS);
if (args == null) {
return;
}
int batteryPercent = BATTERY_LEVEL_UNKNOWN;
switch (cmd) {
case VENDOR_SPECIFIC_HEADSET_EVENT_XEVENT:
batteryPercent = getBatteryLevelFromXEventVsc(args);
break;
case VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV:
batteryPercent = getBatteryLevelFromAppleBatteryVsc(args);
break;
}
if (batteryPercent != BATTERY_LEVEL_UNKNOWN) {
updateBatteryLevel(device, batteryPercent);
}
break;
android.bluetooth.headset.action.HF_INDICATORS_VALUE_CHANGED: 这个广播动作是当蓝牙耳机的某些指示器值发生变化时发出的。这些指示器通常包括耳机的电池电量、信号强度等。应用程序可以通过监听这个广播来获取这些指示器的最新值。
BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT: 这个广播动作是用于处理来自蓝牙耳机的厂商特定事件。不同的耳机厂商可能会提供一些特定的功能或事件,这些事件可以通过这个广播动作来通知应用程序。例如,某些耳机可能会有特殊的按键功能,或者支持高级的语音识别功能。