On Android 14 (API level 34) and newer, detect screenshots of a visible activity with Activity.ScreenCaptureCallback. Declare the install-time android.permission.DETECT_SCREEN_CAPTURE permission, register the callback in onStart(), and unregister it in onStop(). The callback reports that a capture occurred; it does not provide the screenshot pixels or the identity of the person who captured it.
What Android’s screenshot-detection API does
Android 14 introduced a privacy-preserving, per-activity callback for screenshot detection. It is intended for an app that wants to react after a user captures the activity currently visible on screen—for example, by recording an audit event, updating in-app state, or displaying guidance.
- Minimum version: API level 34 (Android 14).
- Scope: the individual activity that is visible and has registered the callback.
- Output: an event through
onScreenCaptured(), not an image. - Permission:
android.permission.DETECT_SCREEN_CAPTURE, declared in the manifest. - Lifecycle: register while the activity is started and unregister when it stops.
Android also displays a system notice for each detection signal. Explain that behavior in your privacy or help text so users are not surprised.
Set up the permission and lifecycle
1. Declare the install-time permission
Add this line to AndroidManifest.xml:
<manifest ...>
<uses-permission android:name="android.permission.DETECT_SCREEN_CAPTURE" />
...
</manifest>
The permission is install-time. The detection API does not use the per-session consent dialog required by MediaProjection.
#1 Best Overall
2. Register only while the activity is visible
Create one callback instance for the activity, register it from onStart(), and unregister the same instance from onStop(). Tying registration to these lifecycle methods avoids leaving a callback attached after the activity is no longer visible.
Complete Kotlin implementation
This activity records a local event whenever Android reports a screenshot. The API call is guarded so the app still builds and runs on older Android releases.
import android.app.Activity
import android.os.Build
import android.os.Bundle
import android.util.Log
class AccountActivity : Activity() {
private var callbackRegistered = false
private val screenCaptureCallback =
Activity.ScreenCaptureCallback {
// Keep this handler small; persist or send an event as appropriate.
Log.i("AccountActivity", "Visible activity was captured")
onScreenshotDetected()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_account)
}
override fun onStart() {
super.onStart()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
registerScreenCaptureCallback(
mainExecutor,
screenCaptureCallback
)
callbackRegistered = true
}
}
override fun onStop() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE &&
callbackRegistered
) {
unregisterScreenCaptureCallback(screenCaptureCallback)
callbackRegistered = false
}
super.onStop()
}
private fun onScreenshotDetected() {
// Update state, show an explanation, or queue an audit record.
// Do not expect screenshot pixels here.
}
}
Build.VERSION_CODES.UPSIDE_DOWN_CAKE is the Android 14 API constant. If your project uses a different minimum SDK, retain the runtime check; otherwise the app can attempt to call an API that does not exist on an older device.
What the callback tells you—and what it cannot
It reports an event, not an image
onScreenCaptured() has no bitmap, file path, URI, or pixel buffer. Your response must be based on the state your app already knows, such as which account screen was visible or which document was open. If you need the actual pixels, use MediaProjection instead.
Recommended Free Tools
It does not identify the person
The callback does not provide a user name, account, process, or other identity for whoever initiated the capture. Treat it as “this monitored activity received a supported capture signal,” not as proof of who pressed a button.
Rank #2
Coverage is limited
The Android documentation describes detection for the supported hardware-button screenshot combination. It does not detect screenshots made with ADB commands or instrumentation tests that capture screen contents. Do not promise universal detection in product requirements or security documentation.
FLAG_SECURE changes the behavior
When the activity window uses FLAG_SECURE, Android prevents the window from appearing in screenshots and other non-secure displays. The API reference states that onScreenCaptured() is not invoked for an activity window with this flag. Therefore, prevention and notification are separate designs: a protected window is not a way to receive a capture event.
Choose detection, prevention, or active capture
| Approach | Purpose | Minimum API | User consent | Pixels available? | Scope and limitations |
|---|---|---|---|---|---|
Activity.ScreenCaptureCallback |
React after a supported screenshot of your visible activity | 34 | No MediaProjection session; declare DETECT_SCREEN_CAPTURE |
No | Per activity; supported hardware-button screenshots only; excludes ADB and instrumentation captures |
FLAG_SECURE |
Prevent sensitive content from appearing in screenshots or other non-secure displays | Available as a window security flag; use according to your app’s supported versions | No capture session | No | Blocks the protected window; the screenshot callback is not invoked for that window |
| MediaProjection | Actively capture or share a display or app window | 21; Android 14 adds app-window sharing | Yes, before each session | Yes, through a virtual display and Surface |
Session and resource lifecycle must be managed; it is not passive screenshot detection |
Use the callback for audit or UX reactions
Select the callback when your requirement is notification after a user screenshot. Keep the handler quick, then queue durable work such as analytics or an audit record. Because no image is delivered, design the event schema around activity and app state rather than a missing file.
Free tools Windows power users keep installed
One-click scans. No signup required.
Use FLAG_SECURE for confidentiality
Set the flag on windows containing credentials, payment data, health information, or other content that must not be captured. If policy permits users to control protection, expose a clear setting and explain its effect.
Use MediaProjection for recording or sharing
MediaProjection starts with MediaProjectionManager.createScreenCaptureIntent(). Android requires user consent before each projection session. The selected display or app window is rendered to a virtual display backed by a Surface. Register MediaProjection.Callback.onStop() and release the virtual display and surface when the session ends. Android 14 adds app-window sharing; Android 12L (API 32) documents surface-scaling behavior. Audio playback capture was introduced in Android 10 (API 29) and is documented separately from screenshot detection.
For managed-device deployments, Android also documents DevicePolicyManager.setScreenCaptureDisabled(). That policy control is different from both the per-activity callback and a user-consented projection session.
Supporting Android versions below 14
There is no equivalent standardized per-activity callback in the supplied Android API documentation for older releases. Gate registration behind an API 34 check and define an explicit fallback:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
- On API 34 and newer, register the callback normally.
- On older versions, omit registration and do not claim that screenshots are detected.
- If the real requirement is protection rather than notification, apply
FLAG_SECUREon every supported version where your policy requires it. - If the requirement is screen content, start a user-consented MediaProjection session instead of trying to infer screenshots.
Test every activity that can show sensitive content. Registration is per activity; registering one activity does not automatically monitor another.
Troubleshooting
The callback never fires
- Confirm the device is running Android 14/API 34 or newer.
- Verify
DETECT_SCREEN_CAPTUREis in the application manifest. - Check that registration occurs after
super.onStart()and that the activity is actually visible. - Test with the supported hardware-button screenshot path. ADB and instrumentation captures are outside the documented coverage.
- Ensure the window is not using
FLAG_SECURE; the callback is not invoked for a secure window.
The app crashes on an older device
Calling the API without a version guard can fail on pre-34 devices. Wrap both registration and unregistration in an API-level check, as in the Kotlin example, and keep the callback type out of code paths that execute on unsupported releases.
Unregistration causes an error or duplicate events appear
Use the exact callback object that was registered, unregister it once, and track whether registration succeeded. Do not create a new callback instance in onStop(). Lifecycle recreation can otherwise leave mismatched instances or repeated registrations.
A test expects the screenshot file
The detection callback never supplies pixels. Change the test to assert that your event handler ran, or write a separate MediaProjection test that obtains user consent and validates the captured surface.
Users report an unexpected system notice
Android shows a notice for each detection signal. Tell users in the app’s privacy or security explanation that screenshot detection is active and describe what your app records in response.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Or skip the browser setup
If what you actually need is automated screenshots of websites for documentation, previews, or monitoring—not detection of screenshots taken on an Android device—ScreenshotNeo provides a one-request website screenshot API. It is not a replacement for Activity.ScreenCaptureCallback, FLAG_SECURE, or MediaProjection.
ScreenshotNeo accepts a URL and returns PNG, JPEG, WebP, or PDF. Cookie and consent banners, newsletter popups, and chat widgets are removed before capture. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP server gives Claude, Cursor, and other MCP clients take_screenshot, get_page_info, and capture_pdf tools.
Use the API documentation at https://screenshotneo.com/docs/ for all parameters. A cURL request is:
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
The same request in Python:
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
And in Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
Every plan includes the features: the free plan provides 1,000 shots per month with no card, and paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account to try it without a card.
Frequently asked questions
Does the detection permission require a runtime dialog?
DETECT_SCREEN_CAPTURE is documented as an install-time permission. Add it to the manifest; the screenshot-detection flow itself is not a MediaProjection consent request.
Can one registration monitor the whole application?
No. The callback is scoped to an activity. Register it separately in each activity whose visible content you need to monitor, following that activity’s start and stop lifecycle.
Frequently Asked Questions
Does the detection permission require a runtime dialog?
No runtime dialog is described for the install-time DETECT_SCREEN_CAPTURE permission; declare it in the manifest.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Can one callback monitor every activity in the app?
No. ScreenCaptureCallback is per activity, so register it in each activity that needs monitoring.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




