Android 蓝牙相关广播介绍

Android 蓝牙相关广播介绍

文章目录

一、前言

本文主要介绍Android 蓝牙相关的广播,并非硬件相关的蓝牙广播信号,而是蓝牙app中的广播接收器onReceive 的蓝牙相关广播。

最近刚好开发了一下蓝牙相关的功能,所以进行一些知识总结和介绍,本文应该是全网最面的接收Android广播介绍知识的文章。

Android 蓝牙广播是系统应用或者蓝牙功能应用必备知识,网上介绍的较少或者比较片面,所以Android蓝牙相关开发的可以了解和收藏。

二、相关广播

蓝牙相关广播都是在 BluetoothDevice.java 和 BluetoothAdapter.java 中进行了定义。

蓝牙相关广播主要包括:蓝牙开关,蓝牙连接,蓝牙状态改变,蓝牙配对等等等等。

//Android13 中的源码地址:

packages\modules\Bluetooth\framework\java\android\bluetooth\BluetoothDevice.java

packages\modules\Bluetooth\framework\java\android\bluetooth\BluetoothAdapter.java

1、蓝牙相关广播

(1)蓝牙开关

BluetoothAdapter.java 的代码

BluetoothAdapter.ACTION_STATE_CHANGED

    /**
     * Broadcast Action: The state of the local Bluetooth adapter has been
     * changed.
     * <p>For example, Bluetooth has been turned on or off.
     * <p>Always contains the extra fields {@link #EXTRA_STATE} and {@link
     * #EXTRA_PREVIOUS_STATE} containing the new and old states
     * respectively.
     */
    @RequiresLegacyBluetoothPermission
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
            ACTION_STATE_CHANGED = "android.bluetooth.adapter.action.STATE_CHANGED";

    /**
     * Used as an int extra field in {@link #ACTION_STATE_CHANGED}
     * intents to request the current power state. Possible values are:
     * {@link #STATE_OFF}, //10
     * {@link #STATE_TURNING_ON}, //11
     * {@link #STATE_ON}, //12
     * {@link #STATE_TURNING_OFF}, //13
     */
     
   public static final String EXTRA_STATE = "android.bluetooth.adapter.extra.STATE";

这里说明了,广播里面包含 EXTRA_STATE 数据,里面包含蓝牙的状态。

(2)蓝牙断开/连接

BluetoothDevice.java 的代码

BluetoothDevice.ACTION_ACL_CONNECTED

BluetoothDevice.ACL_DISCONNECTED

//①蓝牙连接Action
   /**
     * Broadcast Action: Indicates a low level (ACL) connection has been
     * established with a remote device.
     * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link #EXTRA_TRANSPORT}.
     * <p>ACL connections are managed automatically by the Android Bluetooth
     * stack.
     */
    @RequiresLegacyBluetoothPermission
    @RequiresBluetoothConnectPermission
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String ACTION_ACL_CONNECTED =
            "android.bluetooth.device.action.ACL_CONNECTED";

//②蓝牙断开Action
    /**
     * Broadcast Action: Indicates a low level (ACL) disconnection from a
     * remote device.
     * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link #EXTRA_TRANSPORT}.
     * <p>ACL connections are managed automatically by the Android Bluetooth
     * stack.
     */
    @RequiresLegacyBluetoothPermission
    @RequiresBluetoothConnectPermission
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String ACTION_ACL_DISCONNECTED =
            "android.bluetooth.device.action.ACL_DISCONNECTED";
//③蓝牙断开/连接 可以获取到的额外信息BluetoothDevice ,里面有很多数据,比如名称,MAC地址
    /**
     * Used as a Parcelable {@link BluetoothDevice} extra field in every intent
     * broadcast by this class. It contains the {@link BluetoothDevice} that
     * the intent applies to.
     */
    public static final String EXTRA_DEVICE = "android.bluetooth.device.extra.DEVICE";

//④蓝牙断开/连接 可以获取到的额外信息,普通蓝牙还是低功耗LE蓝牙
    /**
     * Used as an int extra field in {@link #ACTION_ACL_CONNECTED} and
     * {@link #ACTION_ACL_DISCONNECTED} intents to indicate which transport is connected.
     * Possible values are: {@link #TRANSPORT_BREDR} and {@link #TRANSPORT_LE}.
     */
    @SuppressLint("ActionValue")
 public static final String EXTRA_TRANSPORT = "android.bluetooth.device.extra.TRANSPORT";
(3)蓝牙状态

BluetoothDevice.java 的代码

BluetoothDevice.ACTION_BOND_STATE_CHANGED

这里的状态并非蓝牙断开连接,主要是保存和忘记

    /**
     * Broadcast Action: Indicates a change in the bond state of a remote
     * device. For example, if a device is bonded (paired).
     * <p>Always contains the extra fields {@link #EXTRA_DEVICE}, {@link
     * #EXTRA_BOND_STATE} and {@link #EXTRA_PREVIOUS_BOND_STATE}.
     */
    // Note: When EXTRA_BOND_STATE is BOND_NONE then this will also
    // contain a hidden extra field EXTRA_UNBOND_REASON with the result code.
    @RequiresLegacyBluetoothPermission
    @RequiresBluetoothConnectPermission
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String ACTION_BOND_STATE_CHANGED =
            "android.bluetooth.device.action.BOND_STATE_CHANGED";
            

    /**
     * Used as an int extra field in {@link #ACTION_BOND_STATE_CHANGED} intents.
     * Contains the previous bond state of the remote device.
     * <p>Possible values are:
     * {@link #BOND_NONE}, //10 
     * {@link #BOND_BONDING}, //11
     * {@link #BOND_BONDED}. //12
     */
    public static final String EXTRA_PREVIOUS_BOND_STATE =
            "android.bluetooth.device.extra.PREVIOUS_BOND_STATE";

配对设备和忘记设备成功都是有绑定状态的改变,而断开设备和重新连接设备不一定有bond的改变。

上面也说明了使用 EXTRA_DEVICE 额外信息可以获取到 BluetoothDevice 对象,但是要注意如果是忘记设备有可能获取到的 BluetoothDevice 对象为null。

(4)蓝牙配对/取消配对

BluetoothDevice.ACTION_PAIRING_REQUEST

BluetoothDevice.ACTION_PAIRING_CANCEL

//①蓝牙配对
	/**
     * Broadcast Action: This intent is used to broadcast PAIRING REQUEST
     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} to
     * receive.
     */
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String ACTION_PAIRING_REQUEST =
            "android.bluetooth.device.action.PAIRING_REQUEST";
