BluetoothAdapter — 什么是它,方法和 Android 中的蓝牙管理

作者: IT Sectr 发布日期: 2026-07-16 阅读时间: 10 分钟

BluetoothAdapter — Android 的系统类,代表设备的本地蓝牙适配器。BluetoothAdapter 是 Android 中所有蓝牙操作的入口点:开启无线电 (enable)、扫描设备、管理可见性 (setScanMode)、获取适配器信息 (getName, getAddress, getState)。该类可通过 BluetoothManager.getAdapter() (API 18+) 或 BluetoothAdapter.getDefaultAdapter() 获取。在没有蓝牙模块的设备上,getDefaultAdapter() 返回 null。根据 Android Developers, 2026,BluetoothAdapter 是从 API 5 开始 Android 上任何 BLE 应用程序的必需组件。

要点

  • BluetoothAdapter — Android 的系统类,用于管理设备的本地蓝牙适配器
  • getDefaultAdapter() — 用于获取实例的静态方法;在没有蓝牙的设备上返回 null
  • getBluetoothLeScanner() — 访问现代 BLE 扫描器的方法 (API 21+)
  • enable/disable — 开启和关闭蓝牙无线电的方法(需要 BLUETOOTH_ADMIN 权限)
  • startDiscovery/startLeScan — 经典和 BLE 扫描的方法(LE Scan 已弃用,请使用 BluetoothLeScanner)

什么是 BluetoothAdapter:本质和获取实例

BluetoothAdapter 代表 Android 设备的物理蓝牙适配器。每个设备恰好有一个适配器(例外 — 具有多个蓝牙芯片的 Android Automotive,其中使用 BluetoothManager.getAdapterList())。BluetoothAdapter 封装了无线电状态:STATE_OFF (0)、STATE_TURNING_ON (1)、STATE_ON (2)、STATE_TURNING_OFF (3)。状态通过 BroadcastReceiver 在 ACTION_STATE_CHANGED 上跟踪。

获取 BluetoothAdapter 实例是 Android 上任何 BLE 应用程序的第一步。推荐的方法 — 通过 BluetoothManager.getAdapter() 从 API 18+ 开始。替代方法 — BluetoothAdapter.getDefaultAdapter() 静态方法,从 API 5 开始工作,但灵活性较差。如果设备没有蓝牙模块(仅 Wi-Fi 的平板电脑、模拟器),两种方法都返回 null。null 检查是强制性的:应用程序必须正确终止或禁用 BLE 功能。

kotlin
// 获取 BluetoothAdapter(推荐)
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothManager
import android.content.Context

class BluetoothHelper(context: Context) {

    private val bluetoothAdapter: BluetoothAdapter?

    init {
        // 方法 1:通过 BluetoothManager (API 18+)
        val manager = context.getSystemService(Context.BLUETOOTH_SERVICE)
                as BluetoothManager?
        bluetoothAdapter = manager?.adapter

        // 方法 2:通过静态方法 (API 5+)
        // val adapter = BluetoothAdapter.getDefaultAdapter()

        // 空值检查
        if (bluetoothAdapter == null) {
            // 设备不支持蓝牙
        }
    }

    // 检查蓝牙状态
    fun isBluetoothEnabled(): Boolean {
        return bluetoothAdapter?.isEnabled == true
    }

    // 获取适配器信息
    fun getAdapterInfo(): Map<String, String> {
        return mapOf(
            "name" to (bluetoothAdapter?.name ?: "N/A"),
            "address" to (bluetoothAdapter?.address ?: "N/A"),
            "state" to (bluetoothAdapter?.state?.toString() ?: "N/A"),
            "scanMode" to (bluetoothAdapter?.scanMode?.toString() ?: "N/A")
        )
    }
}

BluetoothHelper 类演示了通过 BluetoothManager 获取 BluetoothAdapter 并进行后续的 null 检查。isBluetoothEnabled 检查 isEnabled — 在任何 BLE 操作之前的强制条件。getAdapterInfo 返回设备名称、MAC 地址、状态和可见性模式。重要:在 Android 10+ (API 29+) 上,如果应用程序没有 BLUETOOTH_ADMIN 和 ACCESS_FINE_LOCATION 权限,系统服务将返回虚假的 MAC 地址 (02:00:00:00:00:00)。

BluetoothAdapter 的主要方法:enable, disable, getState, getAddress

