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

同一安卓设备双APP实现BLE GATT Client与Server角色开发咨询

同一设备上实现安卓GATT Client与Peripheral(Server)通信

核心实现步骤(Kotlin示例)

一、GATT Server(Peripheral端)

  1. 权限配置
    在AndroidManifest.xml中添加必要权限:
<!-- Android 12+ 权限 -->
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<!-- 旧版本兼容 -->
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
  1. 初始化广播与GATT服务
// 获取BluetoothAdapter
val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
// 初始化BLE广播器
val advertiser = bluetoothAdapter.bluetoothLeAdvertiser

// 创建自定义服务和特征UUID
val serviceUuid = UUID.fromString("0000FFE0-0000-1000-8000-00805F9B34FB")
val characteristicUuid = UUID.fromString("0000FFE1-0000-1000-8000-00805F9B34FB")

// 创建GATT服务
val gattService = BluetoothGattService(serviceUuid, BluetoothGattService.SERVICE_TYPE_PRIMARY)
// 创建可读写、支持通知的特征
val characteristic = BluetoothGattCharacteristic(
    characteristicUuid,
    BluetoothGattCharacteristic.PROPERTY_READ or BluetoothGattCharacteristic.PROPERTY_WRITE or BluetoothGattCharacteristic.PROPERTY_NOTIFY,
    BluetoothGattCharacteristic.PERMISSION_READ or BluetoothGattCharacteristic.PERMISSION_WRITE
)
gattService.addCharacteristic(characteristic)

// 初始化GATT Server回调
val gattServerCallback = object : BluetoothGattServerCallback() {
    override fun onConnectionStateChange(device: BluetoothDevice?, status: Int, newState: Int) {
        super.onConnectionStateChange(device, status, newState)
        // 处理连接/断开事件
        if (newState == BluetoothProfile.STATE_CONNECTED) {
            // 客户端已连接
        }
    }

    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 {
            val receivedData = String(it)
            // 业务逻辑处理
        }
        // 响应客户端写入请求
        bluetoothGattServer?.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, null)
    }
}

// 启动GATT Server
val bluetoothGattServer = bluetoothManager.openGattServer(this, gattServerCallback)
bluetoothGattServer?.addService(gattService)

// 配置广播参数
val advertiseSettings = AdvertiseSettings.Builder()
    .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY)
    .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH)
    .setConnectable(true)
    .build()

// 设置广播数据(包含服务UUID)
val advertiseData = AdvertiseData.Builder()
    .addServiceUuid(ParcelUuid(serviceUuid))
    .build()

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

    override fun onStartFailure(errorCode: Int) {
        super.onStartFailure(errorCode)
        // 处理广播启动失败,比如权限不足、蓝牙未开启
    }
})

二、GATT Client端

  1. 权限配置
    除了Server端的权限,还需要添加扫描权限:
<!-- Android 12+ 扫描权限 -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<!-- 旧版本需要位置权限 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" />
  1. 扫描与连接逻辑
val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
val targetServiceUuid = UUID.fromString("0000FFE0-0000-1000-8000-00805F9B34FB")
val characteristicUuid = UUID.fromString("0000FFE1-0000-1000-8000-00805F9B34FB")

// 配置扫描过滤器,只扫描目标服务UUID的设备
val scanFilter = ScanFilter.Builder()
    .setServiceUuid(ParcelUuid(targetServiceUuid))
    .build()
val scanSettings = ScanSettings.Builder()
    .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
    .build()

// 启动扫描
bluetoothAdapter.bluetoothLeScanner.startScan(
    listOf(scanFilter),
    scanSettings,
    object : ScanCallback() {
        override fun onScanResult(callbackType: Int, result: ScanResult?) {
            super.onScanResult(callbackType, result)
            result?.device?.let { device ->
                // 停止扫描
                bluetoothAdapter.bluetoothLeScanner.stopScan(this)
                // 发起GATT连接
                device.connectGatt(this@MainActivity, false, object : BluetoothGattCallback() {
                    override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) {
                        super.onConnectionStateChange(gatt, status, newState)
                        if (newState == BluetoothProfile.STATE_CONNECTED) {
                            // 连接成功,发现服务
                            gatt?.discoverServices()
                        }
                    }

                    override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
                        super.onServicesDiscovered(gatt, status)
                        if (status == BluetoothGatt.GATT_SUCCESS) {
                            // 获取目标服务和特征
                            gatt?.getService(targetServiceUuid)?.getCharacteristic(characteristicUuid)?.let { characteristic ->
                                // 写入数据到Server
                                val data = "Hello from Client".toByteArray()
                                characteristic.value = data
                                gatt.writeCharacteristic(characteristic)

                                // 监听特征通知(可选)
                                gatt.setCharacteristicNotification(characteristic, true)
                                val descriptor = characteristic.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805F9B34FB"))
                                descriptor.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
                                gatt.writeDescriptor(descriptor)
                            }
                        }
                    }

                    override fun onCharacteristicWrite(gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int) {
                        super.onCharacteristicWrite(gatt, characteristic, status)
                        if (status == BluetoothGatt.GATT_SUCCESS) {
                            // 数据写入成功
                        }
                    }
                })
            }
        }
    }
)

实用学习资源(无外链)

  • 在Stack Overflow搜索关键词「Android GATT client same device peripheral」,能找到大量开发者分享的实战代码、权限踩坑、同一设备通信的特殊处理技巧;
  • 安卓开发者社区的官方讨论板块中,有不少开发者分享了同一设备BLE通信的完整实现流程,包含版本兼容、广播优先级等细节;
  • 专注安卓BLE开发的技术博客合集里,会分章节讲解GATT Server/Client的搭建,以及同一设备运行时的进程隔离、蓝牙资源冲突解决方法。

内容的提问来源于stack exchange,提问作者Ahmer Iqbal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 23:48:23