//② 取消配对
    /** @hide */
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    @UnsupportedAppUsage
    public static final String ACTION_PAIRING_CANCEL =
            "android.bluetooth.device.action.PAIRING_CANCEL";

其实上面广播看起来好像不难,开发过蓝牙具体功能的估计是大部分用到,只是有些细节可能没注意而已。

从上面代码看,常用的广播除了开关状态在 BluetoothAdapter 里面定义,其他的广播都是在 BluetoothDevice 里面定义的。

(5)从源码看Android系统有哪些广播

其实除了常用广播,看看源码定义其他也有些有用的广播比如下面的:

BluetoothAdapter.java 相关广播:
//蓝牙开关,上面已经介绍过了
public static final String ACTION_STATE_CHANGED = "android.bluetooth.adapter.action.STATE_CHANGED";

//扫描状态改变广播
public static final String ACTION_SCAN_MODE_CHANGED = "android.bluetooth.adapter.action.SCAN_MODE_CHANGED";

//是否可被其他设备发现广播
public static final String ACTION_DISCOVERY_STARTED = "android.bluetooth.adapter.action.DISCOVERY_STARTED";

//蓝牙名称修改后的广播
public static final String ACTION_LOCAL_NAME_CHANGED = "android.bluetooth.adapter.action.LOCAL_NAME_CHANGED";

//连接状态的改变?
public static final String ACTION_CONNECTION_STATE_CHANGED =
"android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED";

//BLE 低功耗设备连接
public static final String ACTION_BLE_ACL_CONNECTED = "android.bluetooth.adapter.action.BLE_ACL_CONNECTED";

//BLE 低功耗设备断开
public static final String ACTION_BLE_ACL_DISCONNECTED = "android.bluetooth.adapter.action.BLE_ACL_DISCONNECTED";

//被发现开始
public static final String ACTION_DISCOVERY_STARTED = "android.bluetooth.adapter.action.DISCOVERY_STARTED";

//被发现结束
public static final String ACTION_DISCOVERY_FINISHED = "android.bluetooth.adapter.action.DISCOVERY_FINISHED";

//蓝牙MAC地址修改
public static final String ACTION_BLUETOOTH_ADDRESS_CHANGED = "android.bluetooth.adapter.action.BLUETOOTH_ADDRESS_CHANGED";

//请求被发现广播
public static final String ACTION_REQUEST_DISCOVERABLE = "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";

//请求开启广播
public static final String ACTION_REQUEST_ENABLE = "android.bluetooth.adapter.action.REQUEST_ENABLE";

//请求关闭广播
public static final String ACTION_REQUEST_DISABLE = "android.bluetooth.adapter.action.REQUEST_DISABLE";

//BLE设备请求扫描广播
public static final String ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE = "android.bluetooth.adapter.action.REQUEST_BLE_SCAN_ALWAYS_AVAILABLE";
...

上面的广播都是从 Android13 BluetoothAdapter 具体源码上整理下来的。这些广播好像很少用到过!

BluetoothDevice.java 相关广播:
//新蓝牙设备被发现后,这个广播在普通应用也比较常用
public static final String ACTION_FOUND = "android.bluetooth.device.action.FOUND";

//BluetoothDevice 对象或者 BluetoothClass 对象信息变化后
public static final String ACTION_CLASS_CHANGED ="android.bluetooth.device.action.CLASS_CHANGED";

//蓝牙设备连接,上面已经有介绍
public static final String ACTION_ACL_CONNECTED = "android.bluetooth.device.action.ACL_CONNECTED";

//蓝牙设备请求关闭,这个场景没怎么用过
public static final String ACTION_ACL_DISCONNECT_REQUESTED = "android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED";

//蓝牙设备关闭,上面已经有介绍
public static final String ACTION_ACL_DISCONNECTED = "android.bluetooth.device.action.ACL_DISCONNECTED";

//扫描到的蓝牙设备(非自身)的名称修改
public static final String ACTION_NAME_CHANGED = "android.bluetooth.device.action.NAME_CHANGED";

//扫描到的蓝牙设备(非自身)的别称修改,alias一般情况和name一致
public static final String ACTION_ALIAS_CHANGED = "android.bluetooth.device.action.ALIAS_CHANGED";

//绑定状态改变,上面已经有介绍
public static final String ACTION_BOND_STATE_CHANGED = "android.bluetooth.device.action.BOND_STATE_CHANGED";

//蓝牙电量改变
public static final String ACTION_BATTERY_LEVEL_CHANGED = "android.bluetooth.device.action.BATTERY_LEVEL_CHANGED";

2、广播接收代码示例

这里一段代码,接收上面大部分广播

package com.liwenzhi.broadcastdemo;

