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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 23:19:52