Android全局禁用截图与录屏的正确实现方法咨询
Android全局禁用截图与录屏的正确实现方法咨询
嗨,我来帮你梳理下这个问题~
首先你提到的第一种方法:
getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);
确实只能作用于当前的Activity或者App,没办法覆盖全局,这是因为FLAG_SECURE本质上是给单个Window设置的标记,只对所属的Window生效。
然后你贴的那段用TYPE_SYSTEM_OVERLAY的代码,出现错误大概率是因为权限和系统版本的问题:
- 首先,
TYPE_SYSTEM_OVERLAY在Android 8.0(API 26)之后已经被废弃了,取而代之的是TYPE_APPLICATION_OVERLAY,如果还用旧的类型,在高版本系统上会直接抛出异常。 - 其次,悬浮窗权限是必须的,你需要在Manifest里声明权限,而且在Android 6.0+(API 23)之后,还需要引导用户手动开启这个权限(跳转到应用设置页面让用户授权)。
- 另外,那段代码里的View只是一个空的LinearLayout加View,还存在逻辑漏洞,比如没有正确处理WindowManager的生命周期,容易导致内存泄漏。
那全局禁用截图录屏的正确思路是什么呢?其实核心还是利用FLAG_SECURE,但要给覆盖整个屏幕的全局悬浮Window设置这个标记,这样整个屏幕都会受到保护。
下面是修正后的可行代码示例:
1. 声明权限
在AndroidManifest.xml里添加权限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
2. 动态申请悬浮窗权限(针对API 23+)
在启动全局悬浮窗之前,先检查并申请权限:
private boolean checkOverlayPermission(Context context) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (!Settings.canDrawOverlays(context)) { Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + context.getPackageName())); context.startActivity(intent); return false; } } return true; }
3. 创建全局覆盖Window并设置FLAG_SECURE
private void createSecureOverlay(Context context) { WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); // 创建一个铺满屏幕的透明View View secureView = new View(context); secureView.setBackgroundColor(Color.TRANSPARENT); WindowManager.LayoutParams params; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { params = new WindowManager.LayoutParams( WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, WindowManager.LayoutParams.FLAG_SECURE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSPARENT ); } else { params = new WindowManager.LayoutParams( WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, WindowManager.LayoutParams.FLAG_SECURE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSPARENT ); } // 设置布局在屏幕最底层,不影响其他操作 params.gravity = Gravity.TOP | Gravity.LEFT; try { wm.addView(secureView, params); } catch (Exception e) { e.printStackTrace(); // 这里可以处理添加失败的情况,比如权限未授予 } }
额外注意事项
- 这个透明的悬浮窗会覆盖整个屏幕,但我们设置了
FLAG_NOT_TOUCHABLE和FLAG_NOT_FOCUSABLE,所以不会影响用户正常操作其他App。 - 当你的App退出时,记得调用
wm.removeView(secureView)来移除这个悬浮窗,避免内存泄漏。 - 部分定制化ROM可能会限制这种全局悬浮窗的功能,需要做兼容性测试。
备注:内容来源于stack exchange,提问作者ANDuser
相关产品推荐
相关产品推荐