import androidx.appcompat.app.AppCompatActivity;

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.os.Bundle;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DebugLog.debug("");
        registerBroadcast(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        DebugLog.debug("");
        unRegisterBroadcast(this);
    }

    public void registerBroadcast(Context context) {
        DebugLog.debug("");
        String a = Intent.ACTION_SCREEN_OFF;
        final IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
        intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        intentFilter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
        intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);

        intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
        intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED);
        intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
        intentFilter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);
        intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
        intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
        context.registerReceiver(mEthernetReceiver, intentFilter);
    }


    public void unRegisterBroadcast(Context context) {
        context.unregisterReceiver(mEthernetReceiver);
    }

    private final BroadcastReceiver mEthernetReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            DebugLog.info("action = " + action);
            if (action == null) {
                DebugLog.error("action == null!");
                return;
            }
            //常用的信息写在前面
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            if (device != null) {
                DebugLog.info("BluetoothDevice = " + device + ",name = " + device.getAlias());
            } else {
                DebugLog.info("BluetoothDevice is null!");
            }

            switch (action) {
                case Intent.ACTION_BOOT_COMPLETED: //开机
                    //判断蓝牙是否连接
                    BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
                    int blueConnectState = bluetoothAdapter.getConnectionState();
                    DebugLog.info("bluetooth ConnectState :STATE_DISCONNECTED=0, STATE_CONNECTING=1, STATE_CONNECTED=2, STATE_DISCONNECTING=3");
                    DebugLog.info("blueConnectState = " + blueConnectState);
                    break;
                //BluetoothAdapter 相关广播
                case BluetoothAdapter.ACTION_STATE_CHANGED: //蓝牙开关
                    DebugLog.info("Bluetooth Switch state :STATE_OFF --> 10, STATE_TURNING_ON --> 11, STATE_ON --> 12 ,STATE_TURNING_OFF --> 13 ");
                    int switchState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
                    DebugLog.info("Bluetooth Switch change to= " + switchState);
                    break;
                case BluetoothAdapter.ACTION_SCAN_MODE_CHANGED: //蓝牙扫描状态修改
                    DebugLog.info("Bluetooth scan mode :SCAN_MODE_NONE --> 20, SCAN_MODE_CONNECTABLE --> 21, SCAN_MODE_CONNECTABLE_DISCOVERABLE --> 23");
                    int scanMode = intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE, -1);
                    DebugLog.info("Bluetooth scanMode change to = " + scanMode);
                    break;
                case BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED: //蓝牙连接,和ACL连接的区别 ?
                    DebugLog.info("bluetooth ConnectState :STATE_DISCONNECTED=0, STATE_CONNECTING=1, STATE_CONNECTED=2, STATE_DISCONNECTING=3");
                    int connectPreviousState = intent.getIntExtra(BluetoothAdapter.EXTRA_PREVIOUS_CONNECTION_STATE, -1);
                    DebugLog.info("Bluetooth connectPreviousState = " + connectPreviousState);
                    int connectState = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, -1);
                    DebugLog.info("Bluetooth state = " + connectState);
                    break;

                //BluetoothDevice 相关广播

                case BluetoothDevice.ACTION_ACL_CONNECTED: //蓝牙连接
                    //判断当前连接的蓝牙数量
                    DebugLog.debug("ACTION_ACL_CONNECTED() !");
                    break;
                case BluetoothDevice.ACTION_ACL_DISCONNECTED: //蓝牙断开
                    DebugLog.debug("ACTION_ACL_DISCONNECTED() !");
                    break;
                case BluetoothDevice.ACTION_BOND_STATE_CHANGED: //蓝牙绑定状态改变,绑定前后蓝牙变化广播
                    DebugLog.info("Bluetooth bond state :BOND_NONE = 10, BOND_BONDING = 11, BOND_BONDED = 12 ");
                    int bondPreviousState = intent.getIntExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, -1);
                    DebugLog.info("Bluetooth bondPreviousState = " + bondPreviousState);
                    int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1);
                    DebugLog.info("Bluetooth bondState = " + bondState);
                    break;
                case BluetoothDevice.ACTION_PAIRING_REQUEST: //蓝牙配对
                    DebugLog.debug("ACTION_PAIRING_REQUEST !");
                    int pinNumber = intent.getIntExtra("android.bluetooth.device.extra.PAIRING_KEY", 1234);
                    DebugLog.debug("ACTION_PAIRING_REQUEST  pinNumber = " + pinNumber);
                    break;
                case BluetoothDevice.ACTION_PAIRING_CANCEL: //蓝牙取消配对
                    DebugLog.debug("ACTION_PAIRING_CANCEL !");
                    break;
            }
        }
    };


}

上面的代码是在Activity 界面动态注册蓝牙主要广播代码,为啥不用静态,可以看看后面蓝牙广播注册时机说明。

3、广播接收代码示例日志

紧接着上面示例代码,下面是Android13 上mtk方案的日志情况。

(1)蓝牙打开、关闭日志
蓝牙打开:
//1、蓝牙打开,获取到的BluetoothDevice对象为 null
MainActivity.java(58)::onReceive - action = android.bluetooth.adapter.action.STATE_CHANGED
MainActivity.java(68)::onReceive - BluetoothDevice is null!

//2、蓝牙进入正在开启状态
MainActivity.java(81)::onReceive - Bluetooth Switch state :STATE_OFF --> 10, STATE_TURNING_ON --> 11, STATE_ON --> 12 ,STATE_TURNING_OFF --> 13 
MainActivity.java(83)::onReceive - Bluetooth Switch change to= 11

//3、这里是系统设置本设备可被其他设备发现后(应用一般开启蓝牙会控制)
MainActivity.java(58)::onReceive - action = android.bluetooth.adapter.action.SCAN_MODE_CHANGED
MainActivity.java(68)::onReceive - BluetoothDevice is null!
MainActivity.java(86)::onReceive - Bluetooth scan mode :SCAN_MODE_NONE --> 20, SCAN_MODE_CONNECTABLE --> 21, SCAN_MODE_CONNECTABLE_DISCOVERABLE --> 23
MainActivity.java(88)::onReceive - Bluetooth scanMode change to = 23

//4、蓝牙进入开启状态,获取到的BluetoothDevice对象为 null
MainActivity.java(58)::onReceive - action = android.bluetooth.adapter.action.STATE_CHANGED
MainActivity.java(68)::onReceive - BluetoothDevice is null!
MainActivity.java(81)::onReceive - Bluetooth Switch state :STATE_OFF --> 10, STATE_TURNING_ON --> 11, STATE_ON --> 12 ,STATE_TURNING_OFF --> 13 
MainActivity.java(83)::onReceive - Bluetooth Switch change to= 12
蓝牙关闭:
//1、蓝牙状态改变,进入正在关闭蓝牙状态
MainActivity.java(58)::onReceive - action = android.bluetooth.adapter.action.STATE_CHANGED
MainActivity.java(68)::onReceive - BluetoothDevice is null!
MainActivity.java(81)::onReceive - Bluetooth Switch state :STATE_OFF --> 10, STATE_TURNING_ON --> 11, STATE_ON --> 12 ,STATE_TURNING_OFF --> 13 
MainActivity.java(83)::onReceive - Bluetooth Switch change to= 13
//2、可被发现状态为NONE, 这个是系统原生流程设置的
MainActivity.java(58)::onReceive - action = android.bluetooth.adapter.action.SCAN_MODE_CHANGED
MainActivity.java(68)::onReceive - BluetoothDevice is null!
MainActivity.java(86)::onReceive - Bluetooth scan mode :SCAN_MODE_NONE --> 20, SCAN_MODE_CONNECTABLE --> 21, SCAN_MODE_CONNECTABLE_DISCOVERABLE --> 23
MainActivity.java(88)::onReceive - Bluetooth scanMode change to = 20

//3、蓝牙状态改变,蓝牙关闭状态
MainActivity.java(58)::onReceive - action = android.bluetooth.adapter.action.STATE_CHANGED
MainActivity.java(68)::onReceive - BluetoothDevice is null!
MainActivity.java(81)::onReceive - Bluetooth Switch state :STATE_OFF --> 10, STATE_TURNING_ON --> 11, STATE_ON --> 12 ,STATE_TURNING_OFF --> 13 
MainActivity.java(83)::onReceive - Bluetooth Switch change to= 10
//4、可被发现状态为NONE, 这个是系统原生流程设置的
MainActivity.java(58)::onReceive - action = android.bluetooth.adapter.action.SCAN_MODE_CHANGED
MainActivity.java(68)::onReceive - BluetoothDevice is null!
MainActivity.java(86)::onReceive - Bluetooth scan mode :SCAN_MODE_NONE --> 20, SCAN_MODE_CONNECTABLE --> 21, SCAN_MODE_CONNECTABLE_DISCOVERABLE --> 23
MainActivity.java(88)::onReceive - Bluetooth scanMode change to = 20

