170

The app I'm currently building has the requirement that the app has to prevent the OS to take a screenshot of the app when it's being pushed into the background for security reasons. This way it won't be able to see the last active screen when switching between apps.

I'm planning to put this functionality in the application class's onPause method, but first I need to find out how I can achieve this functionality.

So is there anybody out there, that has a clue how to fix this?

korius
  • 359
  • 2
  • 6
StingRay5
  • 2,388
  • 2
  • 20
  • 29

8 Answers8

301

Try 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);
  }
}

This definitely secures against manual screenshots and automatic screenshots from the ICS recent-tasks history. It also secures against screen recording (e.g., apps using the media projection APIs).

UPDATE: it also secures against Now On Tap or other assistants on Android 6.0; they will not get access to the details of widgets and containers in your UI if the user brings up the assistant.

UPDATE #2: however, not everything in the activity will be protected. Any pop-up windows — Dialog, Spinner, AutoCompleteTextView, action bar overflow, etc. — will be insecure. You can fix the Dialog problem by calling getWindow() on it and setting FLAG_SECURE. The rest... gets tricky. See this blog post for more.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • 6
    @Dany's: Actually, it has everything to do with the question. I just tested it on a Nexus S (4.0.3), and it works as expected -- the recent-tasks screenshot is suppressed. You still see the application name and icon, but the screenshot is black. You are welcome to try it on ICS hardware. – CommonsWare Mar 22 '12 at 13:22
  • Thanks, will take a look, any idea if this will also work with the backwards compatibility package? – StingRay5 Mar 22 '12 at 13:54
  • 2
    @StingRay5: `FLAG_SECURE` has existed since the beginning -- it just had limited meaning until recently. – CommonsWare Mar 22 '12 at 14:19
  • 1
    Interesting to note that there is a method called onCreateThumbnail ni the activity lifecycle, but it's never used. – Snicolas Aug 08 '12 at 05:11
  • @CommonsWare How can I check if `LayoutParams.FLAG_SECURE` is set or not. Actually I set `LayoutParams.FLAG_SECURE` to restrict screen-capture, and I wrote a code to take screen shot, and I am able to take screenshot. So can you please tell that how can I verify that ? – Pankaj Kumar Jun 17 '13 at 08:05
  • 2
    @PankajKumar: If the "code to take screen shot" that you wrote is that classic "grab the framebuffer as root" trick, `FLAG_SECURE` won't defend against that, as that's too low-level. Similarly, if you took your own widget hierarchy and had it draw to a `Bitmap`-backed `Canvas`, `FLAG_SECURE` probably won't defend against that, as you are taking your own screenshots of your own widgets and therefore presumably *wanted* the "secure" ones in there. `FLAG_SECURE` is for *system* screenshots, such as the recent-tasks thumbnails. – CommonsWare Jun 17 '13 at 10:24
  • Ok. I got the point. Is there any way where I can check if `FLAG_SECURE` is set or not? – Pankaj Kumar Jun 17 '13 at 10:30
  • @PankajKumar: For your own window, you should know if `FLAG_SECURE` is set or not, as you are the one setting it. If you are writing some framework and therefore do not know if a `Window` has `FLAG_SECURE` or not, in theory you should be able to find it in the `getAttributes()` result, though I have never tried this. And, if you are referring to a window from some other process, I doubt that an SDK app can find out if a window has `FLAG_SECURE` or not. – CommonsWare Jun 17 '13 at 10:35
  • 2
    Wonderful and simple answer! I'm wondering why apps like [snapchat](http://www.snapchat.com/) don't use this to prevent someone taking a screenshot of the images sent. – Shobhit Puri Aug 25 '13 at 11:16
  • @CommonsWare Hope you are doing well. I have one more issue related to secure flag. I set this flag as you given into answer, and it was working well before KitKat. In KitKat, if I press `power+volumn_down` and rotate device, able to take screen-shot. Is this bug into KitKat? Or there is another method to set secure flag? Please update me. – Pankaj Kumar Jan 22 '14 at 12:58
  • @CommonsWare Actually this issue doesn't come into 4.3. So is this a bug into KitKat? As per your given link its look like this is device specific, right? – Pankaj Kumar Jan 22 '14 at 13:17
  • @PankajKumar: I am saying that I have attempted to reproduce this issue and have been unable to do so (see comment #4 on the issue report). – CommonsWare Jan 22 '14 at 13:37
  • Any idea how I can prevent Android from taking a screenshot when it goes to the background, but allow users to take a screenshot manually? I've posted another question: http://stackoverflow.com/questions/28873633/how-do-i-prevent-android-from-taking-a-screenshot-when-app-goes-to-background-b – Wirling Mar 17 '15 at 07:58
  • @CommonsWare Can i display custom photo instead of auto screenshots in recent application list? – Dhaval Khant Apr 24 '15 at 06:57
  • @DhavalKhant: You can try `onCreateThumbnail()`, though I have not tried it personally: http://developer.android.com/reference/android/app/Activity.html#onCreateThumbnail%28android.graphics.Bitmap,%20android.graphics.Canvas%29 – CommonsWare Apr 24 '15 at 10:46
  • Just to add the package, because it took me a short while: WindowManager.LayoutParams.FLAG_SECURE – Andreas Rudolph Jun 04 '15 at 14:13
  • This doesn't work reliably on Android 5.1, see https://code.google.com/p/android/issues/detail?id=169933 – petrsyn Sep 11 '15 at 21:10
  • Yep, apparently there are some bugs, another ticket opened here: https://code.google.com/p/android-developer-preview/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars&groupby=&sort=&id=2484 – Ciprian Sep 22 '15 at 11:59
  • Is there a way to set this in Xamarin? I could not reach FLAG_SECURE parameter. – Emrah Akgül Jun 22 '16 at 11:05
  • 1
    @EmrahAkgül: I can barely spell Xamarin. :-) You are better served asking a separate Stack Overflow question, with the appropriate Xamarin tag, asking how to use it. – CommonsWare Jun 22 '16 at 11:21
  • Thank you for the "UPDATE #2", It would not occurred to me. – Quark Nov 18 '16 at 14:06
  • @EmrahAkgül or anyone else wondering for Xamarin : `Window.SetFlags(WindowManagerFlags.Secure, WindowManagerFlags.Secure);` – Gabriel Bourgault Aug 25 '17 at 14:25
  • @AjayMistry: `FLAG_SECURE` is working as expected for me on a Samsung Galaxy S8 running Android 7.0, in landscape mode. – CommonsWare Jan 06 '18 at 12:56
  • @CommonsWare :I triend it but it doesn't work...instead it works fine in portrait mode but when I change it to landscape mode it record the screen.. what i have to do to achieve this?? – Ajay Mistry Jan 09 '18 at 05:58
  • @AjayMistry: Contact the device manufacturer, as they have a bug. – CommonsWare Jan 09 '18 at 11:47
  • `getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);` doesn't work for Android Pie. – Rajeev Sahu Oct 03 '18 at 13:56
  • 1
    @user1182217: It worked fine for me this morning, in a test on a Google Pixel running Android 9.0 (Pie). Feel free to provide a link to a sample project which can reproduce your problems on Android 9.0. – CommonsWare Oct 03 '18 at 21:48
  • @CommonsWare: I tried in One Plus device having Android Pie (9.0). How ever FLAG_SECURE works fine below 9.0. – Rajeev Sahu Oct 04 '18 at 09:45
  • 1
    @user1182217: Then perhaps the problem is with that particular device model. – CommonsWare Oct 04 '18 at 10:58
  • @CommonsWare: Yes, you are right. In pixel it's working fine. Problem is with One Plus device model. Thanks. – Rajeev Sahu Oct 05 '18 at 06:55
  • you could also look into [some possible improvements over FLAG_SECURE](https://github.com/commonsguy/cwac-security/blob/master/docs/FLAGSECURE.md) – Andreas Happe Oct 24 '18 at 19:03
  • just wanted to point out that that's not a full answer. There should also be an import at the top of the MainActivitiy.java file, -> import android.view.WindowManager; and you only need to add this part getWindow().setFlags( WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE ); – verunar Nov 23 '21 at 15:04
  • @CommonsWare Also have a look at my question too. https://stackoverflow.com/q/76651691/4134215 – Taimoor Khan Jul 16 '23 at 20:07
81

Be careful about using WindowManager.LayoutParams.FLAG_SECURE, on some devices (verified on Samsung Galaxy ACE, e.g. GT-S5830) this will make the view scrambled. Looks like a Samsung specific bug. I recommend the following:

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

This is what a scrambled screen looks like:

Scrambled Screen Image

This is working properly on ICS Samsung phones though, so I'm assuming problem is isolated to Gingerbread devices (or older).

Michael Richardson
  • 4,213
  • 2
  • 31
  • 48
gardarh
  • 3,084
  • 2
  • 28
  • 31
  • 9
    You're totally right, we came across this issue, and it certainly was needed to check for the API level. Actually forgot to post this, so thanks for bringing it up again. :) – StingRay5 Jun 27 '12 at 18:54
  • It also occurs on Samsung Gio (Gingerbread) but on Froyo its ok - so it occurs only on 2.3 – pixel Oct 29 '12 at 12:13
  • We noticed this problem as well. You can verify in the Emulator on Gingerbread devices. – twaddington Dec 31 '12 at 19:40
  • I can also confirm that this problem appears on Samsung Gingerbread devices. – Ernir Erlingsson Apr 17 '13 at 07:44
  • 7
    Even on newer Android versions FLAG_SECURE can be problematic: on Android 4.3 FLAG_SECURE causes animation problems in screen rotation animation, see https://code.google.com/p/android/issues/detail?id=58632 - this has been fixed on Android 4.4 – Oliver Jun 23 '14 at 08:43
  • Hi... i need to block screenshot for particular activity. but your code suppress the screenshot for whole app. – user3546693 Nov 17 '15 at 05:23
13

The solution provided by CommonsWare continues to be valid also in Lollipop.

Just a note, if you want to continue to not see snapshots in recent list for the entire app, ALL the implemented activities should specify in the onCreate() method the flag getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE); before setContentView();

