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

Android应用退至后台时显示纯色全屏的实现方案咨询

Android后台隐私全屏遮挡实现方案

主流金融应用的核心实现思路

这类应用并未依赖FLAG_SECURE,而是通过拦截系统界面快照时机,主动替换快照内容,再配合全局窗口遮挡的组合方案,实现全屏纯色覆盖,具体分原生Android和React Native场景说明:

原生Android实现

  1. 快照回调直接替换内容
    利用Activity的onCreateSnapshotView方法——这是系统生成应用快照(比如进入最近任务列表)时的专属回调,直接返回纯颜色视图替代原界面:

    override fun onCreateSnapshotView(container: ViewGroup?): View {
        // 根据当前主题模式选择对应颜色
        val color = if (isDarkMode()) Color.BLACK else Color.WHITE
        val snapshotView = View(this)
        snapshotView.setBackgroundColor(color)
        snapshotView.layoutParams = ViewGroup.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT
        )
        return snapshotView
    }
    
    private fun isDarkMode(): Boolean {
        val uiMode = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
        return uiMode == Configuration.UI_MODE_NIGHT_YES
    }
    
  2. 全局窗口兜底遮挡
    配合onPause/onResume添加全局覆盖视图,确保包括状态栏在内的全屏幕被遮挡,避免快照回调未触发的极端场景:

    private var secureOverlay: View? = null
    
    override fun onPause() {
        super.onPause()
        showSecureOverlay()
    }
    
    override fun onResume() {
        super.onResume()
        hideSecureOverlay()
    }
    
    private fun showSecureOverlay() {
        val color = if (isDarkMode()) Color.BLACK else Color.WHITE
        val params = WindowManager.LayoutParams().apply {
            type = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
            } else {
                WindowManager.LayoutParams.TYPE_PHONE
            }
            flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN or
                    WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS or
                    WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
            width = WindowManager.LayoutParams.MATCH_PARENT
            height = WindowManager.LayoutParams.MATCH_PARENT
            backgroundColor = color
        }
        secureOverlay = View(this).apply { setBackgroundColor(color) }
        getSystemService(WindowManager::class.java).addView(secureOverlay, params)
    }
    
    private fun hideSecureOverlay() {
        secureOverlay?.let {
            getSystemService(WindowManager::class.java).removeView(it)
            secureOverlay = null
        }
    }
    

    注意:Android 6.0+需要申请SYSTEM_ALERT_WINDOW权限,需引导用户在系统设置中开启。

React Native实现

RN需通过原生模块封装上述逻辑,同时处理快照替换:

  1. 原生模块封装遮挡逻辑
    编写Android原生模块,暴露showSecureOverlay和hideSecureOverlay方法给JS层,在App中监听状态变化调用:
    import { AppState, NativeModules } from 'react-native';
    const { SecureOverlayModule } = NativeModules;
    
    useEffect(() => {
      const handleAppStateChange = (nextAppState) => {
        if (nextAppState === 'background') {
          SecureOverlayModule.showSecureOverlay();
        } else if (nextAppState === 'active') {
          SecureOverlayModule.hideSecureOverlay();
        }
      };
    
      AppState.addEventListener('change', handleAppStateChange);
      return () => AppState.removeEventListener('change', handleAppStateChange);
    }, []);
    
  2. 修改MainActivity处理快照
    在RN的MainActivity中重写onCreateSnapshotView方法,返回纯色视图,逻辑与原生Android一致。

为什么之前的onPause添加视图方案失效?

系统生成最近任务快照的时机是在onPause执行完成后,部分场景下(比如快速切换应用),添加的视图还未完全渲染就被系统抓取快照,导致旧界面依然被捕获。而onCreateSnapshotView是系统专门用于生成快照的回调,直接返回的视图会被作为快照内容,能确保显示纯色。

同时部分厂商定制系统对快照时机有特殊处理,需要快照替换+全局遮挡的组合方案才能覆盖所有场景。

内容的提问来源于stack exchange,提问作者Marco Caldera

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 23:50:33