You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Android设备配置为BLE设备,使其可被其他设备检测?

兄弟,我来帮你搞定把Android设备变成BLE外设的问题——之前你做的是中心设备(搜索连接其他BLE设备),现在要转成外设模式让其他设备发现你,其实Android从API 21(Android 5.0)开始就支持这个功能了,我给你一步步拆解,连常见坑都给你列出来:

先确认前提条件
  • 你的Android设备必须运行Android 5.0(API 21)及以上,这是BLE外设模式的最低系统要求。
  • 部分低端设备可能硬件不支持该模式,先通过代码确认:
    val bluetoothAdapter = (getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager).adapter
    if (!bluetoothAdapter.isMultipleAdvertisementSupported) {
        Toast.makeText(this, "当前设备不支持BLE外设模式", Toast.LENGTH_SHORT).show()
        return
    }
    
步骤1:配置权限

根据Android版本不同,权限要求有差异,先在AndroidManifest.xml里添加基础权限:

<!-- 基础BLE权限(Android 11及以下) -->
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
<!-- Android 12+ 外设模式核心权限 -->
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<!-- 定位权限(Android 10及以下扫描需要,部分设备外设模式也要求) -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" />

<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />

Android 12+需要动态申请BLUETOOTH_ADVERTISE和BLUETOOTH_CONNECT权限:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
    val permissions = arrayOf(
        Manifest.permission.BLUETOOTH_ADVERTISE,
        Manifest.permission.BLUETOOTH_CONNECT
    )
    if (ContextCompat.checkSelfPermission(this, permissions[0]) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, permissions, 1001)
    }
}
步骤2:初始化BLE外设核心组件

你需要用到BluetoothLeAdvertiser(负责广播)和BluetoothGattServer(处理设备连接、读写请求):

val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
val bluetoothAdapter = bluetoothManager.adapter

// 获取广播器
val advertiser = bluetoothAdapter.bluetoothLeAdvertiser ?: run {
    Toast.makeText(this, "无法获取BLE广播组件", Toast.LENGTH_SHORT).show()
    return
}
步骤3:创建GATT服务与特征

外设需要提供可被中心设备读写的服务和特征,这是BLE通信的核心载体:

// 自定义服务和特征的UUID(可以自己生成,也用通用UUID)
val SERVICE_UUID = UUID.fromString("0000FFE0-0000-1000-8000-00805F9B34FB")
val CHAR_UUID = UUID.fromString("0000FFE1-0000-1000-8000-00805F9B34FB")

// 创建主服务
val gattService = BluetoothGattService(SERVICE_UUID, BluetoothGattService.SERVICE_TYPE_PRIMARY)

// 创建特征:支持读、写、通知
val gattChar = BluetoothGattCharacteristic(
    CHAR_UUID,
    BluetoothGattCharacteristic.PROPERTY_READ or BluetoothGattCharacteristic.PROPERTY_WRITE or BluetoothGattCharacteristic.PROPERTY_NOTIFY,
    BluetoothGattCharacteristic.PERMISSION_READ or BluetoothGattCharacteristic.PERMISSION_WRITE
)

gattService.addCharacteristic(gattChar)

// 启动GattServer,处理连接和读写事件
val gattServer = bluetoothManager.openGattServer(this, object : BluetoothGattServerCallback() {
    override fun onConnectionStateChange(device: BluetoothDevice?, status: Int, newState: Int) {
        super.onConnectionStateChange(device, status, newState)
        when(newState) {
            BluetoothProfile.STATE_CONNECTED -> Log.d("BLE外设", "已连接设备: ${device?.name}")
            BluetoothProfile.STATE_DISCONNECTED -> Log.d("BLE外设", "设备已断开")
        }
    }

    override fun onCharacteristicReadRequest(device: BluetoothDevice?, requestId: Int, offset: Int, characteristic: BluetoothGattCharacteristic?) {
        super.onCharacteristicReadRequest(device, requestId, offset, characteristic)
        // 返回特征数据给请求设备
        gattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, characteristic?.value)
    }

    override fun onCharacteristicWriteRequest(device: BluetoothDevice?, requestId: Int, characteristic: BluetoothGattCharacteristic?, preparedWrite: Boolean, responseNeeded: Boolean, offset: Int, value: ByteArray?) {
        super.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value)
        // 处理收到的写入数据
        value?.let { Log.d("BLE外设", "收到数据: ${String(it)}") }
        if (responseNeeded) {
            gattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, null)
        }
    }
})

// 将服务添加到GattServer
gattServer.addService(gattService)
步骤4:启动BLE广播

配置广播参数和数据,让其他设备能发现你的设备:

// 广播设置:低功耗模式,允许连接,持续广播
val advertiseSettings = AdvertiseSettings.Builder()
    .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_POWER)
    .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM)
    .setConnectable(true)
    .setTimeout(0) // 0表示无限广播
    .build()

// 广播数据:包含设备名称和服务UUID(让中心设备知道你提供的服务)
val advertiseData = AdvertiseData.Builder()
    .setIncludeDeviceName(true)
    .addServiceUuid(ParcelUuid(SERVICE_UUID))
    .build()

// 启动广播
advertiser.startAdvertising(advertiseSettings, advertiseData, object : AdvertiseCallback() {
    override fun onStartSuccess(settingsInEffect: AdvertiseSettings?) {
        super.onStartSuccess(settingsInEffect)
        Log.d("BLE外设", "广播启动成功")
    }

    override fun onStartFailure(errorCode: Int) {
        super.onStartFailure(errorCode)
        val errorMsg = when(errorCode) {
            ADVERTISE_FAILED_ALREADY_STARTED -> "广播已启动"
            ADVERTISE_FAILED_DATA_TOO_LARGE -> "广播数据过大(超过31字节)"
            ADVERTISE_FAILED_FEATURE_UNSUPPORTED -> "设备不支持该广播特性"
            ADVERTISE_FAILED_INTERNAL_ERROR -> "系统内部错误"
            ADVERTISE_FAILED_TOO_MANY_ADVERTISERS -> 当前环境广播设备过多"
            else -> "未知错误: $errorCode"
        }
        Log.e("BLE外设", "广播启动失败: $errorMsg")
    }
})
常见问题排查
  1. 其他设备搜不到你的设备:
    • 检查权限是否申请成功,特别是Android 12+的BLUETOOTH_ADVERTISE权限。
    • 广播数据不要超过31字节,比如设备名称过长会导致广播失败。
    • 确认setConnectable(true)已设置,否则中心设备可能无法发现。
  2. 能发现但无法连接:
    • 检查GattServer是否正确添加了服务,回调是否正常工作。
    • 部分设备需要开启定位才能扫描BLE设备,让测试设备打开定位试试。
  3. 广播启动失败:
    • 根据onStartFailure的错误码针对性排查,比如ADVERTISE_FAILED_TOO_MANY_ADVERTISERS可以换个环境试试。

内容的提问来源于stack exchange,提问作者Grigoriy Park

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:40:48