Otherwise a snapshot in the recent list will show the first activity without the flag if the user navigated through it.

Davideas
  • 3,226
  • 2
  • 33
  • 51
  • 1
    In my app, I have functionality of setting/clearing FLAG_SECURE based on a user preference. It worked fine till KITKAT and black screen can be seen in task switcher. In Lollipop, the Overview displays the last snapshot of my app, the time when FLAG_SECURE was not set(cleared). – r.bhardwaj Apr 10 '15 at 12:27
  • @r.bhardwaj i think we can't do so much in that case, but you can advice the user that, the change needs App to be restarted to take fully effect ;-) and you are done. – Davideas Oct 17 '15 at 10:02
  • 1
    Anyone found a way to inflate a custom view before snapshot is taken so it's not just a black screen? I've tried inflating a view on window manager in onPause, but it seems by then it's too late. – user1064249 Feb 02 '17 at 14:39
  • Hi @user1064249 Have you found any solution? I want inflate the Launcher View before the OS take the screenshot – Alexiscanny Jan 04 '18 at 18:11
7

In case if someone is looking for a solution in which the app must secure (screen overlay) when the app is background or stick of all running app and the in-app app should allow screenshot. Try Below:-

@Override
    protected void onResume() {
        super.onResume();
        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
    }

    @Override
    protected void onPause() {
        super.onPause();
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
    }
