Android中使用Window Manager实现新Overlay显示时自动隐藏旧Overlay
解决Android来电Overlay重复叠加问题
你的问题核心是每次来电时可能创建了多个WindowManagerForNumber实例,每个实例都会独立添加Overlay窗口,导致多次叠加。以下是具体修复方案:
1. 将WindowManagerForNumber改为单例类
确保整个应用中只有一个Overlay管理实例,从根源避免重复创建窗口:
class WindowManagerForNumber private constructor(private val context: Context) { // 单例实现 companion object { @Volatile private var INSTANCE: WindowManagerForNumber? = null fun getInstance(context: Context): WindowManagerForNumber { return INSTANCE ?: synchronized(this) { INSTANCE ?: WindowManagerForNumber(context.applicationContext).also { INSTANCE = it } } } } // 原类的其他代码保持不变... }
2. 修改open方法,先关旧窗再开新窗
在添加新窗口前强制移除已存在的窗口,确保每次只显示一个:
fun open() { try { // 先关闭已存在的窗口 close() // 再添加新窗口 if (mView?.parent == null) { mWindowManager?.addView(mView, mParams) bool = true setDialogWindowStatus(true) } } catch (e: Exception) { e.printStackTrace() } }
3. 优化close方法的安全判断
避免因空指针或窗口已被移除导致的异常,确保窗口能被正确清理:
fun close() { if (bool && mView != null && mWindowManager != null) { try { mWindowManager?.removeView(mView) } catch (e: Exception) { e.printStackTrace() } mView?.invalidate() bool = false setDialogWindowStatus(false) dialogCallerSearchBinding?.apply { tvCallingName.text = null tvCountryName.text = null tvCallingNumber.text = null } } }
4. 调整来电触发逻辑
确保每次来电时获取单例实例,而不是创建新对象:
// 来电时调用示例 val overlayManager = WindowManagerForNumber.getInstance(context) overlayManager.setData(name, number, appRepository) { overlayManager.open() }
额外注意事项
- 确保已申请
SYSTEM_ALERT_WINDOW权限(Android 6.0+需用户手动授权) - 来电结束或通话挂断时,记得调用
close()方法清理窗口 - 若使用广播接收器监听来电,确保接收器是单例或避免重复注册
内容的提问来源于stack exchange,提问作者Assad khan
相关产品推荐
相关产品推荐

