当我的应用程序进入后台时,如何防止Android截屏?


146

我当前正在构建的应用程序要求该应用程序必须防止操作系统出于安全原因将其推入后台时截取该应用程序的屏幕截图。这样,当在应用程序之间切换时,它将无法看到上一个活动屏幕。

我打算将此功能放在应用程序类的onPause方法中,但首先我需要了解如何实现此功能。

那么,有没有人知道如何解决此问题?

Answers:


264

尝试FLAG_SECURE

public class FlagSecureTestActivity extends Activity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,
                         WindowManager.LayoutParams.FLAG_SECURE);

    setContentView(R.layout.main);
  }
}

这绝对可以防止来自ICS最近任务历史记录的手动屏幕截图和自动屏幕截图。它还可以防止屏幕录制(例如,使用媒体投影API的应用程序)。

更新:它还可以防止Now Tap或Android 6.0上的其他助手的攻击;如果用户调出助手,他们将无法访问UI中的小部件和容器的详细信息。

更新#2:但是,并非活动中的所有内容都会受到保护。任何弹出窗口- ,DialogSpinnerAutoCompleteTextView行动起来吧溢出等-将是不安全的。您可以Dialog通过调用getWindow()并设置来解决问题FLAG_SECURE。其余...变得棘手。有关更多信息,请参见此博客文章


6
@ Dany's:实际上,它与问题有关。我刚刚在Nexus S(4.0.3)上进行了测试,它可以按预期工作-最新任务的屏幕截图被隐藏。您仍然可以看到应用程序名称和图标,但屏幕截图为黑色。欢迎您在ICS硬件上进行尝试。
CommonsWare 2012年

2
@ StingRay5:FLAG_SECURE从一开始就存在-直到最近才具有有限的含义。
CommonsWare 2012年

1
有趣的是,活动生命周期中有一个名为onCreateThumbnail的方法,但从未使用过。
Snicolas 2012年

2
@PankajKumar:如果您编写的“获取屏幕快照的代码”是经典的“将帧缓冲区作为根”,那么FLAG_SECURE就别无所求,因为那太底层了。同样,如果您采用自己的窗口小部件层次结构并将其绘制为Bitmap-backed Canvas,则FLAG_SECURE可能无法防御这一情况,因为您正在获取自己的窗口小部件的屏幕快照,因此大概在其中需要 “安全”的屏幕快照。FLAG_SECURE用于系统屏幕截图,例如最近任务的缩略图。
CommonsWare 2013年

2
美妙而简单的答案!我想知道为什么Snapchat之类的应用程序不使用它来阻止某人对发送的图像进行截图。
Shobhit Puri

78

在某些设备(在Samsung Galaxy ACE上验证,例如GT-S5830)上使用WindowManager.LayoutParams.FLAG_SECURE时要小心,这会使视图混乱。看起来像是三星特定的错误。我建议以下内容:

if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
}

这是一个混乱的屏幕看起来像:

屏幕图像混乱

不过,这在ICS Samsung手机上可以正常工作,因此我假设问题仅存在于Gingerbread设备(或更旧的设备)上。


8
完全正确,我们遇到了这个问题,因此肯定需要检查API级别。实际上忘记了发布,因此感谢您再次提出。:)
StingRay12年5

它也发生在Samsung Gio(姜饼)上,但在Froyo上还可以-因此仅发生在2.3
像素(

我们也注意到了这个问题。您可以在姜饼设备上的仿真器中进行验证。
twaddington

我也可以确认此问题出现在Samsung Gingerbread设备上。
Ernir Erlingsson

7
即使在较新的Android版本FLAG_SECURE可能会出现问题:在Android 4.3 FLAG_SECURE导致屏幕旋转动画动画的问题,请参见code.google.com/p/android/issues/detail?id=58632 -这已经被固定在Android 4.4系统
奥利弗

13

CommonsWare提供的解决方案在Lollipop中仍然有效。

只是注意,如果你想继续发现近期列表快照为整个应用程序,所有的执行活动应在指定onCreate()方法的标志getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);setContentView();

否则,如果用户浏览最近的列表中的快照,则该快照将显示不带该标志的第一个活动。


1
在我的应用中,我具有根据用户偏好设置/清除FLAG_SECURE的功能。在任务切换器中看到KITKAT和黑屏之前,它一直工作良好。在Lollipop中,概述显示我的应用程序的最后一个快照,即未设置(清除)FLAG_SECURE的时间。
r.bhardwaj 2015年

@ r.bhardwaj我认为在这种情况下我们不能做很多事情,但是您可以建议用户,更改需要重新启动App才能完全生效;-),您就完成了。
Davideas

1
任何人都可以找到一种在拍摄快照之前膨胀自定义视图的方法,因此它不仅仅是黑屏吗?我曾尝试在onPause中扩大窗口管理器上的视图,但到那时似乎为时已晚。
user1064249 '17

嗨@ user1064249您找到任何解决方案了吗?我想在操作系统截屏之前为Launcher View充气
-Alexiscanny

1

这是一种通过将应用程序置于后台时用启动屏幕覆盖应用程序内容来隐藏应用程序内容的解决方案。这不是使用FLAG_SECURE技术,我只是重写屏幕的onPause和onResume方法并修改视图以显示一个覆盖了背面的所有内容。

https://stackoverflow.com/a/52976001/6686912


0
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,
            WindowManager.LayoutParams.FLAG_SECURE);

这对我有用,它可以防止从屏幕上截取屏幕快照以及任何内置或第三方记录应用程序。


0

将这些行添加到每个活动的setContentView之前的onCreate之后,这对我来说就是工作。

getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,     
WindowManager.LayoutParams.FLAG_SECURE);
setContentView(R.layout.activity_notification);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.