Community
  • 1
  • 1
Gaurav
  • 114
  • 3
  • 7
  • 1
    Exactly what I was looking for, thanks! One can also call `addFlags()` instead of `setFlags()`, which makes it even easier. – martinstoeckli Nov 29 '21 at 10:59
4

As of Android 13, there is a new way to prevent a screenshot being taken for the recent apps list, while still allowing the user to take screenshots while using the app: https://developer.android.com/reference/android/app/Activity#setRecentsScreenshotEnabled(boolean)

Lee Kang
  • 729
  • 9
  • 19
3

Here is a solution for hiding content of an app by covering it with a splash screen when the app is put into the background. This is not using the FLAG_SECURE technique, I simply override the onPause and onResume methods of the screens and modify the view to show one that covers everything in the back.

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

D. Maul
  • 341
  • 2
  • 11
2
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,
            WindowManager.LayoutParams.FLAG_SECURE);

this worked for me, it prevents from taking screenshot and also any inbuilt or third party recording application from recording screen.

Harsh Barnwal
  • 101
  • 2
  • 7
1

This is work for me after adding these line into the onCreate before setContentView of every activity.

getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,     
WindowManager.LayoutParams.FLAG_SECURE);
setContentView(R.layout.activity_notification);
Arun Prajapati
  • 283
  • 2
  • 6