【android 蓝牙开发——传统蓝牙】
【android 蓝牙开发——BLE(低功耗)蓝牙 2021-10-09更新】
总结一下蓝牙开发的基本使用以及蓝牙耳机的断开和链接。
所以需权限:
注意这里需要位置权限。
开启权限:
ActivityResultLauncher bluetoothOpenLaunch;
private void startBluetooth() {
bluetoothOpenLaunch = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback() {
@Override
public void onActivityResult(ActivityResult result) {
System.out.println("MainActivity.onActivityResult" + result.getResultCode());
if (Activity.RESULT_OK == result.getResultCode()) {
getPermission();
}
}
});
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
ArrayList arrayListOf = new ArrayList<>();
arrayListOf.add(Manifest.permission.BLUETOOTH_CONNECT);
PermissionUtils.permission(String.valueOf(arrayListOf))
.callback(new PermissionUtils.SimpleCallback() {
@Override
public void onGranted() {
System.out.println("MainActivity.onGranted");
bluetoothOpenLaunch.launch(intent);
}
@Override
public void onDenied() {
System.out.println("MainActivity.onDenied");
ToastUtils.showLong("请开启蓝牙权限");
}
}).request();
} else {
bluetoothOpenLaunch.launch(intent);
}
}
private void getPermission() {
ArrayList arrayListOf = new ArrayList<>();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
arrayListOf.add(Manifest.permission.BLUETOOTH_SCAN);
arrayListOf.add(Manifest.permission.BLUETOOTH_CONNECT);
arrayListOf.add(Manifest.permission.BLUETOOTH_ADVERTISE);
}
arrayListOf.add(Manifest.permission.BLUETOOTH);
arrayListOf.add(Manifest.permission.BLUETOOTH_ADMIN);
arrayListOf.add(Manifest.permission.ACCESS_FINE_LOCATION);
arrayListOf.add(Manifest.permission.ACCESS_COARSE_LOCATION);
PermissionUtils.permission(String.valueOf(arrayListOf))
.callback(new PermissionUtils.SimpleCallback() {
@Override
public void onGranted() {
ToastUtils.showLong("蓝牙相关权限已成功授权");
BluetoothManager blueManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
//mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
mBluetoothAdapter = blueManager.getAdapter();
}
@Override
public void onDenied() {
ToastUtils.showLong("请开启蓝牙权限");
}
}).request();
}
监听蓝牙连接配对等相关广播,建议直接采用以下方式:(也有其他方法,搜索低功耗蓝牙的方式 startLeScan )
//注册BoradcasrReceiver
private void registerReceiver() {
IntentFilter discoveryFilter = new IntentFilter();
discoveryFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
discoveryFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
discoveryFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
discoveryFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
discoveryFilter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);
discoveryFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
discoveryFilter.addAction(BluetoothDevice.ACTION_FOUND);
registerReceiver(discoveryReceiver, discoveryFilter);
}
//蓝牙搜索广播的接收器
@SuppressLint("MissingPermission")
private BroadcastReceiver discoveryReceiver = new BroadcastReceiver() {
String pin = "0000"; //此处为你要连接的蓝牙设备的初始密钥,一般为 1234 或 0000
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); //获取设备,发现远程蓝牙设备
if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
Log.i(TAG, "onReceive: 开始搜索");
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
Log.i(TAG, "onReceive: 搜索结束");
} else if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// //获取扫描到的设备
String name = bluetoothDevice.getName();
String address = bluetoothDevice.getAddress();
Log.i(TAG, "onReceive: name=" + name + " address=" + address);
/*if (bluetoothDevice.getBondState() == BluetoothDevice.BOND_BONDED) {
Log.i(TAG, "已配对 onReceive: name=" + name + " address=" + address);
} else {
}*/
//已经配对
boolean isExist = false;
for (DeviceBean device : bluetoothDevices) {
if (device.getAddress().equals(address)) {
isExist = true;
}
}
if (!isExist) {
bluetoothDevices.add(new DeviceBean(name, address));
mAdapter.notifyDataSetChanged();
}
} else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
//Log.i(TAG, "onReceive: 绑定状态改变");
int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR);
Log.i(TAG, "onReceive: 绑定状态改变 state=" + state);
if (state == 12) {
Log.i(TAG, "onReceive: 绑定成功 ");
ToastUtils.showLong("绑定成功");
String name = bluetoothDevice.getName();
String address = bluetoothDevice.getAddress();
boolean isExist = false;
for (DeviceBean device : pairedDevices) {
if (device.getAddress().equals(address)) {
isExist = true;
}
}
if (!isExist) {
/*for (DeviceBean device : pairedDevices) {
device.setStatus(false);
}*/
DeviceBean deviceBean = new DeviceBean(name, address);
deviceBean.setStatus(true);
pairedDevices.add(0, deviceBean);
mDevicePairedAdapter.notifyDataSetChanged();
} else {
for (DeviceBean device : pairedDevices) {
if (device.getAddress().equals(address)) {
device.setStatus(true);
mDevicePairedAdapter.notifyDataSetChanged();
break;
}
}
}
}
} else if (BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED.equals(action)) {
//Log.i(TAG, "onReceive: 连接状态改变");
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, BluetoothAdapter.ERROR);
String name = bluetoothDevice.getName();
String address = bluetoothDevice.getAddress();
Log.i(TAG, "onReceive: 连接状态改变 state=" + state);
switch (state) {
case 0://断开成功
for (DeviceBean device : pairedDevices) {
if (device.getAddress().equals(address)) {
device.setStatus(false);
mDevicePairedAdapter.notifyDataSetChanged();
break;
}
}
break;
//case 1: break;
case 2://连接成功
Log.i(TAG, "onReceive: 连接成功 address=" + address);
ToastUtils.showLong("连接成功");
for (DeviceBean device : pairedDevices) {
if (device.getAddress().equals(address)) {
device.setStatus(true);
mDevicePairedAdapter.notifyDataSetChanged();
break;
}
}
break;
default:
break;
}
} else if (BluetoothDevice.ACTION_PAIRING_REQUEST.equals(action)) {
Log.i(TAG, "onReceive: 配对");
try {
// bluetoothDevice.setPairingConfirmation(true);
// abortBroadcast();
// bluetoothDevice.setPin(pin.getBytes());
//1:
/* ClsUtils.setPairingConfirmation(bluetoothDevice.getClass(),bluetoothDevice,true);
//2:如果没有将广播终止,则会出现一个一闪而过的配对框。
abortBroadcast();
//3.调用setPin方法进行配对..
boolean ret = ClsUtils.setPin(bluetoothDevice.getClass(), bluetoothDevice, pin);
System.out.println("ConnectingDevicesActivity.onReceive ret="+ret);*/
} catch (Exception e) {
throw new RuntimeException(e);
}
} else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
Log.i(TAG, "onReceive: 蓝牙开关状态改变");
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
switch (state) {
case BluetoothAdapter.STATE_OFF:
break;
case BluetoothAdapter.STATE_ON:
break;
}
} else {
Log.i(TAG, "onReceive: else action=" + action);
}
}
};
我们也可以获取已配对蓝牙列表:
private void initData() {
Set bondedDevices = mBluetoothAdapter.getBondedDevices();
if (bondedDevices != null && bondedDevices.size() > 0) {
for (BluetoothDevice bondedDevice : bondedDevices) {
System.out.println("ConnectingDevicesActivity.initData name==" + bondedDevice.getName());
DeviceBean deviceBean = new DeviceBean(bondedDevice.getName(), bondedDevice.getAddress());
pairedDevices.add(deviceBean);
}
mDevicePairedAdapter.notifyDataSetChanged();
}
}
蓝牙耳机断开和连接的具体方法:
public boolean isDisconnected = false;
/**
* 断开蓝牙设备连接
*
* @param bluetoothDevice BluetoothDevice
*/
public void disconnect(BluetoothDevice bluetoothDevice) {
currentBluetoothDevice = bluetoothDevice;
//获取A2DP代理对象
mBluetoothAdapter.getProfileProxy(this, disconnectProfileServiceListener, BluetoothProfile.HEADSET);
//获取HEADSET代理对象
mBluetoothAdapter.getProfileProxy(this, disconnectProfileServiceListener, BluetoothProfile.A2DP);
}
private final BluetoothProfile.ServiceListener disconnectProfileServiceListener = new BluetoothProfile.ServiceListener() {
@Override
public void onServiceDisconnected(int profile) {
System.out.println("ConnectingDevicesActivity.onServiceDisconnected profile="+profile);
}
@Override
public void onServiceConnected(int profile, BluetoothProfile proxy) {
try {
if (profile == BluetoothProfile.HEADSET) {
//使用HEADSET的协议断开蓝牙设备(使用了反射技术调用断开的方法)
BluetoothHeadset bluetoothHeadset = (BluetoothHeadset) proxy;
boolean isDisConnect = false;
try {
Method connect = null;
if (isDisconnected) {
connect = bluetoothHeadset.getClass().getDeclaredMethod("disconnect", BluetoothDevice.class); //disconnect connect
} else {
connect = bluetoothHeadset.getClass().getDeclaredMethod("connect", BluetoothDevice.class); //disconnect connect
}
connect.setAccessible(true);
isDisConnect = (boolean) connect.invoke(bluetoothHeadset, currentBluetoothDevice);
if (isDisconnected) {
Log.d(TAG, "isDisConnect:" + (isDisConnect ? "断开通话成功" : "断开通话失败") + currentBluetoothDevice.getName());
} else {
Log.d(TAG, "isDisConnect:" + (isDisConnect ? "链接通话成功" : "链接通话失败") + currentBluetoothDevice.getName());
}
} catch (Exception e) {
e.printStackTrace();
}
}
if (profile == BluetoothProfile.A2DP) {
//使用A2DP的协议断开蓝牙设备(使用了反射技术调用断开的方法)
BluetoothA2dp bluetoothA2dp = (BluetoothA2dp) proxy;
boolean isDisConnect = false;
try {
Method connect = null;
if (isDisconnected) {
connect = bluetoothA2dp.getClass().getDeclaredMethod("disconnect", BluetoothDevice.class);
} else {
connect = bluetoothA2dp.getClass().getDeclaredMethod("connect", BluetoothDevice.class);
}
connect.setAccessible(true);
isDisConnect = (boolean) connect.invoke(bluetoothA2dp, currentBluetoothDevice);
if (isDisconnected) {
Log.d(TAG, "isDisConnect:" + (isDisConnect ? "断开音频成功" : "断开音频失败") + currentBluetoothDevice.getName());
} else {
Log.d(TAG, "isDisConnect:" + (isDisConnect ? "链接音频成功" : "链接音频失败") + currentBluetoothDevice.getName());
}
} catch (Exception e) {
e.printStackTrace();
}
if (isDisConnect) {
for (DeviceBean device : pairedDevices) {
if (device.getAddress().equals(currentBluetoothDevice.getAddress())) {
device.setStatus(!isDisconnected);
mDevicePairedAdapter.notifyDataSetChanged();
break;
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
};