一、简介
Android设备,需要实时监控本机蓝牙连接其他蓝牙设备的状态,包含:连接、配对、开关3种状态。本文介绍了2种方法,各有优势,下面来到我的Studio一起瞅瞅吧~
二、定时器任务 + Handler + 功能方法
定时器任务 + Handler + 功能方法,此组合适用于页面初始化时、页面创建完毕后的2种情况,更新蓝牙连接状态的界面UI。
2.1 定时器任务
java
//在页面初始化加载时引用
updateInfoTimerTask();
private void updateInfoTimerTask() {
MyTimeTask infoTimerTask = new MyTimeTask(1000, new TimerTask() {
@Override
public void run() {
mHandler.sendEmptyMessage(1);
}
});
infoTimerTask.start();
}
//定时器任务工具类
import java.util.Timer;
import java.util.TimerTask;
public class MyTimeTask {
private Timer timer;
private TimerTask task;
private long time;
public MyTimeTask(long time, TimerTask task) {
this.task = task;
this.time = time;
if (timer == null){
timer = new Timer();
}
}
public void start(){
//每隔 time时间段 就执行一次
timer.schedule(task, 0, time);
}
public void stop(){
if (timer != null) {
timer.cancel();
if (task != null) {
//将原任务从队列中移除
task.cancel();
}
}
}
}
2.2 Handler
java
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case 1: {
//使用Handler发送定时任务消息,在页面初始化和应用运行中实时更新蓝牙的连接状态
checkBtDeviceConnectionStates(mContext);
}
break;
}
}
};
2.3 功能方法
java
public void checkBtDeviceConnectionStates(Context context) {
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) {
Log.i(TAG, "checkBtDeviceConnectionStates():蓝牙设备不支持 或 未开启蓝牙");
//更新界面UI
itemTvLogBtStatus.setText(R.string.bt_connect_state_off);
return;
}
Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
if (pairedDevices != null && !pairedDevices.isEmpty()) {
for (BluetoothDevice device : pairedDevices) {
// 检查 A2DP 连接状态(以 A2DP 为例)
boolean a2dpState = bluetoothAdapter.getProfileProxy(context, new BluetoothProfile.ServiceListener() {
@Override
public void onServiceConnected(int profile, BluetoothProfile proxy) {
if (profile == BluetoothProfile.A2DP) {
// 连接状态检查需要在这里进行,因为这是在服务连接后的回调中
int connectionState = ((BluetoothA2dp) proxy).getConnectionState(device);
switch (connectionState) {
case BluetoothProfile.STATE_CONNECTED:
itemTvLogBtStatus.setText(R.string.bt_connect_state_on);
Log.i(TAG, "checkBtDeviceConnectionStates():蓝牙设备 已连接");
break;
case BluetoothProfile.STATE_CONNECTING:
Log.i(TAG, "checkBtDeviceConnectionStates():蓝牙设备 正在连接");
break;
case BluetoothProfile.STATE_DISCONNECTED:
itemTvLogBtStatus.setText(R.string.bt_connect_state_off);
Log.i(TAG, "checkBtDeviceConnectionStates():蓝牙设备 未连接");
break;
case BluetoothProfile.STATE_DISCONNECTING:
Log.i(TAG, "checkBtDeviceConnectionStates():蓝牙设备 正在断开连接");
break;
}
// 注意:在检查完连接状态后,应该注销代理
bluetoothAdapter.closeProfileProxy(profile, proxy);
}
}
@Override
public void onServiceDisconnected(int profile) {
// 蓝牙服务断开连接的处理
}
}, BluetoothProfile.A2DP);
// 注意:上述 getProfileProxy 方法是异步的,并立即返回。
// 因此,上述的 connectionState 检查实际上是在回调中完成的。
// 如果你需要同步检查连接状态,那么可能需要一个更复杂的设计,例如使用 FutureTask 或 RxJava。
// 如果你不需要等待服务连接的结果,可以跳过 a2dpState 的值,因为这是一个整数,它通常表示服务连接的状态(不是设备的连接状态)
// 如果你需要检查其他蓝牙配置文件的连接状态,只需将 BluetoothProfile.A2DP 替换为相应的配置文件常量即可
}
}
}
三、Interface + Listener + 实现类
Interface + Listener + 实现类,此组合可实现监控蓝牙的连接、配对、开关3种状态,适用于页面创建完毕后。
3.1 Interface
java
public interface BluetoothInterface {
//监听手机本身蓝牙的状态
void listenBluetoothConnectState(int state);
int ACTION_STATE_OFF = 10;
int ACTION_STATE_TURNING_OFF = 11;
int ACTION_STATE_ON = 12;
int ACTION_STATE_TURNING_ON = 13;
//监听蓝牙设备的配对状态
void listenBluetoothBondState(int state);
int ACTION_BOND_NONE = 1;
int ACTION_BOND_BONDING = 2;
int ACTION_BOND_BONDED = 3;
//监听蓝牙设备连接和连接断开的状态
void listenBluetoothDeviceState(int state);
int ACTION_ACL_CONNECTED = 1;
int ACTION_ACL_DISCONNECT_REQUESTED = 0;
int ACTION_ACL_DISCONNECTED = -1;
}
3.2 Listener
Listener类,实际作用是启用BroadcastReceiver监听功能的包装工具类。
java
import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.util.Log;
import androidx.core.app.ActivityCompat;
//监听蓝牙设备状态的广播
public class BluetoothListener {
public static final String TAG = BluetoothListener.class.getSimpleName();
private Context mContext;
private BluetoothInterface mBluetoothInterface;
public BluetoothListener(Context context, BluetoothInterface bluetoothInterface) {
this.mContext = context;
this.mBluetoothInterface = bluetoothInterface;
observeBluetooth();
getBluetoothDeviceStatus();
}
public void observeBluetooth() {
IntentFilter lIntentFilter = new IntentFilter();
lIntentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); //蓝牙开关状态变化
lIntentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); //蓝牙设备配对状态变化
lIntentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED); //蓝牙已连接状态变化
lIntentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED); //蓝牙断开连接状态变化
lIntentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED); //蓝牙即将断开连接状态变化
mContext.registerReceiver(blueToothReceiver, lIntentFilter);
}
//判断蓝牙当前 开启/关闭 状态
public boolean getBluetoothDeviceStatus() {
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
boolean isEnabled = bluetoothAdapter.isEnabled();
Log.i(TAG, "蓝牙当前状态 :" + isEnabled);
return isEnabled;
}
public BroadcastReceiver blueToothReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.i(TAG, "蓝牙广播监听事件 onReceive,action:" + action);
//监听手机本身蓝牙状态的广播:手机蓝牙开启、关闭时发送
if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
switch (state) {
case BluetoothAdapter.STATE_OFF:
Log.i(TAG, "STATE_OFF 手机蓝牙 已关闭");
mBluetoothInterface.listenBluetoothConnectState(BluetoothInterface.ACTION_STATE_OFF);
break;
case BluetoothAdapter.STATE_TURNING_OFF:
Log.i(TAG, "STATE_TURNING_OFF 手机蓝牙 正在关闭");
mBluetoothInterface.listenBluetoothConnectState(BluetoothInterface.ACTION_STATE_TURNING_OFF);
break;
case BluetoothAdapter.STATE_ON:
Log.i(TAG, "STATE_ON 手机蓝牙 已开启");
mBluetoothInterface.listenBluetoothConnectState(BluetoothInterface.ACTION_STATE_ON);
break;
case BluetoothAdapter.STATE_TURNING_ON:
Log.i(TAG, "STATE_TURNING_ON 手机蓝牙 正在开启");
mBluetoothInterface.listenBluetoothConnectState(BluetoothInterface.ACTION_STATE_TURNING_ON);
break;
}
}
//监听蓝牙设备配对状态的广播:蓝牙设备配对和解除配对时发送
else if (action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) {
int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1);
switch (state) {
case BluetoothDevice.BOND_NONE:
Log.i(TAG, "BOND_NONE 删除配对设备");
mBluetoothInterface.listenBluetoothBondState(BluetoothInterface.ACTION_BOND_NONE);
break;
case BluetoothDevice.BOND_BONDING:
mBluetoothInterface.listenBluetoothBondState(BluetoothInterface.ACTION_BOND_BONDING);
Log.i(TAG, "BOND_NONE BOND_BONDING 正在配对");
break;
case BluetoothDevice.BOND_BONDED:
mBluetoothInterface.listenBluetoothBondState(BluetoothInterface.ACTION_BOND_BONDED);
Log.i(TAG, "BOND_BONDED 配对成功");
break;
}
}
//监听蓝牙设备连接和连接断开的广播:蓝牙设备连接上和断开连接时发送, 这两个监听的是底层的连接状态
else if (action.equals(BluetoothDevice.ACTION_ACL_CONNECTED)) {
mBluetoothInterface.listenBluetoothDeviceState(BluetoothInterface.ACTION_ACL_CONNECTED);
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
assert device != null;
if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
Log.i(TAG, "CONNECTED,蓝牙设备连接异常:权限拒绝!");
return;
}
Log.i(TAG, "CONNECTED,蓝牙设备连接成功:" + device.getName());
} else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)){
mBluetoothInterface.listenBluetoothDeviceState(BluetoothInterface.ACTION_ACL_DISCONNECTED);
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
assert device != null;
if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
Log.i(TAG, "DISCONNECTED,蓝牙设备断开连接:权限拒绝!");
return;
}
Log.i(TAG, "DISCONNECTED,蓝牙设备断开连接:" + device.getName());
} else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED)){
mBluetoothInterface.listenBluetoothDeviceState(BluetoothInterface.ACTION_ACL_DISCONNECT_REQUESTED);
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
assert device != null;
if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
Log.i(TAG, "DISCONNECT_REQUESTED,蓝牙设备即将断开连接:权限拒绝!");
return;
}
Log.i(TAG, "DISCONNECT_REQUESTED,蓝牙设备即将断开连接:" + device.getName());
}
}
};
public void close(){
if (blueToothReceiver != null){
mContext.unregisterReceiver(blueToothReceiver);
}
if (mContext != null){
mContext = null;
}
Log.d(TAG, "close()");
}
}
3.3 实现类
java
public class 你的Activity或Fragment或View封装类 implements BluetoothInterface {
private static String TAG = LogStatusView.class.getSimpleName();
private Context mContext;
private 你的Activity或Fragment或View封装类(Context context) {
this.mContext = context.getApplicationContext();
//蓝牙广播监听事件
mBluetoothListener = new BluetoothListener(mContext, this);
}
@Override
public void listenBluetoothConnectState(int state) {
if(state == ACTION_STATE_ON){
bluetoothConnectState = 0;
Log.i(TAG, "setBluetoothConnectState,手机蓝牙 已开启:" + state);
} else if (state == ACTION_STATE_OFF){
bluetoothConnectState = 1;
Log.i(TAG, "setBluetoothConnectState,手机蓝牙 已关闭:" + state);
}
}
@Override
public void listenBluetoothBondState(int state) {
if(state == ACTION_BOND_BONDING){
Log.i(TAG, "setBluetoothBondState,蓝牙正在配对:" + state);
} else if (state == ACTION_BOND_BONDED){
Log.i(TAG, "setBluetoothBondState,蓝牙配对成功:" + state);
}
}
@Override
public void listenBluetoothDeviceState(int state) {
if(state == ACTION_ACL_CONNECTED){
itemTvLogBtStatus.setText(R.string.bt_connect_state_on);
Log.i(TAG, "setBluetoothDeviceState,蓝牙设备连接成功:" + state);
} else if (state == ACTION_ACL_DISCONNECTED){
itemTvLogBtStatus.setText(R.string.bt_connect_state_off);
Log.i(TAG, "setBluetoothDeviceState,蓝牙设备断开连接:" + state);
}
}
//资源回收/注销代理方法
public void onReset() {
if (mBluetoothListener != null){
mBluetoothListener.close();
}
Log.i(TAG, "onReset()");
}
}
四、小结
以上就是我对这个功能的简单介绍,创作这篇文章是基于项目中的开发需求,记录一下,分享在此,有需要者请自取,写完收工。