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

Estimote UWB Android SDK多Beacon连接异常问题咨询

问题分析与解决方案

问题背景

开发Android室内导航应用,采用3个Estimote UWB Beacon及无官方文档的Estimote Android UWB SDK。单Beacon连接时可正常获取位置数据(示例日志:Position of 7B:ED : Distance=0.14999998, Azimuth=null, Elevation=null),但连接第二个Beacon时触发以下错误日志:

  • Creating Gms Client session scope
  • Error when removing Please check that the ranging is active and theranging profile supports multi-device ranging.
  • RangingResultPeerDisconnected address:20:00

不确定问题源于代码、SDK限制,还是Pixel 7 Pro的UWB多设备支持能力。

核心问题排查

1. 代码逻辑缺陷

从提供的代码来看,存在多处影响多设备连接的问题:

  • 重复启动/停止扫描:在startUWBScanning中,两次调用launchUWBConnection时都执行uwbManager.startDeviceScanning,且最后立刻调用uwbManager.stopDeviceScanning,导致扫描流程被中断,无法维持多设备的测距会话。
  • 错误的扫描触发时机:每个设备连接时单独启动扫描,不符合UWB扫描的全局逻辑——扫描应仅启动一次,用于发现所有目标Beacon,而非为每个设备重复启动。
  • 协程生命周期未绑定:使用CoroutineScope(Dispatchers.Main.immediate).launch创建无绑定的协程,可能导致内存泄漏,且多设备的rangingResult.collect可能出现冲突。
  • 直接使用固定蓝牙地址:未通过扫描发现设备,直接用硬编码地址获取BluetoothDevice,可能存在设备未处于可连接状态的情况。

2. 设备兼容性确认

Pixel 7 Pro硬件支持UWB,且Google的UWB官方API明确支持多设备测距,因此硬件层面不存在多设备连接限制,问题排除设备硬件因素。

3. SDK潜在限制

错误日志中明确提示ranging profile supports multi-device ranging,说明SDK可能需要配置特定的测距Profile以启用多设备支持。由于SDK无官方文档,需尝试以下方向:

  • 检查EstimoteUWBManager初始化或连接时是否有隐藏的Profile配置参数,用于开启多设备测距。
  • 确认SDK是否支持同时连接多个UWB Beacon,部分厂商的UWB SDK可能存在单设备限制。

修正后的代码示例

以下是针对代码问题的优化版本:

class MainActivity : ComponentActivity() {
    private lateinit var uwbManager: EstimoteUWBManager
    private val lifecycleScope = LifecycleCoroutineScope(this.lifecycle)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.login)

        val usernameEditText = findViewById<EditText>(R.id.username)
        val passwordEditText = findViewById<EditText>(R.id.password)
        val loginButton = findViewById<Button>(R.id.loginbtn)

        loginButton.setOnClickListener {
            lifecycleScope.launch {
                val username = usernameEditText.text.toString()
                val password = passwordEditText.text.toString()

                val encryptedUsername = encryptWithPublicKey(username, publicKeyPEM)
                val encryptedPassword = encryptWithPublicKey(password, publicKeyPEM)

                sendSignInCredentialsToLambda(encryptedUsername, encryptedPassword, applicationContext)
            }
        }

        checkPermissionsAndStartUWB()
    }

    private fun checkPermissionsAndStartUWB() {
        val requiredPermissions = arrayOf(
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.BLUETOOTH_CONNECT,
            Manifest.permission.BLUETOOTH_SCAN,
            Manifest.permission.UWB_RANGING
        )

        if (requiredPermissions.all {
                ContextCompat.checkSelfPermission(this, it) == PackageManager.PERMISSION_GRANTED
            }) {
            initUWBManager()
        } else {
            ActivityCompat.requestPermissions(this, requiredPermissions, 1)
        }
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == 1 && grantResults.all { it == PackageManager.PERMISSION_GRANTED }) {
            initUWBManager()
        } else {
            Log.d("PERMISSIONS", "Some permissions are denied")
        }
    }

    private fun initUWBManager() {
        uwbManager = EstimoteUWBFactory.create()
        uwbManager.init(this, this) { deniedRequirements ->
            deniedRequirements.forEach {
                Log.d("UWBInit", "Requirement denied: $it")
            }
            // 初始化完成后启动扫描和多设备连接
            startMultiDeviceUWBRanging()
        }
    }

    private fun startMultiDeviceUWBRanging() {
        val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
        val targetDeviceAddresses = listOf("D8:EB:87:DF:E7:BE", "EC:01:7C:7F:67:50")
        val targetDevices = targetDeviceAddresses.mapNotNull { address ->
            bluetoothAdapter?.getRemoteDevice(address)
        }

        // 仅启动一次扫描
        lifecycleScope.launch {
            uwbManager.startDeviceScanning(applicationContext)
        }

        // 批量连接目标设备
        targetDevices.forEach { device ->
            connectAndRangeDevice(device)
        }
    }

    private fun connectAndRangeDevice(device: BluetoothDevice) {
        lifecycleScope.launch {
            // 连接设备
            uwbManager.connect(device, applicationContext)
            // 监听该设备的测距结果
            uwbManager.rangingResult.collect { result ->
                when (result) {
                    is EstimoteUWBRangingResult.Position -> {
                        // 仅处理当前设备的结果
                        if (result.device.address == device.address) {
                            val position = result.position
                            val positionInfo = "Position of ${result.device.address} : Distance=${position.distance?.value}, Azimuth=${position.azimuth?.value}, Elevation=${position.elevation?.value}"
                            Log.d("UWBResult", positionInfo)
                        }
                    }
                    is EstimoteUWBRangingResult.PeerDisconnected -> {
                        Log.d("UWBResult", "Device disconnected: ${result.device.address}")
                    }
                    else -> {
                        // 处理其他结果类型
                    }
                }
            }
        }
    }

    fun onRegisterClick(view: View) {
        val intent = Intent(this, SignUpActivity::class.java)
        startActivity(intent)
    }

    override fun onDestroy() {
        super.onDestroy()
        // 停止扫描和连接,释放资源
        lifecycleScope.launch {
            uwbManager.stopDeviceScanning()
            // 若SDK提供断开所有连接的API,此处调用
        }
    }
}

额外建议

  1. 若SDK支持配置测距Profile,尝试查找是否有setRangingProfile或类似方法,设置为支持多设备的模式。
  2. 检查Beacon的固件版本,确保所有Beacon处于同一固件版本,避免兼容性问题。
  3. 增加错误处理逻辑,捕获connect方法可能抛出的异常,排查连接失败的具体原因。

内容的提问来源于stack exchange,提问作者Davide Paolillo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 22:07:03