Android Automotive应用启动报错提示抑制及序列化失败问题排查
问题概述
数月前运行正常的Android Automotive应用,当前无法正常启动,屏幕弹出Application Error. Please report this error to the app developer提示及Close Application按钮。该问题仅在production build的Android 12/13模拟器、Android 12车载设备中出现,debug build无复现,且过往正常版本也受影响。
模拟器启动时的崩溃栈追踪如下:
Serialization failure in getAppInfo androidx.car.app.serialization.Bundler$TracedBundlerException: Class to deserialize is missing a no args constructor: androidx.car.app.FailureResponse, frames: [FailureResponse, FailureResponse] at androidx.car.app.serialization.Bundler.serializeObject(Unknown Source:125) at androidx.car.app.serialization.Bundler.toBundle(Unknown Source:285) at androidx.car.app.serialization.Bundleable.androidx.car.app.serialization.Bundler.toBundle(SourceFile:7) at androidx.car.app.activity.renderer.surface.RemoteProxyInputConnection$$ExternalSyntheticLambda6.androidx.car.app.serialization.Bundleable.create(Unknown Source:25) androidx.car.app.utils.RemoteUtils.lambda$sendFailureResponseToHost$4 androidx.car.app.utils.RemoteUtils$$InternalSyntheticLambda$1$00787579f7b110f935892f6d3a11e0cf6af59cc35bc9b41a1e55d24116f40963$0.call$bridge at kotlinx.coroutines.DebugStringsKt.androidx.car.app.utils.RemoteUtils.dispatchCallToHostForResult(Unknown Source:36) at kotlinx.coroutines.DebugStringsKt.androidx.car.app.utils.RemoteUtils.dispatchCallToHost(Unknown Source:0) at kotlinx.coroutines.DebugStringsKt.androidx.car.app.utils.RemoteUtils.sendFailureResponseToHost(Unknown Source:12) at androidx.car.app.activity.renderer.surface.RemoteProxyInputConnection$$ExternalSyntheticLambda6.androidx.car.app.utils.RemoteUtils.lambda$sendSuccessResponseToHost$3(Unknown Source:71) androidx.car.app.utils.RemoteUtils$$InternalSyntheticLambda$1$00787579f7b110f935892f6d3a11e0cf6af59cc35bc9b41a1e55d24116f40963$0.call$bridge at kotlinx.coroutines.DebugStringsKt.androidx.car.app.utils.RemoteUtils.dispatchCallToHostForResult(Unknown Source:36) at kotlinx.coroutines.DebugStringsKt.androidx.car.app.utils.RemoteUtils.dispatchCallToHost(Unknown Source:0) at kotlinx.coroutines.DebugStringsKt.androidx.car.app.utils.RemoteUtils.sendSuccessResponseToHost(Unknown Source:12) at androidx.car.app.CarAppService$CarAppBinder.getAppInfo(Unknown Source:11) at androidx.car.app.ICarApp$Stub.onTransact(Unknown Source:58) at android.os.Binder.execTransactInternal(Binder.java:1285) at android.os.Binder.execTransact(Binder.java:1244) Caused by: java.lang.NoSuchMethodException: androidx.car.app.FailureResponse.<init> [] at java.lang.Class.getConstructor0(Class.java:2363) at java.lang.Class.getDeclaredConstructor(Class.java:2201) at androidx.car.app.serialization.Bundler.serializeObject(Unknown Source:15)
相关代码均属于Jetpack Car App库,未在应用中直接调用,且该崩溃未在Google Play或崩溃追踪工具中上报,推测Jetpack对此类崩溃有自行处理机制,但仍弹出了错误提示。
原因分析
崩溃核心是R8/ProGuard混淆在生产构建中移除了androidx.car.app.FailureResponse的无参构造方法。由于应用代码未直接调用该构造,R8默认会标记为未使用并移除,而Jetpack Car App库的Bundler序列化组件需要这个构造来完成对象反序列化,最终触发序列化失败,导致系统弹出错误提示。
解决方案
1. 添加ProGuard/R8规则保留无参构造
在项目的proguard-rules.pro文件中添加以下规则,强制保留FailureResponse的无参构造:
-keepclassmembers class androidx.car.app.FailureResponse { public <init>(); }
若使用R8完整模式,可补充更严格的保留规则,避免其他成员被误优化:
-keep class androidx.car.app.FailureResponse { *; }
2. 验证构建配置
检查app/build.gradle中的混淆配置,确保minifyEnabled和shrinkResources的设置未覆盖上述规则:
android { buildTypes { release { minifyEnabled true shrinkResources true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } }
3. 自定义错误提示拦截(备选)
如果上述规则无效,可通过自定义CarAppActivity拦截系统错误提示:
继承CarAppActivity并重写错误回调方法,屏蔽默认提示:
class CustomCarAppActivity : CarAppActivity() { override fun onError(errorMessage: String) { // 注释掉super调用以屏蔽默认错误对话框 // super.onError(errorMessage) // 可添加自定义错误处理逻辑,如日志记录 } }
同时在AndroidManifest.xml中替换默认的CarAppActivity为自定义类:
<activity android:name=".CustomCarAppActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> <category android:name="androidx.car.app.category.CAR_APP" /> </intent-filter> </activity>
验证
修改后打包production build,在Android 12/13模拟器或车载设备上测试,确认应用正常启动且错误提示不再弹出。
内容的提问来源于stack exchange,提问作者Alex Wang

