Android自定义锁屏Activity:如何让来电Activity前置显示?
嘿,这个问题我之前做自定义锁屏的时候也踩过坑,咱们来一步步解决它~
解决方案:让来电界面正常显示并在解锁后前置
一、先解决来电时锁屏遮挡的问题
1. 调整WindowManager.LayoutParams的Type
你现在用的TYPE_SYSTEM_ERROR是系统层级极高的窗口类型,会覆盖包括来电界面在内的几乎所有系统界面,所以得换成更适配锁屏场景的类型:
- 对于Android 7.1+(API 25)及以上,推荐用
TYPE_KEYGUARD_DIALOG——这是系统专门给锁屏对话框预留的类型,优先级低于来电等系统紧急界面; - 更低版本可以用
TYPE_PHONE,记得提前申请对应权限。
修改后的参数示例:
private static final WindowManager.LayoutParams LAYOUT_PARAMS = new WindowManager.LayoutParams( WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT, // 适配不同Android版本的窗口类型 Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1 ? WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG : WindowManager.LayoutParams.TYPE_PHONE, WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION, PixelFormat.TRANSLUCENT );
2. 监听来电事件主动隐藏锁屏
如果调整窗口类型后还是遇到兼容性问题(比如某些定制ROM的特殊限制),可以主动监听来电状态,在来电时临时隐藏锁屏界面,通话结束后再恢复:
// 在锁屏Activity的onCreate方法中注册来电监听 TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { // Android 12+ 使用TelephonyCallback telephonyManager.registerTelephonyCallback(getMainExecutor(), new TelephonyCallback() { @Override public void onCallStateChanged(int state) { super.onCallStateChanged(state); handleCallStateChange(state); } }); } else { // 旧版本使用PhoneStateListener telephonyManager.listen(new PhoneStateListener() { @Override public void onCallStateChanged(int state, String phoneNumber) { super.onCallStateChanged(state, phoneNumber); handleCallStateChange(state); } }, PhoneStateListener.LISTEN_CALL_STATE); } // 统一处理来电状态变化的方法 private void handleCallStateChange(int state) { if (state == TelephonyManager.CALL_STATE_RINGING) { // 来电时隐藏锁屏窗口 getWindow().setVisibility(View.GONE); } else if (state == TelephonyManager.CALL_STATE_IDLE) { // 通话结束/无来电时恢复锁屏显示 getWindow().setVisibility(View.VISIBLE); } }
二、解锁后让来电界面前置显示
当PIN码验证成功后,先检查当前是否有未处理的来电,如果有,主动唤起来电界面:
// 假设这是你验证PIN码正确后的处理逻辑 private void onPinCodeVerified() { TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); if (telephonyManager.getCallState() == TelephonyManager.CALL_STATE_RINGING) { // 尝试唤起来电界面 try { // 优先用系统的ACTION_ANSWER意图 Intent answerIntent = new Intent(Intent.ACTION_ANSWER); answerIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(answerIntent); } catch (ActivityNotFoundException e) { // 如果ACTION_ANSWER失效,尝试直接启动系统来电应用(不同厂商包名可能不同) PackageManager pm = getPackageManager(); // 常见的来电应用包名集合 String[] callPackageNames = {"com.android.incallui", "com.android.phone"}; for (String pkgName : callPackageNames) { Intent callIntent = pm.getLaunchIntentForPackage(pkgName); if (callIntent != null) { callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(callIntent); break; } } } } // 最后关闭锁屏Activity finish(); }
补充注意事项
- 别忘了申请权限:
android.permission.READ_PHONE_STATE,Android 6+还需要动态申请该权限; - 部分定制ROM(如小米、华为)对系统窗口和来电应用有特殊限制,需要针对性测试适配;
- 如果你的锁屏是通过WindowManager添加View实现的(而非Activity),逻辑类似——调整WindowType并监听来电隐藏View即可。
内容的提问来源于stack exchange,提问作者user565
相关产品推荐
相关产品推荐

