加载onboarding布局时应用在部分Android设备上崩溃如何解决?
问题背景
开发宝可梦卡牌主题课程作业小型卡牌游戏时,为新用户设计的仅应用首次启动弹出的onboarding迷你新手引导存在兼容性崩溃问题:
- 功能正常运行环境:Honor 8X实体机、Android Studio内置模拟器,二者系统版本均为API 29(Android 10)
- 触发崩溃环境:Redmi Note 9S、三星S10e、三星S21实体机,三者系统版本均为API 30(Android 11)
- 已通过控制台捕获对应崩溃报错日志
根因定位
该崩溃和API 30的系统行为变更直接相关,高频触发原因有两类:
- 弹出引导的窗口逻辑未做版本适配:API 30收紧了悬浮窗/全屏弹窗的权限校验,同时废弃了旧版Window Type参数,如果直接沿用API 29的弹窗调用逻辑,会直接抛异常崩溃
- 引导弹出时机不对:API 30对Window Token的校验规则比API 29更严格,如果在Activity未完成渲染(比如onCreate生命周期内)就调用Dialog/弹窗的show方法,会触发BadTokenException崩溃
修复步骤
按优先级逐一排查验证:
- 先看控制台崩溃栈顶部的异常类型,精准定位问题:
- 如果是
SecurityException:属于权限适配问题。API 30及以上版本弹出应用上层引导窗时,Window类型必须使用TYPE_APPLICATION_OVERLAY,不能用旧版已废弃的Type值;同时调用show方法前必须先通过Settings.canDrawOverlays(context)校验悬浮窗权限,未获取权限时先引导用户授权,不要直接执行弹出逻辑 - 如果是
WindowManager$BadTokenException:属于弹出时机问题。把引导弹出的逻辑从Activity的onCreate/onStart回调,挪到onResume或者onWindowFocusChanged回调里触发,等Activity的Window完全挂载完成再弹引导
- 如果是
- 给引导模块加版本分支兼容逻辑,示例代码如下:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { // API 30及以上走适配后的逻辑,使用合规Window参数,提前校验权限、确认挂载时机 showOnBoardingAdaptedForR() } else { // 低版本走原有可正常运行的逻辑 showOriginalOnBoarding() }
- 快速验证方法:把项目的targetSdkVersion临时降到29,在API 30设备上运行如果不再崩溃,就可以完全确认是API 30行为变更导致的适配问题,对照官方API 30行为变更文档排查引导模块调用的所有接口即可。
内容的提问来源于stack exchange,提问作者Dessmondd
相关产品推荐
相关产品推荐