BluetoothAdapter 提供了管理蓝牙无线电的方法。enable() 和 disable() 开启和关闭蓝牙。这两种方法都需要 BLUETOOTH_ADMIN 权限并异步执行:调用 enable() 后,系统启动无线电开启过程,状态通过 BroadcastReceiver 以 BluetoothAdapter.ACTION_STATE_CHANGED 动作跟踪。从 Android 10+ 开始,enable() 和 disable() 需要额外的系统权限 — 普通应用程序在没有用户对话框的情况下无法以编程方式管理蓝牙。

getState() 返回适配器的当前状态:STATE_OFF (10)、STATE_TURNING_ON (11)、STATE_ON (12)、STATE_TURNING_OFF (13)。getAddress() 返回蓝牙适配器的 MAC 地址。在 Android 6+ 上,请求 MAC 地址需要 ACCESS_FINE_LOCATION(或 API 31+ 的 ACCESS_COARSE_LOCATION)。在 Android 10+ 上,getAddress() 返回常量地址 02:00:00:00:00:00 — 真实地址无法通过公共 API 获取。

getScanMode() 确定适配器的可见性模式:SCAN_MODE_NONE(不可见)、SCAN_MODE_CONNECTABLE(对已连接设备可见)、SCAN_MODE_CONNECTABLE_DISCOVERABLE(对所有设备可见)。可见性模式出于安全原因有时间限制(通常为 60-300 秒)。通过 setScanMode() 设置模式需要 BLUETOOTH_ADMIN 和 Android 10+ 上的系统权限。

方法描述所需权限
enable()开启蓝牙无线电BLUETOOTH_ADMIN
disable()关闭蓝牙无线电BLUETOOTH_ADMIN
getState()适配器的当前状态BLUETOOTH
getAddress()适配器的 MAC 地址BLUETOOTH + ACCESS_FINE_LOCATION (API 23+)
getScanMode()设备的可见性模式BLUETOOTH
setScanMode()设置可见性模式BLUETOOTH_ADMIN

扫描设备:startDiscovery 和 BluetoothLeScanner

BluetoothAdapter 支持两种类型的扫描。经典蓝牙扫描 (BR/EDR) 通过 startDiscovery() 启动 — 检测所有类型的蓝牙设备,包括手机和耳机。结果通过 BroadcastReceiver 以 BluetoothDevice.ACTION_FOUND 动作返回。startDiscovery() 工作 12 秒,可以通过调用 cancelDiscovery() 取消。此方法已弃用于 BLE — 请使用 BluetoothLeScanner。

通过 BluetoothAdapter 进行 BLE 扫描使用已弃用的方法 startLeScan(LeScanCallback)。从 API 21 开始,Google 建议使用 BluetoothLeScanner,通过 BluetoothAdapter.getBluetoothLeScanner() 获取。BluetoothLeScanner 提供了更灵活的 API:通过 ScanSettings 进行扫描配置(模式、回调类型、匹配模式),通过 ScanFilter 进行过滤(按服务 UUID、设备名称、MAC 地址)以及支持 PendingIntent 进行后台扫描。

kotlin
// 旧的(已弃用)与新的 BLE 扫描 API
import android.bluetooth.BluetoothAdapter
import android.bluetooth.le.*

class BLEScanner(private val bluetoothAdapter: BluetoothAdapter?) {

    // 已弃用:startLeScan (API 18+, API 21)
    @Suppress("DEPRECATION")
    fun legacyScan() {
        bluetoothAdapter?.startLeScan { device, rssi, scanRecord ->
            print("Found (LE Scan): $device.name, RSSI: $rssi")
        }
    }

    // 新的:BluetoothLeScanner (API 21+)
    fun modernScan() {
        val scanner = bluetoothAdapter?.bluetoothLeScanner
            ?: return

        // 扫描设置
        val settings = ScanSettings.Builder()
            .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
            .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
            .setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE)
            .build()

        // 按服务过滤(心率 UUID)
        val filters = listOf(
            ScanFilter.Builder()
                .setServiceUuid(ParcelUuid.fromString("0000180D-0000-1000-8000-00805F9B34FB"))
                .build()
        )