关闭流程里面有两次设置了蓝牙设备不可发现,这个是原生代码流程处理的,不用管的,影响不大。

(2)蓝牙请求连接其他蓝牙设备日志

点击配对蓝牙到自动连接的过程

//1、绑定状态的改变,从 普通状态10 到 正在绑定状态11
MainActivity.java(58)::onReceive - action = android.bluetooth.device.action.BOND_STATE_CHANGED
MainActivity.java(66)::onReceive - BluetoothDevice = 11:75:58:11:AC:7C,name = A19
MainActivity.java(108)::onReceive - Bluetooth bond state :BOND_NONE = 10, BOND_BONDING = 11, BOND_BONDED = 12 
MainActivity.java(110)::onReceive - Bluetooth bondPreviousState = 10
MainActivity.java(112)::onReceive - Bluetooth bondState = 11

//2、这时就有连接成功的简单日志?!
MainActivity.java(58)::onReceive - action = android.bluetooth.device.action.ACL_CONNECTED
MainActivity.java(66)::onReceive - BluetoothDevice = 11:75:58:11:AC:7C,name = A19
MainActivity.java(102)::onReceive - ACTION_ACL_CONNECTED() !

//3、请求配对,配对码没有,因为我是连接的蓝牙耳机,所以是没有配对码的!
MainActivity.java(58)::onReceive - action = android.bluetooth.device.action.PAIRING_REQUEST
MainActivity.java(66)::onReceive - BluetoothDevice = 11:75:58:11:AC:7C,name = A19
MainActivity.java(115)::onReceive - ACTION_PAIRING_REQUEST !
MainActivity.java(117)::onReceive - ACTION_PAIRING_REQUEST  pinNumber = 1234

//上面是进入配对确认状态,确认后会自动进入后续状态。

//4、绑定状态的改变,从正在绑定状态11 到 绑定完成状态12
MainActivity.java(58)::onReceive - action = android.bluetooth.device.action.BOND_STATE_CHANGED
MainActivity.java(66)::onReceive - BluetoothDevice = 11:75:58:11:AC:7C,name = A19
MainActivity.java(108)::onReceive - Bluetooth bond state :BOND_NONE = 10, BOND_BONDING = 11, BOND_BONDED = 12 
MainActivity.java(110)::onReceive - Bluetooth bondPreviousState = 11
MainActivity.java(112)::onReceive - Bluetooth bondState = 12

//5、连接成功详细信息,从断开连接状态0 到连接中状态1
MainActivity.java(58)::onReceive - action = android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED
MainActivity.java(66)::onReceive - BluetoothDevice = 11:75:58:11:AC:7C,name = A19
MainActivity.java(91)::onReceive - bluetooth ConnectState :STATE_DISCONNECTED=0, STATE_CONNECTING=1, STATE_CONNECTED=2, STATE_DISCONNECTING=3
MainActivity.java(93)::onReceive - Bluetooth connectPreviousState = 0
MainActivity.java(95)::onReceive - Bluetooth state = 1


//6、连接成功详细信息,从连接中状态1 到连接成功状态2
MainActivity.java(58)::onReceive - action = android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED
MainActivity.java(66)::onReceive - BluetoothDevice = 11:75:58:11:AC:7C,name = A19
MainActivity.java(91)::onReceive - bluetooth ConnectState :STATE_DISCONNECTED=0, STATE_CONNECTING=1, STATE_CONNECTED=2, STATE_DISCONNECTING=3
MainActivity.java(93)::onReceive - Bluetooth connectPreviousState = 1
MainActivity.java(95)::onReceive - Bluetooth state = 2

//7、扫描状态,进入可被连接状态
MainActivity.java(58)::onReceive - action = android.bluetooth.adapter.action.SCAN_MODE_CHANGED
MainActivity.java(68)::onReceive - BluetoothDevice is null!
MainActivity.java(86)::onReceive - Bluetooth scan mode :SCAN_MODE_NONE --> 20, SCAN_MODE_CONNECTABLE --> 21, SCAN_MODE_CONNECTABLE_DISCOVERABLE --> 23
MainActivity.java(88)::onReceive - Bluetooth scanMode change to = 21

//8、扫描状态,进入可被外部设备发现和连接状态
MainActivity.java(58)::onReceive - action = android.bluetooth.adapter.action.SCAN_MODE_CHANGED
MainActivity.java(68)::onReceive - BluetoothDevice is null!
MainActivity.java(86)::onReceive - Bluetooth scan mode :SCAN_MODE_NONE --> 20, SCAN_MODE_CONNECTABLE --> 21, SCAN_MODE_CONNECTABLE_DISCOVERABLE --> 23
MainActivity.java(88)::onReceive - Bluetooth scanMode change to = 23
(3)其他Android设备请求连接配对设备日志
其他Android手机设备配对自己的设备,未确认配对前
//1、连接成功简单信息
MainActivity.java(58)::onReceive - action = android.bluetooth.device.action.ACL_CONNECTED
MainActivity.java(66)::onReceive - BluetoothDevice = 18:87:40:11:16:0E,name = Redmi 10X
MainActivity.java(102)::onReceive - ACTION_ACL_CONNECTED() !

//2、绑定状态改变,从普通状态10 进入到 配对状态 11
MainActivity.java(58)::onReceive - action = android.bluetooth.device.action.BOND_STATE_CHANGED
MainActivity.java(66)::onReceive - BluetoothDevice = 18:87:40:11:16:0E,name = Redmi 10X
MainActivity.java(108)::onReceive - Bluetooth bond state :BOND_NONE = 10, BOND_BONDING = 11, BOND_BONDED = 12 
MainActivity.java(110)::onReceive - Bluetooth bondPreviousState = 10
MainActivity.java(112)::onReceive - Bluetooth bondState = 11

//3、进入配对过程,手机配对,有请求码。
MainActivity.java(58)::onReceive - action = android.bluetooth.device.action.PAIRING_REQUEST
MainActivity.java(66)::onReceive - BluetoothDevice = 18:87:40:11:16:0E,name = Redmi 10X
MainActivity.java(115)::onReceive - ACTION_PAIRING_REQUEST !
MainActivity.java(117)::onReceive - ACTION_PAIRING_REQUEST  pinNumber = 984754

