使用Kotlin连接WearOS配套手表应用失败,求解决方案
问题背景
我已多日尝试将Jetpack Compose应用连接到Wear OS手表模拟器,模拟器已成功配对(Wear OS应用显示已连接到模拟器),但应用内始终无法建立连接。查阅官方示例、文档及AI工具后仍未解决,怀疑遗漏了某些步骤。最终需求是将蓝牙类的数据发送至手表(拟使用MessageClient)。
现有手机端MyCapabilityListener代码如下,手表端仅实现了WearableListenerService并重写数据接收方法,但onCapabilityChanged回调从未触发,手动调用capabilityClient.getCapability始终返回“Not connected”日志,且已在onCreate中调用MyCapabilityListener(context).addListener。
class MyCapabilityListener(private val context: Context) : DataClient.OnDataChangedListener, MessageClient.OnMessageReceivedListener, CapabilityClient.OnCapabilityChangedListener { private val capabilityClient: CapabilityClient = Wearable.getCapabilityClient(context) private val dataClient: DataClient = Wearable.getDataClient(context) fun sendData(data: String) { val dataItem = PutDataMapRequest.create("/data/path").run { dataMap.putString("data", data) asPutDataRequest() } dataClient.putDataItem(dataItem) } override fun onCapabilityChanged(capabilityInfo: CapabilityInfo) { val nodes = capabilityInfo.nodes if (nodes.isNotEmpty()) { Log.v("Connected", "Connected to the watch") } else { Log.v("Not connected", "Not connected to the watch") } } fun addListener() { Wearable.getCapabilityClient(context) Wearable.getDataClient(context) capabilityClient.addListener(this, Uri.parse("wear://"), CapabilityClient.FILTER_REACHABLE) capabilityClient.getCapability("wear://", CapabilityClient.FILTER_REACHABLE) .addOnSuccessListener { capabilityInfo -> onCapabilityChanged(capabilityInfo) } .addOnFailureListener { e -> Log.e("Capability", "Failed to get capability: ${e.message}") } } }
核心问题分析
代码中误用了Capability的引用方式:传递的wear://不是有效的Capability名称,Capability需要在两端配置文件中明确定义,才能被CapabilityClient识别。此外,Listener的生命周期管理不当也会导致回调失效。
修复步骤
1. 定义共享Capability
在手机端和手表端的res/values/wear.xml中添加Capability定义(若文件不存在则创建):
<resources> <string-array name="android_wear_capabilities"> <item>data_transfer_capability</item> </string-array> </resources>
2. 修正CapabilityClient调用逻辑
修改MyCapabilityListener中的addListener方法,使用正确的Capability名称:
fun addListener() { // 移除无效的重复获取客户端代码 capabilityClient.addListener( this, Uri.parse("wear://*/data_transfer_capability"), CapabilityClient.FILTER_REACHABLE ) capabilityClient.getCapability("data_transfer_capability", CapabilityClient.FILTER_REACHABLE) .addOnSuccessListener { capabilityInfo -> onCapabilityChanged(capabilityInfo) } .addOnFailureListener { e -> Log.e("Capability", "Failed to get capability: ${e.message}") } }
3. 管理Listener生命周期
避免临时实例导致Listener被回收,在Activity或ViewModel中保留实例引用,并在合适时机移除Listener:
// 在Activity中 private lateinit var capabilityListener: MyCapabilityListener override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) capabilityListener = MyCapabilityListener(this) capabilityListener.addListener() } override fun onDestroy() { super.onDestroy() capabilityListener.capabilityClient.removeListener(capabilityListener) }
4. 适配MessageClient发送需求(针对最终目标)
添加基于MessageClient的消息发送方法,确保获取到可到达的手表节点:
// 在MyCapabilityListener中新增方法 fun sendBluetoothData(message: String) { capabilityClient.getCapability("data_transfer_capability", CapabilityClient.FILTER_REACHABLE) .addOnSuccessListener { capabilityInfo -> capabilityInfo.nodes.firstOrNull()?.let { targetNode -> Wearable.getMessageClient(context).sendMessage( targetNode.id, "/bluetooth_data_path", message.toByteArray() ) Log.v("Message", "Data sent to watch") } ?: Log.v("Message", "No reachable watch node found") } }
5. 验证手表端Service配置
确保手表端的WearableListenerService在Manifest中正确注册:
<service android:name=".MyWearableListenerService" android:exported="true"> <intent-filter> <action android:name="com.google.android.gms.wearable.DATA_CHANGED" /> <action android:name="com.google.android.gms.wearable.MESSAGE_RECEIVED" /> <data android:scheme="wear" android:host="*" /> </intent-filter> </service>
内容的提问来源于stack exchange,提问作者Swifty

