How to Customize an Android App Preview in the Background With the Secure Flag
Use Android FLAG_SECURE to hide sensitive Recent Apps previews, understand its limits, and choose when to protect only specific screens.
Short answer: Android does not provide a supported public API for replacing the Recent Apps thumbnail with your own blurred image, logo or custom bitmap. To keep sensitive content out of the Overview screen, set WindowManager.LayoutParams.FLAG_SECURE on the Activity window. When Android captures the background snapshot, the result is blank.
Android’s fraud-prevention guidance recommends this approach for banking apps, password managers and other screens containing sensitive information. The trade-off is that screenshots, recording and some screen-sharing workflows are also blocked.
1. What FLAG_SECURE changes
- Prevents screenshots of the protected window.
- Prevents the window from appearing on non-secure displays, such as many casting destinations.
- Produces a blank background snapshot when the app moves to the background and Android captures the Recent Apps preview.
- Applies at the window level, so it affects the whole Activity window while enabled.
The blank result is intentional. It is not a way to supply a branded replacement preview. Android’s public APIs do not expose a supported hook for setting a custom Recent Apps bitmap.
2. Set FLAG_SECURE for an entire Activity
Kotlin
import android.os.Bundle
import android.view.WindowManager
import androidx.appcompat.app.AppCompatActivity
class AccountActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
window.setFlags(
WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE
)
setContentView(R.layout.activity_account)
}
}
Java
import android.os.Bundle;
import android.view.WindowManager;
import androidx.appcompat.app.AppCompatActivity;
public class AccountActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(
WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE
);
setContentView(R.layout.activity_account);
}
}
You can also use addFlags when you only need to add the bit:
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
Set the flag before the sensitive UI is displayed. Placing it in onCreate is usually the clearest choice for an Activity that is always private.
3. Protect only sensitive screens or states
Global protection is simple, but it can unnecessarily disable screenshots for public screens. For a login form, payment view, password screen or private document, enable the flag when the sensitive state appears and clear it when the user leaves that state.
Kotlin dynamic helper
import android.view.WindowManager
fun enableSecureMode() {
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
}
fun disableSecureMode() {
window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
}
fun showPaymentForm() {
enableSecureMode()
// Render payment fields and sensitive account data.
}
fun showReceiptList() {
disableSecureMode()
// Render content that users may need to capture.
}
Java dynamic helper
private void enableSecureMode() {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
}
private void disableSecureMode() {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
}
Make the transition part of your navigation or state-management code. Do not rely on onPause() or onStop() to swap in a fake image: technical analysis indicates that the system can capture the task thumbnail before those callbacks give you a usable opportunity to change the view.
4. Can you blur or replace the Recent Apps thumbnail?
No supported public API lets an app provide a custom Recent Apps bitmap. Lifecycle tricks that replace the layout in onPause() or onStop() are unsupported and can miss the capture timing.
On Android 12 (API 31) and newer, setTaskDescription() can set task metadata such as the task label and background color. It does not let you provide a custom thumbnail image. Use it for metadata styling, not for hiding sensitive pixels.
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
val description = android.app.ActivityManager.TaskDescription(
"Account",
null,
0xFF123456.toInt()
)
setTaskDescription(description)
}
If the requirement is privacy, use FLAG_SECURE and accept the blank or black preview. If the requirement is branding, Android does not expose a reliable public mechanism to draw that branding into the system-generated thumbnail.
5. Scope, compatibility and security limits
| Question | Practical answer |
|---|---|
| Does it protect every Activity? | Only the window where the flag is set. Set it on each sensitive Activity or use a shared base Activity. |
| Does it stop screenshots? | It tells Android to block screenshots and non-secure-display output for that window. |
| Does it stop every recording or overlay attack? | No. Android warns that the approach is not fully reliable for overlay attacks and cannot guarantee protection against every recorder, modified system or camera. |
| Will users still see a useful Recent Apps card? | Usually the protected card is blank or black because the sensitive pixels are withheld. |
| Does behavior vary by device? | Yes. System UI and vendor implementations can differ, especially on older Android releases. |
For Android 11 (API 30) and lower, Android’s guidance describes reliable help on around 70% of devices and notes limitations such as keyboard taps being recorded on certain devices. Treat this as a compatibility limitation, not a security guarantee.
On Android 12 and newer, HIDE_OVERLAY_WINDOWS can opt an app out of application overlays drawn on top of it. This complements window protection but addresses a different threat.
For apps targeting Android 17 (API 37) or higher, disabling Content Capture with ContentCaptureManager.setContentCaptureEnabled(false) no longer provides that restriction; Android’s current guidance says developers who need to restrict system capture should transition to FLAG_SECURE.
6. Google Play and policy considerations
Apps distributed through Google Play must respect other apps’ FLAG_SECURE declarations and must not create or facilitate bypasses. Google Play distinguishes this window-level privacy flag from REQUIRE_SECURE_ENV, which signals that an app requires a secure execution environment. Review the Google Play security and privacy policy before shipping behavior intended to capture or relay other apps’ screens.
7. Testing checklist
- Open the protected Activity with representative sensitive data.
- Open Recent Apps and verify that the card does not reveal the data.
- Try the Android screenshot gesture or hardware shortcut.
- Test screen recording and casting on the device families you support.
- Navigate to a non-sensitive state and confirm that clearing the flag restores the intended capture behavior.
- Test process recreation, rotation and deep links so the flag is restored whenever the sensitive Activity is recreated.
- Test OEM devices separately; system UI rendering is not identical across vendors.
8. Troubleshooting
The Recent Apps card still shows sensitive content
Cause: The flag was set on a different Activity, set after the sensitive window was already visible, or cleared during navigation.
Fix: Set it on the exact Activity window before rendering private content. Log the window state around navigation and ensure every recreated instance enables the flag.
Screenshots no longer work on public screens
Cause: The flag remains enabled for the whole Activity.
Fix: Use the dynamic addFlags/clearFlags pattern, or move sensitive content into a dedicated Activity.
A custom logo or blurred thumbnail never appears
Cause: Android does not offer a supported custom thumbnail bitmap API.
Fix: Choose between the privacy-first blank preview from FLAG_SECURE and normal system thumbnails. setTaskDescription() can style metadata but cannot replace the bitmap.
Screen sharing is blank
Cause: Blocking non-secure-display output is part of FLAG_SECURE‘s behavior.
Fix: Disable the flag only for a deliberate, trusted workflow and only when no sensitive content is visible. Do not weaken protection merely to make a recording convenient.
Protection differs between phones
Cause: Android version, vendor System UI and capture implementation vary.
Fix: Test on the minimum supported Android version and important OEMs. Document that the flag reduces exposure but is not a complete defense against rooted, modified or externally filmed devices.
9. Performance, reliability and cost
FLAG_SECURE is a window property and normally has negligible application overhead. The main operational cost is compatibility: screenshots, recordings, casting and support tools may no longer work while the flag is active. Dynamic protection limits that impact to sensitive states.
For high-assurance screens, combine the flag with ordinary controls such as short session timeouts, redacted notifications and careful clipboard handling. Do not display secrets in a non-secure Activity before enabling the flag.
10. Or skip the browser setup
If your goal is to capture a website for documentation, QA or an AI workflow rather than protect an Android window, ScreenshotNeo provides a single screenshot API request. Its capture pipeline accepts consent banners, removes more than 60 known consent platforms plus newsletter popups and chat widgets, and bills only clean shots. Bot checks, blank pages, failed loads, timeouts and cache hits are not billed, and response headers identify the page verdict and billing status. ScreenshotNeo also provides an MCP server for AI agents with take_screenshot, get_page_info and capture_pdf.
See the ScreenshotNeo API documentation for all options. This runnable cURL example captures a page as WebP:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
Python
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://example.com"},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
Node.js
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://example.com'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot failed: ${res.status}`);
const data = Buffer.from(await res.arrayBuffer());
require('fs').writeFileSync('shot.webp', data);
There is a free allowance of 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 screenshots, and every feature is available on every plan. Create a free ScreenshotNeo account.
11. FAQ
Can I show a harmless placeholder instead of a blank card?
Not through a supported public Recent Apps thumbnail API. Android’s supported privacy result is a blank or withheld snapshot.
Should I set the flag in the manifest?
The documented approach is to set the flag on the Activity window in code. This lets you protect only the screens or states that need it.
Does FLAG_SECURE encrypt the app’s data?
No. It controls screenshot and non-secure-display output. Use storage encryption, authentication and session controls for data at rest and account protection.
Can a hardware camera still photograph the screen?
No software window flag can stop an external camera. Treat FLAG_SECURE as one layer in a broader privacy design.