配对又分为确认配对或者不配对

点击取消配对/不点击处理导致配对超时的情况
//1、绑定状态,从正在绑定11 到 普通状态10
MainActivity.java(58)::onReceive - action = android.bluetooth.device.action.BOND_STATE_CHANGED
MainActivity.java(66)::onReceive - BluetoothDevice = 18:87:40:11:16:0E,name = Redmi 10X
MainActivity.java(108)::onReceive - Bluetooth bond state :BOND_NONE = 10, BOND_BONDING = 11, BOND_BONDED = 12
MainActivity.java(110)::onReceive - Bluetooth bondPreviousState = 11
MainActivity.java(112)::onReceive - Bluetooth bondState = 10

//2、断开连接简单信息
MainActivity.java(58)::onReceive - action = android.bluetooth.device.action.ACL_DISCONNECTED
MainActivity.java(66)::onReceive - BluetoothDevice = 18:87:40:11:16:0E,name = Redmi 10X
MainActivity.java(105)::onReceive - ACTION_ACL_DISCONNECTED() !
点击确认配对的情况
正常点击配对的情况
//1、绑定状态发生改变,从绑定中11 变成 绑定完成状态12
MainActivity.java(58)::onReceive - action = android.bluetooth.device.action.BOND_STATE_CHANGED
MainActivity.java(66)::onReceive - BluetoothDevice = 18:87:40:11:16:0E,name = Redmi 10X
MainActivity.java(108)::onReceive - Bluetooth bond state :BOND_NONE = 10, BOND_BONDING = 11, BOND_BONDED = 12 
MainActivity.java(110)::onReceive - Bluetooth bondPreviousState = 11
MainActivity.java(112)::onReceive - Bluetooth bondState = 12

//2、绑定状态发生改变,从绑定中11 变成 绑定完成状态12
MainActivity.java(58)::onReceive - action = android.bluetooth.device.action.BOND_STATE_CHANGED
MainActivity.java(66)::onReceive - BluetoothDevice = 18:87:40:11:16:0E,name = Redmi 10X
MainActivity.java(108)::onReceive - Bluetooth bond state :BOND_NONE = 10, BOND_BONDING = 11, BOND_BONDED = 12 
MainActivity.java(110)::onReceive - Bluetooth bondPreviousState = 12
MainActivity.java(112)::onReceive - Bluetooth bondState = 11

//3、连接成功详细状态,从断开连接状态0 到 连接中1
MainActivity.java(58)::onReceive - action = android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED
MainActivity.java(66)::onReceive - BluetoothDevice = 18:87:40:11:16:0E,name = Redmi 10X
MainActivity.java(91)::onReceive - bluetooth ConnectState :STATE_DISCONNECTED=0, STATE_CONNECTING=1, STATE_CONNECTED=2, STATE_DISCONNECTING=3
MainActivity.java(93)::onReceive - Bluetooth connectPreviousState = 0
MainActivity.java(95)::onReceive - Bluetooth state = 1

//4、连接成功详细状态,从连接中1 到 连接成功2
MainActivity.java(58)::onReceive - action = android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED
MainActivity.java(66)::onReceive - BluetoothDevice = 18:87:40:11:16:0E,name = Redmi 10X
MainActivity.java(91)::onReceive - bluetooth ConnectState :STATE_DISCONNECTED=0, STATE_CONNECTING=1, STATE_CONNECTED=2, STATE_DISCONNECTING=3
MainActivity.java(93)::onReceive - Bluetooth connectPreviousState = 1
MainActivity.java(95)::onReceive - Bluetooth state = 2

//5、绑定状态发生改变,从绑定中11 变成 绑定完成状态12
MainActivity.java(58)::onReceive - action = android.bluetooth.device.action.BOND_STATE_CHANGED
MainActivity.java(66)::onReceive - BluetoothDevice = 18:87:40:11:16:0E,name = Redmi 10X
MainActivity.java(108)::onReceive - Bluetooth bond state :BOND_NONE = 10, BOND_BONDING = 11, BOND_BONDED = 12 
MainActivity.java(110)::onReceive - Bluetooth bondPreviousState = 11
MainActivity.java(112)::onReceive - Bluetooth bondState = 12

注意,我这里是mtk平台的方案,和普通系统方案有点不一样的。

普通Android系统方案是无法正常连接手机的,mtk平台是可以的,普通平台估计就是从普通状态进入到绑定状态。

(4)蓝牙连接、断开日志
从保存状态到连接蓝牙设备
//1、蓝牙具体连接状态广播,从 断开 0 到 连接中 1
MainActivity.java(58)::onReceive - action = android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED
MainActivity.java(66)::onReceive - BluetoothDevice = 11:75:58:11:AC:7C,name = A19
MainActivity.java(91)::onReceive - bluetooth ConnectState :STATE_DISCONNECTED=0, STATE_CONNECTING=1, STATE_CONNECTED=2, STATE_DISCONNECTING=3
MainActivity.java(93)::onReceive - Bluetooth connectPreviousState = 0
MainActivity.java(95)::onReceive - Bluetooth state = 1

//2、另外一个简单蓝牙连接状态广播,没有之前的状态的
MainActivity.java(58)::onReceive - action = android.bluetooth.device.action.ACL_CONNECTED
MainActivity.java(66)::onReceive - BluetoothDevice = 11:75:58:11:AC:7C,name = A19
MainActivity.java(102)::onReceive - ACTION_ACL_CONNECTED() !

//其他的蓝牙相关TAG打印
BluetoothDatabase: updateDatabase XX:XX:XX:11:AC:7C

//3、蓝牙具体连接状态广播,从 连接中 1 到 连接成功 2
MainActivity.java(58)::onReceive - action = android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED
MainActivity.java(66)::onReceive - BluetoothDevice = 11:75:58:11:AC:7C,name = A19
MainActivity.java(91)::onReceive - bluetooth ConnectState :STATE_DISCONNECTED=0, STATE_CONNECTING=1, STATE_CONNECTED=2, STATE_DISCONNECTING=3
MainActivity.java(93)::onReceive - Bluetooth connectPreviousState = 1
MainActivity.java(95)::onReceive - Bluetooth state = 2
断开蓝牙设备,从连接状进入保存状态
//1、连接状态详细信息,从连接状态2 进入正在断开连接状态 3
MainActivity.java(58)::onReceive - action = android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED
MainActivity.java(66)::onReceive - BluetoothDevice = 11:75:58:11:AC:7C,name = A19
MainActivity.java(91)::onReceive - bluetooth ConnectState :STATE_DISCONNECTED=0, STATE_CONNECTING=1, STATE_CONNECTED=2, STATE_DISCONNECTING=3
MainActivity.java(93)::onReceive - Bluetooth connectPreviousState = 2
MainActivity.java(95)::onReceive - Bluetooth state = 3

