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

}

四、小结

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

相关推荐
zfoo-framework4 分钟前
【jenkins插件】
java
风_流沙10 分钟前
java 对ElasticSearch数据库操作封装工具类(对你是否适用嘞)
java·数据库·elasticsearch
ProtonBase39 分钟前
如何从 0 到 1 ,打造全新一代分布式数据架构
java·网络·数据库·数据仓库·分布式·云原生·架构
乐之者v1 小时前
leetCode43.字符串相乘
java·数据结构·算法
suweijie7684 小时前
SpringCloudAlibaba | Sentinel从基础到进阶
java·大数据·sentinel
公贵买其鹿5 小时前
List深拷贝后,数据还是被串改
java
xlsw_8 小时前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
神仙别闹9 小时前
基于java的改良版超级玛丽小游戏
java
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭9 小时前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
暮湫9 小时前
泛型(2)
java