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

一、简介

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()");
    }

}

四、小结

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

相关推荐
IT学长编程1 分钟前
计算机毕业设计 基于协同过滤算法的个性化音乐推荐系统的设计与实现 Java实战项目 附源码+文档+视频讲解
java·spring boot·毕业设计·毕业论文·协同过滤算法·计算机毕业设计选题·个性化音乐推荐系统
小小娥子6 分钟前
Redis的基础认识与在ubuntu上的安装教程
java·数据库·redis·缓存
几何心凉13 分钟前
已解决:org.springframework.web.HttpMediaTypeNotAcceptableException
java
华农第一蒟蒻16 分钟前
Java中JWT(JSON Web Token)的运用
java·前端·spring boot·json·token
两点王爷18 分钟前
使用WebClient 快速发起请求(不使用WebClientUtils工具类)
java·网络
计算机学姐29 分钟前
基于SpringBoot+Vue的高校运动会管理系统
java·vue.js·spring boot·后端·mysql·intellij-idea·mybatis
平凡的小码农43 分钟前
JAVA实现大写金额转小写金额
java·开发语言
一直在进步的派大星1 小时前
Docker 从安装到实战
java·运维·docker·微服务·容器
老华带你飞1 小时前
公寓管理系统|SprinBoot+vue夕阳红公寓管理系统(源码+数据库+文档)
java·前端·javascript·数据库·vue.js·spring boot·课程设计
我明天再来学Web渗透1 小时前
【hot100-java】【二叉树的层序遍历】
java·开发语言·数据库·sql·算法·排序算法