//2、连接状态详细信息,从正在断开连接状态 3 进入已断开连接状态0
MainActivity.java(58)::onReceive - action = android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED
MainActivity.java(66)::onReceive - BluetoothDevice = 11:75:58:11:AC:7C,name = A19
MainActivity.java(91)::onReceive - bluetooth ConnectState :STATE_DISCONNECTED=0, STATE_CONNECTING=1, STATE_CONNECTED=2, STATE_DISCONNECTING=3
MainActivity.java(93)::onReceive - Bluetooth connectPreviousState = 3
MainActivity.java(95)::onReceive - Bluetooth state = 0


//3、断开连接简易信息
MainActivity.java(58)::onReceive - action = android.bluetooth.device.action.ACL_DISCONNECTED
MainActivity.java(66)::onReceive - BluetoothDevice = 11:75:58:11:AC:7C,name = A19
MainActivity.java(105)::onReceive - ACTION_ACL_DISCONNECTED() !
(5)蓝牙忘记设备日志

从保存状态忘记设备

//1、绑定状态改变,从之前的绑定状态12 进入 普遍状态 10
MainActivity.java(58)::onReceive - action = android.bluetooth.device.action.BOND_STATE_CHANGED
MainActivity.java(66)::onReceive - BluetoothDevice = 11:75:58:11:AC:7C,name = A19
MainActivity.java(108)::onReceive - Bluetooth bond state :BOND_NONE = 10, BOND_BONDING = 11, BOND_BONDED = 12 
MainActivity.java(110)::onReceive - Bluetooth bondPreviousState = 12
MainActivity.java(112)::onReceive - Bluetooth bondState = 10

//2、可被发现状态改变,可连接和发现,这可能是原生流程
MainActivity.java(58)::onReceive - action = android.bluetooth.adapter.action.SCAN_MODE_CHANGED
MainActivity.java(68)::onReceive - BluetoothDevice is null!
MainActivity.java(86)::onReceive - Bluetooth scan mode :SCAN_MODE_NONE --> 20, SCAN_MODE_CONNECTABLE --> 21, SCAN_MODE_CONNECTABLE_DISCOVERABLE --> 23
MainActivity.java(88)::onReceive - Bluetooth scanMode change to = 23

从连接状态忘记设备

//1、断开设备简单状态
MainActivity.java(58)::onReceive - action = android.bluetooth.device.action.ACL_DISCONNECTED
MainActivity.java(66)::onReceive - BluetoothDevice = 11:75:58:11:AC:7C,name = A19
MainActivity.java(105)::onReceive - ACTION_ACL_DISCONNECTED() !

//2、绑定设备状态改变,冲绑定12 到 普通状态10
MainActivity.java(58)::onReceive - action = android.bluetooth.device.action.BOND_STATE_CHANGED
MainActivity.java(66)::onReceive - BluetoothDevice = 11:75:58:11:AC:7C,name = A19
MainActivity.java(108)::onReceive - Bluetooth bond state :BOND_NONE = 10, BOND_BONDING = 11, BOND_BONDED = 12
MainActivity.java(110)::onReceive - Bluetooth bondPreviousState = 12
MainActivity.java(112)::onReceive - Bluetooth bondState = 10
//3、断开设备详细状态,从连接2 到断开0
MainActivity.java(58)::onReceive - action = android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED
MainActivity.java(66)::onReceive - BluetoothDevice = 11:75:58:11:AC:7C,name = A19
MainActivity.java(91)::onReceive - bluetooth ConnectState :STATE_DISCONNECTED=0, STATE_CONNECTING=1, STATE_CONNECTED=2, STATE_DISCONNECTING=3
MainActivity.java(93)::onReceive - Bluetooth connectPreviousState = 2
MainActivity.java(95)::onReceive - Bluetooth state = 0
//4、可被发现状态改变,可连接和发现,这可能是原生流程
MainActivity.java(58)::onReceive - action = android.bluetooth.adapter.action.SCAN_MODE_CHANGED
MainActivity.java(68)::onReceive - BluetoothDevice is null!
MainActivity.java(86)::onReceive - Bluetooth scan mode :SCAN_MODE_NONE --> 20, SCAN_MODE_CONNECTABLE --> 21, SCAN_MODE_CONNECTABLE_DISCOVERABLE --> 23
MainActivity.java(88)::onReceive - Bluetooth scanMode change to = 23

从这里看从连接状态直接忘记设备是会先断开设备,在忘记设备的。

上面日志有点多,其实固定的状态,无非就几种状态:普通,保存,连接。

日志比较多,不一定要全部看一遍,看一两个后有大概了解就可以了,并且实际情况还会有一定变化,跟自己的开发应用处理过程调用的api有相关。

(6)日志总结

如果上面日志过程没怎么看的,那么日志总结可以看看。

重要过程,日志里面主要包含connection状态,acl_connected,bond等信息

1、开关状态,数值:STATE_OFF=10, STATE_TURNING_ON=11, STATE_ON=12 ,STATE_TURNING_OFF=13 

2、绑定状态,数值::BOND_NONE = 10, BOND_BONDING = 11, BOND_BONDED = 12

3、连接状态,数值:STATE_DISCONNECTED=0, STATE_CONNECTING=1, STATE_CONNECTED=2, STATE_DISCONNECTING=3

4、可被连接和发现状态,数值:SCAN_MODE_NONE=20, SCAN_MODE_CONNECTABLE=21, SCAN_MODE_CONNECTABLE_DISCOVERABLE=23

5、蓝牙从保存到连接会有 ACL_CONNECTED 和 CONNECTION_STATE_CHANGED 广播
CONNECTION_STATE_CHANGED 广播信息更加全面可靠,通过额外数据可以获取具体状态

6、从配对设备日志可以看到,未点击确认配对前就有 ACL_CONNECTED 和 BOND_STATE_CHANGED 广播
但是从 BOND_STATE_CHANGED 额外信息获取可以知道当前是绑定中的状态
确认配对后,才会进入BOND_STATE_CHANGED绑定成功和连接成功CONNECTION_STATE_CHANGED状态广播,
后续没有再收到 ACL_CONNECTED 广播,所以从配对过程也可以看到 ACL_CONNECTED 连接的广播是不准确的

