Detecting Screenshots
warning
Screenshot detection is only available in API level 34 (Android 14) or higher.
Android 14 introduces a way to detect a screenshot performed by user.
Limitation
This method only detects specific combination of hardware button presses (most commonly Power and Volume-down buttons). Here's a table summarizing the limitation of this method:
Screenshot Method | Specific Method | Can be detected? |
---|---|---|
Hardware button presses | ✅ | |
With emulator | ⛔️ | |
With logcat | ⛔️ | |
With Android Debug Bridge (adb) | screencap command | ⛔️ |
KEYCODE_SYSRQ keyevent | ✅ | |
Programmatically | ⛔️ | |
Within instrumented testing | DeviceCapture API | ⛔️ |
captureToImage or captureToBitmap API | ⛔️ |
Basic Usage
First, you need to declare DETECT_SCREEN_CAPTURE
install-time permission inside your AndroidManifest.xml
file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<!-- Add this permission: -->
<uses-permission android:name="android.permission.DETECT_SCREEN_CAPTURE" />
</manifest>
To start detecting screenshots, you need to utilize these 3 key components within your Activity:
Activity.ScreenCaptureCallback
: The screenshot detection callback that you need to define.registerScreenCaptureCallback
: This method registers your screenshot detection callback.unregisterScreenCaptureCallback
: This method unregisters your screenshot detection callback.
Here is a simple example of such Activity:
MainActivity.kt
package com.hanmajid.androidnotebook
import android.app.Activity.ScreenCaptureCallback
import android.os.Build
import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.ui.Modifier
import com.hanmajid.androidnotebook.ui.theme.AndroidNotebookTheme
class MainActivity : ComponentActivity() {
private val screenCaptureCallback = ScreenCaptureCallback {
Toast.makeText(this, "A screenshot is taken!", Toast.LENGTH_LONG).show()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
AndroidNotebookTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
Text("Android")
}
}
}
}
override fun onStart() {
super.onStart()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
registerScreenCaptureCallback(
mainExecutor,
screenCaptureCallback
)
}
}
override fun onStop() {
super.onStop()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
unregisterScreenCaptureCallback(screenCaptureCallback)
}
}
}
Here's what happen when we take a screenshot:
You will notice that after the screenshot was taken, 2 things happen:
My Application detected this screenshot.
message appears below the screenshot preview. I believe this is the default behavior when an Activity uses the screen detection API.A screenshot is taken!
toast appears. This is the callback that we define within our Activity. You can fill this callback with whatever you need in your app.