如何让WearableListenerService在Android 13(API 33)中正常工作?
适配API 33的WearOS消息接收解决方案
针对WearableListenerService在API 33中失效的问题,以下是两种可行的修复方案:
方案一:将WearableListenerService转为前台服务
API 33强化了后台服务启动限制,WearableListenerService作为后台服务会被系统限制运行,转为前台服务可保证其存活并正常接收消息。
1. 修改WearService代码
import android.app.Notification import android.app.NotificationChannel import android.app.NotificationManager import android.app.PendingIntent import android.content.Intent import android.os.Build import androidx.core.app.NotificationCompat import com.google.android.gms.wearable.MessageEvent import com.google.android.gms.wearable.WearableListenerService class WearService : WearableListenerService() { private val TAG = "GAC-WEARS" private val NOTIFICATION_ID = 1001 private val CHANNEL_ID = "WearServiceChannel" override fun onCreate() { super.onCreate() createNotificationChannel() // 启动前台服务,满足API33后台服务运行要求 startForeground(NOTIFICATION_ID, buildForegroundNotification()) App.d(TAG, "ON CREATE") } private fun createNotificationChannel() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel( CHANNEL_ID, "Wear消息服务", NotificationManager.IMPORTANCE_LOW ).apply { description = "处理WearOS设备发来的消息" } val notificationManager = getSystemService(NotificationManager::class.java) notificationManager.createNotificationChannel(channel) } } private fun buildForegroundNotification(): Notification { // 点击通知打开APP主界面 val launchIntent = packageManager.getLaunchIntentForPackage(packageName) val pendingIntent = PendingIntent.getActivity( this, 0, launchIntent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT ) return NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle("Wear连接中") .setContentText("正在监听WearOS消息") .setSmallIcon(R.drawable.wear) .setContentIntent(pendingIntent) .setPriority(NotificationCompat.PRIORITY_LOW) .build() } override fun onMessageReceived(messageEvent: MessageEvent) { App.d(TAG, "RCV ${String(messageEvent.data)}") val root = App.app?.myAct val model = root?.model if (App.NO_WEAR) { return } if (messageEvent.path == RootActivity.BROADCAST_PATH) { val message = String(messageEvent.data) if (model?.connected?.value != null && model?.connected?.value != R.drawable.wear) { if (message.startsWith("start")) { (application as App).showToast("无法连接Wear:已连接其他手表", App.MTYPE.ERROR) } return } App.d(TAG, message) root?.handler?.post { root.onNotify(RootActivity.NOTIFICATIONS.Ping, R.drawable.wear) } if (message.startsWith("start")) { root?.handler?.post { root.onNotify(RootActivity.NOTIFICATIONS.Ping, R.drawable.wear) } } else { val messageIntent = Intent().apply { action = Intent.ACTION_SEND putExtra("message", message) putExtra("device", App.DEV_WEAR) } LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent) } } else { super.onMessageReceived(messageEvent) } } override fun onDestroy() { super.onDestroy() stopForeground(STOP_FOREGROUND_REMOVE) } }
2. 更新Manifest配置
添加前台服务权限,并修改服务声明:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="com.google.android.wearable.permission.RECEIVE_WEARABLE_MESSAGES" /> <service android:name=".WearService" android:permission="com.google.android.wearable.permission.BIND_LISTENER_SERVICE" android:foregroundServiceType="dataSync"> <intent-filter> <action android:name="com.google.android.gms.wearable.MESSAGE_RECEIVED" /> <data android:host="*" android:pathPrefix="/${RootActivity.BROADCAST_PATH}" android:scheme="wear" /> </intent-filter> </service>
方案二:改用WearableMessageClient监听消息
放弃WearableListenerService,直接在Activity中通过WearableMessageClient注册监听,避开后台服务限制,兼容性更好。
代码示例(在RootActivity中实现)
import com.google.android.gms.wearable.Wearable import com.google.android.gms.wearable.MessageEvent import com.google.android.gms.wearable.WearableListener class RootActivity : AppCompatActivity() { private lateinit var messageClient: com.google.android.gms.wearable.WearableMessageClient private var messageListener: WearableListener? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 初始化Wear消息客户端 messageClient = Wearable.getMessageClient(this) } override fun onResume() { super.onResume() // 注册消息监听 messageListener = object : WearableListener() { override fun onMessageReceived(messageEvent: MessageEvent) { handleWearMessage(messageEvent) } } messageClient.addListener(messageListener!!) } override fun onPause() { super.onPause() // 移除监听,避免内存泄漏 messageClient.removeListener(messageListener!!) } private fun handleWearMessage(messageEvent: MessageEvent) { App.d("GAC-WEARS", "RCV ${String(messageEvent.data)}") val model = this.model if (App.NO_WEAR) { return } if (messageEvent.path == BROADCAST_PATH) { val message = String(messageEvent.data) if (model?.connected?.value != null && model?.connected?.value != R.drawable.wear) { if (message.startsWith("start")) { (application as App).showToast("无法连接Wear:已连接其他手表", App.MTYPE.ERROR) } return } App.d("GAC-WEARS", message) handler.post { onNotify(NOTIFICATIONS.Ping, R.drawable.wear) } if (message.startsWith("start")) { handler.post { onNotify(NOTIFICATIONS.Ping, R.drawable.wear) } } else { val messageIntent = Intent().apply { action = Intent.ACTION_SEND putExtra("message", message) putExtra("device", App.DEV_WEAR) } LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent) } } } // 原有Activity代码... }
注意事项
- 确保依赖的Google Play Services Wear版本为
18.1.0及以上,在build.gradle中更新:implementation 'com.google.android.gms:play-services-wearable:18.1.0' - 前台服务的通知设置为低优先级,避免打扰用户;若不需要显示通知,可优先考虑方案二。
内容的提问来源于stack exchange,提问作者Oleg Gryb
相关产品推荐
相关产品推荐