7、断开连接使用 ACL_DISCONNECTED 广播判断一般是没问题的,其实也是不太准确的,因为这时候是正在断开的状态,通过广播 CONNECTION_STATE_CHANGED 额外信息获取到的断开状态才是比较准确的断开。

蓝牙各种情况状态真的是多,很容易忘记;

强烈建议像上面示例代码一样,先打印不同状态值对应的关系,再打印具体的状态值,这样就一下子知道获取到的状态值的含义了。

三、蓝牙状态判断

1、蓝牙开关状态

(1)蓝牙开关状态在 BluetoothAdapter.java 中的定义

  public static final int STATE_OFF = 10;
  public static final int STATE_TURNING_ON = 11;
  public static final int STATE_ON = 12;
  public static final int STATE_TURNING_OFF = 13;
  public static final int STATE_BLE_TURNING_ON = 14; //这个应该没啥用。
(2)蓝牙开启状态判断

系统应用代码中对开关状态的判断处理:

LocalBluetoothManager mBluetoothManager = LocalBluetoothManager.getInstance(context, null);
LocalBluetoothAdapter mLocalAdapter = mBluetoothManager.getBluetoothAdapter();
//判断蓝牙是否打开,如果刚点击开关也会为true,蓝牙关闭肯定为false
boolean isEnabled = mLocalAdapter.isEnabled()
//界面显示的时候,可以再判断一下蓝牙具体状态,因为有可能是打开中的状态
if (isEnabled) {
	updateContent(mLocalAdapter.getBluetoothState());//判断蓝牙状态
} else { //蓝牙关闭的情况
。。。
}

	//蓝牙具体开关状态,处理示例    	
    void updateContent(int bluetoothState) {
    	//蓝牙开关状态记得打印一下,有些问题是在打开中和关闭中处理导致异常的,是可以规避的。
        LogUtil.debug("bluetoothState = " + bluetoothState);
        switch (bluetoothState) { //一般只判断蓝牙是否进入开启和关闭
            case BluetoothAdapter.STATE_ON: //蓝牙开启状态
                enableScanning(); //开始扫描设备和接收设备列表
                addCachedDevices();
                break;
            case BluetoothAdapter.STATE_OFF: //蓝牙已关闭成功状态
                //更新UI
                removeAllDevices();
                break;
        }
    }

上面是一般系统应用的处理,LocalBluetoothManager 等一系列Local相关类都是在系统SettingsLib里面的。

普通应用也可以调用原生接口的类处理:

public final class BluetoothAdapter {
	  
	  //静态获取 BluetoothAdapter 对象方法
	  public static synchronized BluetoothAdapter getDefaultAdapter() {
        if (sAdapter == null) {
            IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);
            if (b != null) {
                IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b);
                sAdapter = new BluetoothAdapter(managerService);
            } else {
                Log.e(TAG, "Bluetooth binder is null");
            }
        }
        return sAdapter;
    }
	
	//判断蓝牙是否开启
	public boolean isEnabled() {
        return getState() == BluetoothAdapter.STATE_ON;
    }
}

2、蓝牙连接状态数值

BluetoothAdapter.java

/** The profile is in disconnected state */
public static final int STATE_DISCONNECTED = 0; //BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTED;

/** The profile is in connecting state */
public static final int STATE_CONNECTING = 1; //BluetoothProtoEnums.CONNECTION_STATE_CONNECTING;

/** The profile is in connected state */
public static final int STATE_CONNECTED = 2; //BluetoothProtoEnums.CONNECTION_STATE_CONNECTED;

/** The profile is in disconnecting state */
public static final int STATE_DISCONNECTING = 3; //BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTING;

3、蓝牙某个设备绑定/连接状态

绑定其实就是已保存的设备,连接的设备是当前使用中的设备。

 LocalBluetoothManager mBluetoothManager = LocalBluetoothManager.getInstance(context, null);
 //已连接+绑定设备列表
Set<BluetoothDevice> bondedDevices = mBluetoothManager.getBluetoothAdapter().getBondedDevices();

for (CachedBluetoothDevice cachedDevice : cachedDevices) {
    
    //蓝牙 BluetoothDevice 对象
    BluetoothDevice deviceDevice = cachedDevice.getDevice();
    //蓝牙名称
    String name = deviceDevice.getName();
    //蓝牙类型
    int majorDeviceClass = cachedDevice.getBtClass().getMajorDeviceClass();
    //蓝牙是否连接状态,不是连接状态的都是保存状态的
    boolean isConnected = cachedDevice.isConnected();
    //处理!
    。。。
}

上面是系统应用写法,如果是普通应用,可以使用 BluetoothDevice 对象判断连接状态。

4、蓝牙关键对象 BluetoothDevice

BluetoothDevice 对象是操作蓝牙非常关键的对象,

里面包含了蓝牙基本信息:蓝牙名称,别名,MAC地址,蓝牙Class类型,电量,绑定状态,是否连接等状态

还包含了一些重要操作:配对,取消配对,连接,断开,忘记等重要操作过程。

(1)获取 BluetoothDevice 对象

普通应用如果没有SettingsLib,只能通过FOUND广播,获取扫描的蓝牙列表

系统应用写法:

//获取扫描列表
Collection<CachedBluetoothDevice> cachedDevices = mBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy();

//已连接/绑定设备列表
Set<BluetoothDevice> bondedDevices = mBluetoothManager.getBluetoothAdapter().getBondedDevices();

其实SettingsLib里面实现也是根据 FOUND广播,不断添加扫描到的蓝牙对象BluetoothDevice ,合成CachedBluetoothDevice 对象。

普通应用就要通过广播接收 BluetoothDevice.ACTION_FOUND ,获取到 BluetoothDevice 对象并收集起来显示在界面。

本文的示例代码里面只监听了广播,扫描和其他所有操作都是其他应用里面的,

获取不到 ACTION_FOUND 广播,应该是有地方收到后,进行了拦截,

自己写的demo应用,自己扫描是可以收到 ACTION_FOUND 广播信息的。

当然其他广播也有 BluetoothDevice 对象,比如蓝牙连接,断开,绑定状态改变,

但是这个广播里面的 BluetoothDevice 回调只是为了更新列表信息的数据。

蓝牙开关开关变化以及扫描状态改变等广播,是没有 BluetoothDevice 对象回调的,

所以获取BluetoothDevice 的时候要进行一下判空处理。

(2)BluetoothDevice 关键信息
public final class BluetoothDevice implements Parcelable, Attributable {

    private static final String TAG = "BluetoothDevice";
    private static final boolean DBG = false;
    
    //1、基本信息
	//对象 toString 只打印MAC 地址
    public String toString() {
        return mAddress;
    }
    