        // 开始扫描
        scanner.startScan(filters, settings, object : ScanCallback() {
            override fun onScanResult(callbackType: Int, result: ScanResult) {
                val device = result.device
                val rssi = result.rssi
                print("Found (BLE Scanner): ${device.name}, RSSI: $rssi, address: ${device.address}")
            }

            override fun onScanFailed(errorCode: Int) {
                print("Scan error: $errorCode")
            }
        })
    }
}

BLEScanner 类比较已弃用的 startLeScan 和现代的 BluetoothLeScanner。在 legacyScan 中,LeScanCallback 回调接收 BluetoothDevice、RSSI 和原始 scanRecord。在 modernScan 中,使用带有 LOW_LATENCY 模式(最大检测速度)的 ScanSettings 和用于按心率服务 UUID (Heart Rate Service 0x180D) 过滤的 ScanFilter。ScanCallback 提供带有 ScanResult 对象的 onScanResult,该对象包含扩展信息:名称、RSSI、广播数据、连接类型。

BluetoothManager:访问 BluetoothAdapter 的现代 API

BluetoothManager — Android 系统服务,在 API 18 (Android 4.3) 中引入,用于管理蓝牙操作。在 API 18 之前,获取 BluetoothAdapter 的唯一方法是 getDefaultAdapter() 静态方法。BluetoothManager 提供:adapter — BluetoothAdapter 实例,getConnectedDevices() — 已连接设备的列表,getDevicesMatchingConnectionStates() — 按状态过滤。BluetoothManager 也用于在旧 API 上获取 BluetoothLeScanner。

BluetoothManager 的优势 相对于直接调用 BluetoothAdapter.getDefaultAdapter():应用程序不依赖于静态单例,管理器考虑上下文 (Activity/Application),这对 Android Enterprise 的多账户场景很重要。在具有多个蓝牙芯片的 Android Automotive 上,BluetoothManager.getAdapterList() 返回所有可用的适配器 — BluetoothAdapter.getDefaultAdapter() 只返回第一个。

kotlin
// 使用 BluetoothManager 进行 BLE
class BLEConnection(context: Context) {

    private val bluetoothManager: BluetoothManager =
        context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager

    private val adapter: BluetoothAdapter? = bluetoothManager.adapter

    // 获取已连接的 BLE 设备列表
    fun getConnectedDevices(): List<BluetoothDevice> {
        return bluetoothManager.getConnectedDevices(
            BluetoothProfile.GATT
        )
    }

    // 按状态过滤设备
    fun getDevicesByState(states: IntArray): List<BluetoothDevice> {
        return bluetoothManager.getDevicesMatchingConnectionStates(
            BluetoothProfile.GATT, states
        )
    }

    // 检查设备上的 BLE 支持
    fun isBLESupported(): Boolean {
        return adapter != null && context.packageManager
            .hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)
    }

    // 通过系统对话框请求开启蓝牙
    fun requestEnableBluetooth(activity: MainActivity) {
        if (adapter?.isEnabled == false) {
            val intent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
            activity.startActivityForResult(intent, REQUEST_ENABLE_BT)
        }
    }

    companion object {
        const val REQUEST_ENABLE_BT = 1001
    }
}

BLEConnection 类使用 BluetoothManager 来访问 BluetoothAdapter 并获取已连接 GATT 设备的列表。isBLESupported 通过 PackageManager.hasSystemFeature(FEATURE_BLUETOOTH_LE) 检查 BLE 无线电的存在 — 这对于具有蓝牙经典但没有 BLE 的设备来说是很重要的检查。requestEnableBluetooth 显示用于开启蓝牙的系统对话框 (ACTION_REQUEST_ENABLE),无需 BLUETOOTH_ADMIN 权限 — 这是在 Android 10+ 上没有系统应用程序的情况下开启蓝牙的唯一合法方式。

使用 BluetoothAdapter 的 Android 权限

权限 对于 BluetoothAdapter 随着每个 Android 版本而演变。在 Android 6-11 (API 23-30) 上,BLE 扫描需要 BLUETOOTH、BLUETOOTH_ADMIN 和 ACCESS_FINE_LOCATION。在 Android 12+ (API 31+) 上,Google 划分了权限:ACCESS_FINE_LOCATION 被 BLUETOOTH_SCAN(扫描)、BLUETOOTH_CONNECT(连接)、BLUETOOTH_ADVERTISE(广播)取代。搜索 BLE 设备时,BLUETOOTH_SCAN 就足够了,不需要位置信息。

