WearOS与手机应用通信异常:手机端onMessageReceived未触发
WearOS与手机应用通信问题:手机端
onMessageReceived未触发 期望功能
点击WearOS应用上的按钮时,向手机应用发送消息数据;手机应用收到消息后,在Logcat中显示数据。
问题详情
使用Kotlin开发WearOS与手机应用的MessageClient通信功能,WearOS端可正常发送消息,但手机端的onMessageReceived始终未触发,设备已配对。
WearOS端代码
class MainActivity : ComponentActivity(), DataClient.OnDataChangedListener, MessageClient.OnMessageReceivedListener{ private var activityContext: Context? = null private var dataClient: DataClient? = null private var messageClient: MessageClient? = null companion object { const val MESSAGE_PATH_SEND = "/send_message" const val MESSAGE_PATH_RECEIVE = "/receive_message" } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { WearApp("Android") } activityContext = this dataClient = Wearable.getDataClient(this) messageClient = Wearable.getMessageClient(this) } @Composable fun WearApp(greetingName: String) { WearOSCommunicationTheme { Column( modifier = Modifier .fillMaxSize() .background(MaterialTheme.colors.background), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { Text(text = "Example text") Button( modifier = Modifier .padding(10.dp) .fillMaxWidth(), onClick = { sendMessageToPhone("this is an example message") }) { Text(text = "Send Msg") } } } } private fun sendMessageToPhone(message: String) { Wearable.getNodeClient(activityContext!!).connectedNodes.addOnSuccessListener { nodes -> for (node in nodes) { if (node.isNearby) { // Check if the node is reachable Wearable.getMessageClient(activityContext!!).sendMessage(node.id, MESSAGE_PATH_SEND, message.toByteArray(Charsets.UTF_8)) .addOnSuccessListener { Log.d("WearOSLog", "Message sent successfully to ${node.id}") } .addOnFailureListener { exception -> Log.e("WearOSLog", "Failed to send message to ${node.id}", exception) } } else { Log.d("WearOSLog", "Node ${node.id} is not reachable") } } }.addOnFailureListener { exception -> Log.e("WearOSLog", "Failed to get connected nodes", exception) } } override fun onDataChanged(dataEvents: DataEventBuffer) { for (event in dataEvents) { if (event.type == DataEvent.TYPE_CHANGED){ // Handle data change } } } override fun onMessageReceived(messageEvent: MessageEvent) { TODO("Not yet implemented") } override fun onResume() { super.onResume() try { Wearable.getDataClient(activityContext!!).addListener(this) Wearable.getMessageClient(activityContext!!).addListener(this) } catch (e: Exception) { e.printStackTrace() } } override fun onPause() { super.onPause() Wearable.getDataClient(activityContext!!).removeListener(this) Wearable.getMessageClient(activityContext!!).removeListener(this) } }
手机端代码
class MainActivity : AppCompatActivity(), MessageClient.OnMessageReceivedListener, DataClient.OnDataChangedListener{ companion object { const val MESSAGE_PATH_SEND = "/send_message" const val MESSAGE_PATH_RECEIVE = "/receive_message" } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } override fun onMessageReceived(messageEvent: MessageEvent) { try { if (messageEvent.path == MESSAGE_PATH_SEND) { val message = String(messageEvent.data, Charsets.UTF_8) Log.d("PhoneSide", "Message received: $message"); } } catch (e: Exception) { e.printStackTrace() Log.d("PhoneSide", "error") } } override fun onResume() { super.onResume() try { Wearable.getDataClient(this).addListener(this) Wearable.getMessageClient(this).addListener(this) } catch (e: Exception) { e.printStackTrace() } } override fun onPause() { super.onPause() try { Wearable.getDataClient(this).removeListener(this) Wearable.getMessageClient(this).removeListener(this) } catch (e: Exception) { e.printStackTrace() } } override fun onDataChanged(p0: DataEventBuffer) { TODO("Not yet implemented") } }
WearOS端清单文件
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-feature android:name="android.hardware.type.watch" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@android:style/Theme.DeviceDefault"> <uses-library android:name="com.google.android.wearable" android:required="true" /> <meta-data android:name="com.google.android.wearable.standalone" android:value="true" /> <activity android:name=".presentation.MainActivity" android:exported="true" android:label="@string/app_name" android:theme="@android:style/Theme.DeviceDefault"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
手机端清单文件
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <uses-permission android:name="android.permission.WAKE_LOCK" /> <application android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.WearOSCommunication" tools:targetApi="31"> <activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
解决方案
1. 修正手机端Manifest配置
添加Wearable库声明、通信权限及应用关联元数据:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="com.google.android.gms.permission.BIND_WEARABLE_LISTENER" /> <application android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.WearOSCommunication" tools:targetApi="31"> <uses-library android:name="com.google.android.wearable" android:required="false" /> <!-- 若两端包名不同,替换为手表应用的包名 --> <meta-data android:name="com.google.android.wearable.app" android:value="com.yourpackage.wear" /> <activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
2. 调整WearOS端独立应用设置
将standalone元数据改为false,表明应用依赖手机端:
<meta-data android:name="com.google.android.wearable.standalone" android:value="false" />
3. 使用Service监听消息(避免Activity后台回收)
创建WearMessageListenerService替代Activity监听:
class WearMessageListenerService : WearableListenerService() { companion object { const val MESSAGE_PATH_SEND = "/send_message" } override fun onMessageReceived(messageEvent: MessageEvent) { super.onMessageReceived(messageEvent) if (messageEvent.path == MESSAGE_PATH_SEND) { val message = String(messageEvent.data, Charsets.UTF_8) Log.d("PhoneSide", "Message received: $message") } } }
在手机端Manifest注册该Service:
<service android:name=".WearMessageListenerService" android:exported="true"> <intent-filter> <action android:name="com.google.android.gms.wearable.MESSAGE_RECEIVED" /> <data android:host="*" android:pathPrefix="/send_message" android:scheme="wear" /> </intent-filter> </service>
4. 确保两端包名与签名一致
- 两端应用包名需相同,或在手机端Manifest中指定手表应用包名。
- 调试和发布时使用同一签名文件,否则系统会拦截跨应用通信。
5. 移除WearOS端的isNearby判断(测试阶段)
模拟器配对或非蓝牙连接的设备可能被isNearby过滤,暂时移除该判断:
private fun sendMessageToPhone(message: String) { Wearable.getNodeClient(activityContext!!).connectedNodes.addOnSuccessListener { nodes -> for (node in nodes) { Wearable.getMessageClient(activityContext!!).sendMessage(node.id, MESSAGE_PATH_SEND, message.toByteArray(Charsets.UTF_8)) .addOnSuccessListener { Log.d("WearOSLog", "Message sent successfully to ${node.id}") } .addOnFailureListener { exception -> Log.e("WearOSLog", "Failed to send message to ${node.id}", exception) } } }.addOnFailureListener { exception -> Log.e("WearOSLog", "Failed to get connected nodes", exception) } }
内容的提问来源于stack exchange,提问作者kkrgzz
相关产品推荐
相关产品推荐

