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

一、简介

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

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

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

2.1 定时器任务

//在页面初始化加载时引用
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

private Handler mHandler = new Handler() {public void handleMessage(Message msg) {switch (msg.what) {case 1: {//使用Handler发送定时任务消息,在页面初始化和应用运行中实时更新蓝牙的连接状态checkBtDeviceConnectionStates(mContext);}break;}}
};

2.3 功能方法

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

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监听功能的包装工具类。

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 实现类

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.mzph.cn/bicheng/20617.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

写字静不下心?不如试试这些“笨方法”

夏天悄悄热起来啦&#xff5e;有人说&#xff0c;想踏踏实实写一会儿&#xff0c;但又静不下心&#xff0c;耐不住性子&#xff0c;快收下这四个小锦囊&#xff0c;与古人一起笨拙精进吧&#xff01;    1、不论输赢      每次课前&#xff0c;暄桐林曦老师总会强调&am…

AlloyTeam Web前端大会:深入探索前端的无限可能

AlloyTeam Web前端大会&#xff1a;深入探索前端的无限可能 在数字化浪潮的推动下&#xff0c;Web前端技术日新月异&#xff0c;成为引领行业发展的重要力量。AlloyTeam Web前端大会作为业界的盛会&#xff0c;汇聚了众多前端领域的精英&#xff0c;共同探讨前端的未来发展趋势…

内网-win1

一、概述 1、工作组&#xff1a;将不同的计算机按功能(或部门)分别列入不同的工作组 (1)、查看&#xff08;windows&#xff09; 查看当前系统中所有用户组&#xff1a;打开命令行--》net localgroup查看组中用户&#xff1a;打开命令行 --》net localgroup 后接组名查看用户…

FreeRTOS任务调度机制(源码讲解)

任务的调度机制(核心是链表)&#xff01;&#xff01;&#xff01; 使用链表来管理任务 在我前面写的FreeRTOS任务(深入到源码进行分析)&#xff0c;我创建了三个任务&#xff0c;他们的优先级都是一样的&#xff0c;所以他们在FreeRTOS中是轮流执行的&#xff0c;实际上&…

19.1 简易抽奖

准备一个数组&#xff0c;里面添加10个奖品数据&#xff0c;让奖品数据快速的在盒子中随机显示&#xff0c;通过按钮控制盒子里面的内容停止。 效果图&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8">&…

解释Python中的PEP 8是什么 为什么它很重要

PEP 8 是 Python 的一个编码规范&#xff0c;也称为 Python 增强提案 8。它提供了一系列关于如何编写清晰、一致的 Python 代码的指导原则。这些原则涵盖了代码布局、命名约定、注释、文档字符串、编码建议、导入语句、异常、全局变量、嵌套等方面。 为什么PEP 8很重要&#x…

npm install pubsub-js报错的解决汇总

我在练习谷粒商城P83时&#xff0c;选择分类时触发向后端请求选择分类catId绑定的品牌数据&#xff0c;发现前端控制台报错&#xff1a; "PubSub is not definded",找不到pubsub。 因为缺少pubsub包&#xff0c;所以开始安装此包。 于是在网上一顿搜索猛如虎&…

xilinx ip自带XDC只读

检查生成的IP核再目录下显示的文件类型是不是.xcix 如果是的话&#xff0c;重新生成为.xci 再二次编辑即可 或者 将框柱的部分不选择&#xff0c;从新生成

MongoDB CRUD操作:批量写操作

MongoDB CRUD操作&#xff1a;批量写操作 文章目录 MongoDB CRUD操作&#xff1a;批量写操作关于批量操作的顺序bulkWrite()支持的方法举例向分片集合批量插入的策略预分割集合无序写入 mongos避免单调节流 MongoDB提供了批量执行写入操作的能力&#xff0c;但批量写入操作只影…

《计算机工程与应用》最新投稿经验2024年5月

研二下第一次投稿&#xff0c;深度学习长时间序列预测方向&#xff0c;选择了《计算机工程与应用》期刊&#xff0c;是CSCD扩展刊北大核心&#xff0c;且在24年被EI收录等等。4.10交稿到最后5.31收到录用通知&#xff0c;历时不到2个月&#xff0c;总的来说编辑部效率确实高。 …

LLM背后的基础模型 1

写在最前面的话 任何开源技术是最有生命力的&#xff0c;也是最具分享精神的。一直觉得大模型领域需要有一个系列能够从零开始系统性的讲述领域知识&#xff0c;给与这个领域的从业人员或者对其有兴趣的门外汉及时的帮助。国外承担“布道者”的公司众多&#xff0c;而数砖公司…

云技术最全详解

目录 云技术 1.定义 2.特点 2.类型 2.1IaaS&#xff08;基础设置即服务&#xff09; 2.2PaaS&#xff08;平台即服务&#xff09; 2.3SaaS&#xff08;软件即服务&#xff09; 3.云技术模型 3.1公有云 3.2私有云 3.3混合云 云技术 1.定义 云技术是一种云计算和存储…

如何让 LightRoom 每次导入照片后不自动弹出 SD 卡 LR

如何让 LightRoom 每次导入照片后不自动弹出 SD 卡 LR 在导入窗口左上角有个选项&#xff1a; 导入后弹出 把这个去掉就可以了

Rust 基本语法

变量 整数 无符号整数以u开头有符号整数以i开头对于Rust默认整数是i32对于整数溢出 开发模式中编译会检测溢出&#xff0c;如果溢出会导致程序panic发布模式中编译不会检查可能会导致的溢出&#xff0c;如果运行时发生溢出&#xff0c;会执行环绕操作保证数值在范围内且程序不…

Spark大数据 掌握RDD的创建

在Apache Spark中&#xff0c;弹性分布式数据集&#xff08;Resilient Distributed Dataset&#xff0c;简称RDD&#xff09;是一个核心的数据结构&#xff0c;用于表示不可变、可分区、可并行操作的元素集合。理解并掌握RDD的创建是使用Spark进行大数据处理的关键步骤之一。 …

Qt Creator(Qt 6.6)拷贝一行

Edit - Preference - Environment&#xff1a; 可看到&#xff0c;拷贝一行的快捷键是&#xff1a; ctrl Ins

数据结构-堆(带图)详解

前言 本篇博客我们来仔细说一下二叉树顺序存储的堆的结构&#xff0c;我们来看看堆到底如何实现&#xff0c;以及所谓的堆排序到底是什么 &#x1f493; 个人主页&#xff1a;普通young man-CSDN博客 ⏩ 文章专栏&#xff1a;数据结构_普通young man的博客-CSDN博客 若有问题 评…

程序员是牛马吗?

在今天的讨论中&#xff0c;一个引人深思的问题被提出&#xff1a;程序员是否只是现代社会的牛马&#xff1f;这个问题迅速引发了激烈的争论。许多程序员开始意识到&#xff0c;尽管他们辛勤工作&#xff0c;但最终可能仍无法摆脱被剥削的命运。因此&#xff0c;他们渴望改变&a…

MySQL(二)-基础操作

一、约束 有时候&#xff0c;数据库中数据是有约束的&#xff0c;比如 性别列&#xff0c;你不能填一些奇奇怪怪的数据~ 如果靠人为的来对数据进行检索约束的话&#xff0c;肯定是不行的&#xff0c;人肯定会犯错~因此就需要让计算机对插入的数据进行约束要求&#xff01; 约…

混合模型方差分析

文章目录 一、说明二、受试者“间”因素和受试者“内”因素的意思&#xff1f;三、混合模型方差分析回答 3 件事四、混合模型方差分析的假设 一、说明 在本文中&#xff0c;我将讨论一种称为混合模型方差分析的方差分析变体&#xff0c;也称为具有重复测量的 2 因素方差分析。…