三星Watch4 WearOS中WearableActivityController.onDestroy抛SecurityException原因
问题分析与解决方案
问题场景
在继承WearableActivity的WearOS主Activity中,重写onDestroy()并调用父类方法时触发崩溃,该问题仅出现在Android 11的三星Watch4设备上,其他手表无此异常。
触发崩溃的代码片段:
class MainActivity() : WearableActivity(), CapabilityClient.OnCapabilityChangedListener { // ... override fun onDestroy() { super.onDestroy() // <--- 此处报错! if (mApp?.receiver != null) { Util.d(TAG, "UNREG " + mApp?.receiver) androidx.localbroadcastmanager.content.LocalBroadcastManager.getInstance(this).unregisterReceiver(mApp!!.receiver!!) mApp!!.receiver = null } } }
完整崩溃堆栈:
java.lang.RuntimeException: at android.app.ActivityThread.performDestroyActivity (ActivityThread.java:5147) at android.app.ActivityThread.handleDestroyActivity (ActivityThread.java:5176) at android.app.servertransaction.DestroyActivityItem.execute (DestroyActivityItem.java:44) at android.app.servertransaction.TransactionExecutor.executeLifecycleState (TransactionExecutor.java:176) at android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:97) at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2073) at android.os.Handler.dispatchMessage (Handler.java:106) at android.os.Looper.loop (Looper.java:246) at android.app.ActivityThread.main (ActivityThread.java:7690) at java.lang.reflect.Method.invoke (Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:593) at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:995) Caused by: java.lang.SecurityException: at android.os.Parcel.createExceptionOrNull (Parcel.java:2400) at android.os.Parcel.createException (Parcel.java:2384) at android.os.Parcel.readException (Parcel.java:2367) at android.os.Parcel.readException (Parcel.java:2309) at com.google.android.wearable.ambient.activity.IAmbientActivityService$Stub$Proxy.detach (IAmbientActivityService.java:366) at com.google.android.wearable.compat.WearableActivityController$AmbientServiceConnection.detach (WearableActivityController.java:886) at com.google.android.wearable.compat.WearableActivityController.detach (WearableActivityController.java:667) at com.google.android.wearable.compat.WearableActivityController.update (WearableActivityController.java:268) at com.google.android.wearable.compat.WearableActivityController.onDestroy (WearableActivityController.java:202) at c.b.e (WearableActivityDelegate.java:2) at c.a.onDestroy (WearableActivity.java:1) at android.app.Activity.performDestroy (Activity.java:8278) at android.app.Instrumentation.callActivityOnDestroy (Instrumentation.java:1344) at android.app.ActivityThread.performDestroyActivity (ActivityThread.java:5132) Caused by: android.os.RemoteException: at com.android.server.am.ActivityManagerService.enforceCallingPermission (ActivityManagerService.java:6521) at com.android.server.am.ActivityManagerService$LocalService.enforceCallingPermission (ActivityManagerService.java:19800) at com.android.server.wm.ActivityTaskManagerService.enforceCallerIsRecentsOrHasPermission (ActivityTaskManagerService.java:3841) at com.android.server.wm.ActivityTaskManagerService.getFocusedStackInfo (ActivityTaskManagerService.java:2293) at com.android.server.am.ActivityManagerService.getFocusedStackInfo (ActivityManagerService.java:17678)
问题根源
这是三星Watch4(Android 11)独有的系统兼容性bug:WearableActivity的父类实现中,调用IAmbientActivityService.detach()时,系统层面的权限检查逻辑出现异常,最终抛出SecurityException。
解决方案
方案1:捕获异常快速修复
由于问题仅特定设备出现,且super.onDestroy()的核心销毁逻辑已基本执行,可直接捕获异常避免崩溃:
override fun onDestroy() { try { super.onDestroy() } catch (e: SecurityException) { // 仅三星Watch4 Android11触发的兼容问题,忽略该异常 Util.d(TAG, "Ignoring SecurityException in super.onDestroy()", e) } // 原有清理逻辑 if (mApp?.receiver != null) { Util.d(TAG, "UNREG " + mApp?.receiver) androidx.localbroadcastmanager.content.LocalBroadcastManager.getInstance(this).unregisterReceiver(mApp!!.receiver!!) mApp!!.receiver = null } }
方案2:迁移至现代WearOS组件(长期最优解)
WearableActivity属于旧版兼容API,建议迁移至WearOS Jetpack的现代组件,彻底规避旧API的兼容问题:
- 使用
AppCompatActivity配合AmbientModeSupport实现息屏模式 - 或直接使用
WearableAppCompatActivity(需依赖最新Wear库)
示例迁移代码(基于AmbientModeSupport):
class MainActivity : AppCompatActivity(), AmbientModeSupport.AmbientCallbackProvider { private lateinit var ambientController: AmbientModeSupport.AmbientController override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) ambientController = AmbientModeSupport.attach(this) // ...其他初始化逻辑 } override fun getAmbientCallback(): AmbientModeSupport.AmbientCallback { return object : AmbientModeSupport.AmbientCallback() { // 按需实现息屏模式回调:onEnterAmbient、onExitAmbient等 } } override fun onDestroy() { // 无需处理旧版WearableActivity的销毁逻辑,直接执行自身清理 if (mApp?.receiver != null) { Util.d(TAG, "UNREG " + mApp?.receiver) androidx.localbroadcastmanager.content.LocalBroadcastManager.getInstance(this).unregisterReceiver(mApp!!.receiver!!) mApp!!.receiver = null } super.onDestroy() } }
方案3:状态检查临时规避
若无法立即迁移,可在调用父类方法前检查Activity状态,避免重复销毁触发异常:
override fun onDestroy() { if (!isDestroyed) { try { super.onDestroy() } catch (e: SecurityException) { // 捕获兼容异常 } } // 原有清理逻辑 if (mApp?.receiver != null) { Util.d(TAG, "UNREG " + mApp?.receiver) androidx.localbroadcastmanager.content.LocalBroadcastManager.getInstance(this).unregisterReceiver(mApp!!.receiver!!) mApp!!.receiver = null } }
注意事项
- 方案1适合紧急上线修复,快速解决崩溃问题
- 方案2是长期优化方向,符合WearOS现代开发规范
- 修复后需重点验证三星Watch4 Android11设备的崩溃情况是否消除
内容的提问来源于stack exchange,提问作者Oleg Gryb
相关产品推荐
相关产品推荐

