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

Android经典蓝牙CompanionDeviceService未启动且无设备状态回调问题

经典蓝牙CompanionDevice实现问题:CompanionDeviceService未触发回调

我在实现经典蓝牙CompanionDevice功能,但设备进入范围、连接/断开时,对应的MyCompanionService从未被调用。测试环境为:安装应用的Android 12设备,作为Companion设备的Android 13设备。

以下是相关代码与配置:

清单文件中的权限与服务配置

<uses-permission android:name="android.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE"/>
<uses-permission android:name="android.permission.REQUEST_COMPANION_RUN_IN_BACKGROUND"/>
<uses-permission android:name="android.permission.REQUEST_COMPANION_USE_DATA_IN_BACKGROUND"/>

<service
        android:name=".MyCompanionService"
        android:label="My Companion Service"
        android:exported="true"
        android:permission="android.permission.BIND_COMPANION_DEVICE_SERVICE">
        <intent-filter>
            <action android:name="android.companion.CompanionDeviceService" />
        </intent-filter>
    </service>

MyCompanionService类代码

@RequiresApi(Build.VERSION_CODES.S)
class MyCompanionService: CompanionDeviceService() {

override fun onRebind(intent: Intent?) {
    super.onRebind(intent)
    Log.d("MyCompanionService", "Rebind ${intent.toString()}")
}

override fun onUnbind(intent: Intent?): Boolean {
    Log.d("MyCompanionService", "Unbind ${intent.toString()}")
    return super.onUnbind(intent)
}

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
    Log.d("MyCompanionService", "onStartCommand ${intent.toString()}")
    return super.onStartCommand(intent, flags, startId)
}

override fun onStart(intent: Intent?, startId: Int) {
    super.onStart(intent, startId)
    Log.d("MyCompanionService", "onStart ${intent.toString()}")
}

override fun onCreate() {
    super.onCreate()
    Log.d("MyCompanionService", "onCreate")
}

override fun onDeviceAppeared(address: String) {
    super.onDeviceAppeared(address)
    Log.d("MyCompanionService", "onDeviceAppeared ${address}")
}

override fun onDeviceAppeared(associationInfo: AssociationInfo) {
    super.onDeviceAppeared(associationInfo)
    Log.d("MyCompanionService", "onDeviceAppeared ${associationInfo}")
}

override fun onDeviceDisappeared(associationInfo: AssociationInfo) {
    super.onDeviceDisappeared(associationInfo)
    Log.d("MyCompanionService", "onDeviceDisappeared ${associationInfo}")
}

override fun onDeviceDisappeared(address: String) {
    super.onDeviceDisappeared(address)
    Log.d("MyCompanionService", "onDeviceDisappeared ${address}")
}

override fun onDestroy() {
    super.onDestroy()
    Log.d("MyCompanionService", "onDestroy")
}
}

设备配对及观察代码

private fun startCompanionAppPair() {
    val deviceFilter: BluetoothDeviceFilter = BluetoothDeviceFilter.Builder().build()

    val pairingRequest: AssociationRequest = AssociationRequest.Builder()
        .addDeviceFilter(deviceFilter)
        .build()

    deviceManager.associate(
        pairingRequest,
        object : CompanionDeviceManager.Callback() {
            @Deprecated("Deprecated in Java")
            override fun onDeviceFound(chooserLauncher: IntentSender) {
                startIntentSenderForResult(
                    chooserLauncher,
                    SELECT_DEVICE_REQUEST_CODE, null, 0, 0, 0
                )
            }

            override fun onFailure(error: CharSequence?) {
                // Handle the failure.
                println(error.toString())
            }
        }, null
    )

}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    when (requestCode) {
        SELECT_DEVICE_REQUEST_CODE -> when (resultCode) {
            Activity.RESULT_OK -> {
                // The user chose to pair the app with a Bluetooth device.
                //val deviceToPair: ScanResult? =
                val deviceToPair: BluetoothDevice? = data?.getParcelableExtra(CompanionDeviceManager.EXTRA_DEVICE)
                deviceToPair?.let { device ->
                    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED) {
                        device.createBond()
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
                            deviceManager.startObservingDevicePresence(device.address)
                    }
                    // Continue to interact with the paired device.
                }
            }
        }
        else -> super.onActivityResult(requestCode, resultCode, data)
    }
}

排查关键点

  • 确认Companion关联关系:调用deviceManager.getAssociations()检查是否存在目标设备的AssociationInfo。不要手动调用device.createBond(),CompanionDeviceManager.associate()会自动处理系统配对,手动调用可能破坏关联流程。
  • 补全权限申请:Android 12+需动态申请BLUETOOTH_SCAN、BLUETOOTH_CONNECT权限;通过deviceManager.hasPermissionForAssociation(associationId)验证REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE权限是否生效。
  • 修正Service配置:确保MyCompanionService的包名与清单声明完全一致,android:permission="android.permission.BIND_COMPANION_DEVICE_SERVICE"无拼写错误。
  • 正确启动设备观察:从onActivityResult的data中获取AssociationInfo(data.getParcelableExtra(CompanionDeviceManager.EXTRA_ASSOCIATION_INFO)),使用associationInfo.id调用startObservingDevicePresence,废弃的地址参数方法可能无法触发回调。
  • 检查后台权限:在系统设置中开启应用的“允许后台活动”,否则Android 12+会限制Service后台运行,无法接收设备状态回调。

内容的提问来源于stack exchange,提问作者Mahmoud Omara

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 19:53:18