权限表 按 Android 版本:

操作API 23-30API 31+
BLE 扫描ACCESS_FINE_LOCATIONBLUETOOTH_SCAN(无需位置)
连接 BLEACCESS_FINE_LOCATIONBLUETOOTH_CONNECT
BLE 广播ACCESS_FINE_LOCATIONBLUETOOTH_ADVERTISE
开启/关闭BLUETOOTH_ADMINBLUETOOTH_ADMIN(系统)
获取 MAC 地址ACCESS_FINE_LOCATIONBLUETOOTH_CONNECT(虚假地址)

在 Android 12+ 上,所有蓝牙权限都是运行时权限 — 必须通过 ActivityResultContracts.RequestMultiplePermissions 在运行时请求。BLUETOOTH_SCAN 和 BLUETOOTH_ADVERTISE 属于 NEARBY_DEVICES 组,BLUETOOTH_CONNECT — 属于同一组。BLUETOOTH 和 BLUETOOTH_ADMIN 权限保留在清单中以便与 API < 31 兼容,但对于 API 31+,它们被忽略 — Google 要求明确指定新权限。

kotlin
// 在 Android 12+ 上请求蓝牙权限
import android.Manifest
import android.content.pm.PackageManager
import android.os.Build
import androidx.core.content.ContextCompat

class PermissionHelper(context: Context) {

    fun getRequiredPermissions(): Array<String> {
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            // Android 12+: BLE 扫描
            arrayOf(
                Manifest.permission.BLUETOOTH_SCAN,
                Manifest.permission.BLUETOOTH_CONNECT,
                Manifest.permission.BLUETOOTH_ADVERTISE
            )
        } else {
            // Android 6-11: BLE 扫描
            arrayOf(
                Manifest.permission.ACCESS_FINE_LOCATION,
                Manifest.permission.BLUETOOTH,
                Manifest.permission.BLUETOOTH_ADMIN
            )
        }
    }

    // 检查所有权限
    fun hasPermissions(context: Context): Boolean {
        return getRequiredPermissions().all { permission ->
            ContextCompat.checkSelfPermission(context, permission)
                    == PackageManager.PERMISSION_GRANTED
        }
    }
}

PermissionHelper 类根据 API 级别返回正确的权限集。在 Android 12+ 上,使用 BLUETOOTH_SCAN、BLUETOOTH_CONNECT、BLUETOOTH_ADVERTISE 无需位置信息。在 Android 6-11 上,BLE 扫描仍需要 ACCESS_FINE_LOCATION。开发人员在通过 ActivityResultContracts 或 RxPermissions 请求权限时必须考虑这两种情况。

在 Kotlin 中使用 BluetoothAdapter 的完整示例

完整示例 — 在 Kotlin 中使用 BluetoothAdapter 进行扫描、连接和读取 BLE 设备数据的 BLE 应用程序。该示例涵盖了权限检查、获取适配器、通过 BluetoothLeScanner 进行扫描以及通过 BluetoothDevice.connectGatt 进行连接。

kotlin
// Kotlin 中的完整 BLE 管理器
class BLEManager(private val context: Context) {

    private val bluetoothManager: BluetoothManager =
        context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
    private val adapter: BluetoothAdapter? = bluetoothManager.adapter
    private var scanner: BluetoothLeScanner? = adapter?.bluetoothLeScanner
    private var gatt: BluetoothGatt? = null

    // 1. 服务发现
    fun canScan(): Boolean {
        return adapter?.isEnabled == true
                && scanner != null
                && PermissionHelper(context).hasPermissions(context)
    }

    // 2. 带过滤器的扫描
    fun startScanning(callback: (BluetoothDevice, Int) -> Unit) {
        if (!canScan()) return

        val settings = ScanSettings.Builder()
            .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
            .setReportDelay(0)
            .build()

        scanner?.startScan(null, settings, object : ScanCallback() {
            override fun onScanResult(callbackType: Int, result: ScanResult) {
                callback(result.device, result.rssi)
            }
        })
    }

    // 3. 停止扫描
    fun stopScanning() {
        scanner?.stopScan(object : ScanCallback() {})
    }