    //2、获取MAC地址
    public String getAddress() {
        if (DBG) Log.d(TAG, "mAddress: " + mAddress);
        return mAddress;
    }
	//3、获取蓝牙设备名称
    public String getName() {}    
    //4、设备蓝牙设备别名,如果未设置别名,最后也是获取的名称 Name
    public String getAlias() {}
	//5、设置其他蓝牙设备别名名称
    public int setAlias(@Nullable String alias) {}
    //6、获取电池电量,充电状态可能不准确
    public @IntRange(from = -100, to = 100) int getBatteryLevel() {}
	//7、获取绑定状态
    public int getBondState() {}
	//8、判断设备是否是连接状态
    public boolean isConnected() {}
    
	//常用操作
	
	//1、从普通状态进入配对,执行确认配对就会进入连接状态
	public boolean createBond() {}
	//2、取消配对
	public boolean cancelBondProcess() { }
	//3、连接,可以从保存状态进入连接状态
	public int connect() { }
	//4、断开连接,可以用连接状态进入保存状态
	public int disconnect() { }
	//5、忘记设备
	public boolean removeBond() {
	//6、自动确认连接,前提是对方设备确认了配对,蓝牙设备不用对方确认,手机、蓝牙键盘一般要对方确认
	public boolean setPairingConfirmation(boolean confirm) {
	
}

BluetoothDevice 对象大致就上面的内容了,有兴趣可以再看看源码。

其中蓝牙类型还是比较多知识的,可以看看之前那个博客:

https://blog.csdn.net/wenzhi20102321/article/details/133777224

四、其他

1、蓝牙配对广播ACTION_PAIRING_REQUEST的说明

这个配对是别的设备向你配对,还是你的设备向其他的设备配对?

其实不管是你配对其他设备,还是其他设备向你配对都是有这个广播,

系统的弹框提示(有的有配对码),就是用接收这个广播,然后弹框提示。

这个广播是有序广播,如果要自定义弹框就可以自己接收这个广播弹框,并进行拦截

abortBroadcast(); //onReceive 方法内,拦截广播可以拦截掉系统那个,让系统的配对框不显示。

如果要默认就是支持配对,就在收到 ACTION_PAIRING_REQUEST 广播里面,设置默认同意即可。

BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
device.setPairingConfirmation(true);

在广播请求广播内设置了上述代码,本机设备相当于默认支持别的设备配对的。

至于是否需要弹框提示,可以根据实际情况处理。

2、蓝牙广播注册时机说明

理论上,除了几个特殊广播,比如息屏广播和时间变化广播等,

蓝牙上面的所有广播,无论是静态还是动态都是可以注册的,但是实际上却不是这样的。

我这个是通过Android13 实际代码验证的情况:

只能动态注册的蓝牙广播:

BluetoothAdapter.ACTION_STATE_CHANGED: //蓝牙开关
BluetoothAdapter.ACTION_SCAN_MODE_CHANGED: //蓝牙扫描状态修改
BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED: //蓝牙连接详细情况
BluetoothDevice.ACTION_BOND_STATE_CHANGED: //蓝牙绑定状态改变,绑定前后蓝牙变化广播

动态和静态注册都ok 的蓝牙广播:

BluetoothDevice.ACTION_ACL_CONNECTED: //蓝牙连接
BluetoothDevice.ACTION_ACL_DISCONNECTED: //蓝牙断开

这里看静态注册没几个广播信息的!

这里不做具体原因分析,如果要研究可以看看AMS加载 apk 信息的过程,应该有对某些广播的限制代码(静态注册相当于没注册)。

所以说蓝牙的广播动态注册是最保险的,可以在自己的某个服务启动后进行动态监听注册即可。

插一句,所有的广播都是可以动态注册并且能正常监听,

即使是开机广播 Intent.ACTION_BOOT_COMPLETED 只要你在系统服务刚起来的时候注册这个广播,

开机完成后也是可以收到广播信息的,并且还会比静态注册的方式收到得快一些。

3、各种状态总结

蓝牙状态感觉很多的样子,但是其实就三个,开关状态,绑定状态,连接状态。

写完这个后,我可能也会不记得了,所以最的方法是,打印状态前,打印一下所有状态的含义。

但是还是要总结一下,大概知道有这些属性值就行:

1、开关状态,数值:
STATE_OFF=10, STATE_TURNING_ON=11, STATE_ON=12 ,STATE_TURNING_OFF=13 

2、绑定状态,数值::
BOND_NONE = 10, BOND_BONDING = 11, BOND_BONDED = 12

3、连接状态,数值:
STATE_DISCONNECTED=0, STATE_CONNECTING=1, STATE_CONNECTED=2, STATE_DISCONNECTING=3

除了上面三个,还有个是否可以连接和被发现状态

4、可被发现和连接状态:
SCAN_MODE_NONE=20, SCAN_MODE_CONNECTABLE=21, SCAN_MODE_CONNECTABLE_DISCOVERABLE=23

是否可被发现是有api可以控制的

蓝牙关闭是会进入不可发现和连接的 SCAN_MODE_NONE 状态。

    // 设置蓝牙可见性
    public void requestDiscoverable() {
    	LocalBluetoothAdapter mLocalAdapter = mBluetoothManager.getBluetoothAdapter();
        mLocalAdapter.setDiscoverableTimeout(300); //注意单位是秒哦
        //可发现和可连接状态
        mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
    }

4、其他开发组对于这部分知识的总结

(1)Android 蓝牙基本开发知识介绍,包含一些常用的api和广播

地址:https://www.jianshu.com/p/b15314d91df0

(3)Android 蓝牙驱动开发

地址: https://www.voycn.com/index.php/article/androidzhilanyaqudongkaifazongjie

(4)蓝牙通讯框架

https://zhuanlan.zhihu.com/p/500092347

(5)蓝牙广播-硬件信号相关的介绍

https://blog.51cto.com/u_12959/7464069

(6)之前写的蓝牙总结文章,有兴趣可以看看

Android无线蓝牙开发总结:

https://blog.csdn.net/wenzhi20102321/article/details/53870789

Android蓝牙4.0开发:

https://blog.csdn.net/wenzhi20102321/article/details/53893511

Android 蓝牙协议配置讲解:

https://blog.csdn.net/wenzhi20102321/article/details/125826972

Android13 原生设置应用蓝牙配对代码分析研究:

https://blog.csdn.net/wenzhi20102321/article/details/131648367

Android 实现蓝牙录音:

https://blog.csdn.net/wenzhi20102321/article/details/89714569

  • 29
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

峥嵘life

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值