You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:17:41