手机锁屏状态下从后台服务启动App出现屏幕冻结无响应问题
问题根因
该异常由Android系统窗口权限限制、Activity生命周期触发异常共同导致:
- Android 10及以上版本对后台启动Activity做了权限限制,未申请对应权限时,锁屏状态下启动的Activity会被系统挂起,解锁后未正确恢复生命周期导致窗口无法获得焦点,出现灰色遮罩、无响应问题
- 锁屏状态下系统持有WindowManager锁,Activity未配置锁屏展示相关参数时,解锁后系统不会主动释放窗口遮挡状态
- 启动Activity的Intent Flag配置错误,导致Activity未正确加载到新任务栈,被原有后台任务状态卡住
解决方案
1. 添加并动态申请必要权限
在AndroidManifest.xml中添加如下权限:
<!-- 悬浮窗权限(Android 10+ 后台启动Activity必需) --> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <!-- 唤醒屏幕、锁屏展示权限 --> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
应用启动时动态申请悬浮窗权限:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(context)) { Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + context.getPackageName())); startActivity(intent); }
2. 配置目标Activity的窗口参数
在要启动的目标Activity的onCreate方法中添加如下配置,允许页面在锁屏状态下正常展示,解锁后自动获得焦点:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 配置锁屏展示、亮屏参数 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { setShowWhenLocked(true); setTurnScreenOn(true); } else { getWindow().addFlags( WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON ); } // 清除窗口遮挡、无焦点标记 getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE); getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN); setContentView(R.layout.your_target_layout); // 原有业务逻辑 }
3. 修正Service中启动Activity的Intent配置
在NewTaskService中启动Activity时添加必要的Flag,确保Activity正确加载:
Intent targetIntent = new Intent(this, YourTargetActivity.class); targetIntent.addFlags( Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP ); startActivity(targetIntent);
4. 补充异常兼容
如果修复后仍偶现灰色遮罩,可在目标Activity的onResume方法中主动刷新窗口状态:
@Override protected void onResume() { super.onResume(); getWindow().getDecorView().requestFocus(); getWindow().getDecorView().invalidate(); }
内容的提问来源于stack exchange,提问作者Faizan Ahmad
相关产品推荐
相关产品推荐

