Android设备实时监控蓝牙的连接、配对、开关3种状态

embedded/2024/10/20 20:56:03/

一、简介

Android设备,需要实时监控本机蓝牙连接其他蓝牙设备的状态,包含:连接、配对、开关3种状态。本文介绍了2种方法,各有优势,下面来到我的Studio一起瞅瞅吧~

二、定时器任务 + Handler + 功能方法

定时器任务 + Handler + 功能方法,此组合适用于页面初始化时、页面创建完毕后的2种情况,更新蓝牙连接状态的界面UI。

2.1 定时器任务

java">//在页面初始化加载时引用
updateInfoTimerTask();private void updateInfoTimerTask() {MyTimeTask infoTimerTask = new MyTimeTask(1000, new TimerTask() {@Overridepublic 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():蓝牙设备不支持 或 未开启蓝牙");//更新界面UIitemTvLogBtStatus.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() {@Overridepublic 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);}}@Overridepublic 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() {@Overridepublic 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);}@Overridepublic 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);}}@Overridepublic 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);}}@Overridepublic 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()");}}

四、小结

以上就是我对这个功能的简单介绍,创作这篇文章是基于项目中的开发需求,记录一下,分享在此,有需要者请自取,写完收工。


http://www.ppmy.cn/embedded/45156.html

相关文章

MySQL alter 语句

ALTER TABLE user ADD COLUMN cdkey varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT CD-Key, ADD COLUMN erp_userid varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT ERP用户ID, ADD UNIQUE INDEX un…

Chatgpt-4o:人工智能领域的革新与未来展望

随着科技的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;领域正经历着前所未有的变革。作为这一领域的佼佼者&#xff0c;OpenAI于2024年5月13日正式发布了其最新旗舰模型——Chatgpt-4o。这一模型不仅在技术上取得了重大突破&#xff0c;更在用户体验、应用场景以及…

网页如何给js后台传递数字类型参数

网页无法通过get方法传递数字参数给js后台&#xff0c;就是网页端写的是数字参数&#xff0c;传递给后台也变成了数字字符串。而js对数字类型和字符串类型是不相同的。由于我们的代码是通过中间件挂载接口的&#xff0c;通过joi库检查参数。 const Joi require(joi); //注意&…

Vue2 + Element UI 封装 Table 递归多层级列表头动态

1、在 components 中创建 HeaderTable 文件夹&#xff0c;在创建 ColumnItem.vue 和 index.vue。 如下&#xff1a; 2、index.vue 代码内容&#xff0c;如下&#xff1a; <template><div><el-table:data"dataTableData"style"width: 100%"…

算法第三天力扣第69题:X的平方根

69. x 的平方根 (可点击下面链接或复制网址进行做题) https://leetcode.cn/problems/sqrtx/https://leetcode.cn/problems/sqrtx/ 给你一个非负整数 x ,计算并返回 x 的 算术平方根 。 由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。 注意:不允许使用任何内…

nn.Embedding使用

nn.Embedding使用 Embedding.weight会从标准正态分布中初始化成大小为&#xff08;num_embeddings, embedding_dim&#xff09;的矩阵 PE矩阵的作用就是替换这个标准正态分布 input中的标号表示从矩阵对应行获取权重来表示单词 # 1.设置embedding结构 max_seq_len 1000 # 句…

L9110S电机控制模块

1.L9110s控制小车前进后退左右 接通VCC&#xff0c;GND 模块电源指示灯亮&#xff0c; 以下资料来源官方&#xff0c;但是仍需我们调制 &#xff08;前进&#xff09;&#xff1a; L1A输入低电平&#xff0c;L1B输入高电平 R1A输入低电平&#xff0c;R1B输入高电平 &a…

Github Page 部署失败

添加 .gitmodules 文件 [submodule "themes/ayer"]path themes/ayerurl https://github.com/Shen-Yu/hexo-theme-ayer.git 添加 .nojekyll 文件