    // 4. 连接到 BLE 设备
    fun connectToDevice(device: BluetoothDevice) {
        if (adapter?.isEnabled != true) return

        gatt = device.connectGatt(
            context,
            false,
            object : BluetoothGattCallback() {
                override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
                    if (newState == BluetoothProfile.STATE_CONNECTED) {
                        gatt.discoverServices()
                    }
                }

                override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
                    // 已找到服务,可以读取特征
                }
            },
            BluetoothDevice.TRANSPORT_LE
        )
    }

    // 5. 释放资源
    fun disconnect() {
        gatt?.disconnect()
        gatt?.close()
        gatt = null
    }
}

BLEManager 管理器在 Android 上整合了完整的 BLE 循环:适配器和权限检查 (canScan)、通过 BluetoothLeScanner 使用 ScanSettings 进行扫描 (startScanning)、通过 BluetoothDevice.connectGatt 使用 TRANSPORT_LE 进行连接 (connectToDevice)、释放资源 (disconnect)。所有 BLE 操作都在 UI 线程上执行 — Android 在主线程上调用 BluetoothGattCallback 回调。对于高性能的 BLE 任务,建议将 GATT 操作转移到后台 HandlerThread。

常见问题

Android 中的 BluetoothAdapter 是什么?

BluetoothAdapter — 代表 Android 设备本地蓝牙适配器的类。通过 BluetoothManager.getAdapter() (API 18+) 或 BluetoothAdapter.getDefaultAdapter() 获取。提供开启/关闭蓝牙、扫描设备、管理可见性和获取适配器信息的方法。在没有蓝牙模块的设备上返回 null。

为什么 BluetoothAdapter.getDefaultAdapter() 返回 null?

原因 — 设备上没有蓝牙无线电。常见于仅 Wi-Fi 的平板电脑、Android 模拟器和没有蓝牙的 Android TV。在应用程序启动时检查 getDefaultAdapter() 是否为 null,如果适配器不存在,请禁用 BLE 功能。替代方法 — 通过 PackageManager.hasSystemFeature(FEATURE_BLUETOOTH_LE) 进行检查以更精确地确定。

BluetoothLeScanner 与 startLeScan 有何不同?

BluetoothLeScanner (API 21+) — 用于 BLE 扫描的现代 API,支持 ScanFilter、ScanSettings 和 PendingIntent。startLeScan (API 18+) — BluetoothAdapter 的已弃用方法,接受带有有限数据集的 LeScanCallback。Google 推荐所有新项目使用 BluetoothLeScanner,它允许按 UUID 过滤、配置功耗模式以及通过 PendingIntent 在后台工作。

Android 12+ 上的 BLE 需要哪些权限?

在 Android 12+ (API 31) 上,BLE 扫描需要 BLUETOOTH_SCAN,连接需要 BLUETOOTH_CONNECT,广播需要 BLUETOOTH_ADVERTISE。位置权限 ACCESS_FINE_LOCATION 不再是 BLE 所必需的。在 Android 6-11 上需要 ACCESS_FINE_LOCATION。所有权限都通过 ActivityResultContracts 在运行时请求。

是否可以在没有对话框的情况下以编程方式开启蓝牙?

从 Android 10+ 开始,没有系统对话框的编程式蓝牙开启仅适用于具有 BLUETOOTH_PRIVILEGED 权限的系统应用程序。普通应用程序必须使用 Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) 和 startActivityForResult — 用户在系统对话框中确认开启。清单中的 BLUETOOTH_ADMIN 在 Android 10+ 上不提供 enable() 权限。

总结

  • BluetoothAdapter — Android 上所有蓝牙操作的入口点,通过 BluetoothManager 或 getDefaultAdapter() 获取
  • getState()isEnabled — 在任何 BLE 操作之前对蓝牙无线电状态的基本检查
  • BluetoothLeScanner (API 21+) 取代了已弃用的 startLeScan,支持 ScanFilter、ScanSettings 和 PendingIntent
  • BluetoothManager — 获取 BluetoothAdapter 的现代方式,支持多账户场景和 Automotive
  • 权限 已经演变:ACCESS_FINE_LOCATION (API 23-30) → BLUETOOTH_SCAN/CONNECT/ADVERTISE (API 31+)
  • enable()/disable() — 在 Android 10+ 上,对于普通应用程序只能通过 ACTION_REQUEST_ENABLE 系统对话框
  • connectGatt — BluetoothDevice 的方法,通过 BluetoothGattCallback 与 BLE 外设建立 GATT 连接

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读