[Android] Screenshot detection while user using your app

Overview

Android Arsenal Maven Central Minimum SDK Version Workflow Status

Android-ScreenshotDetection

Screenshot Detection Library

Download

Since version 1.0.1 will move from JCenter to MavenCentral

// build.gradle (project)
allprojects {
    repositories {
        mavenCentral()
        /* ... */
    }
}

Gradle

implementation 'com.akexorcist:screenshot-detection:1.0.1'

Permission in this library

This library has declared the permission to read the external storage. So you need to handle the runtime permission by yourself. If not, app will not crash and screenshot detection still work but no file path.

Usage

Implement the library to your activity or your base activity.

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity

import com.akexorcist.screenshotdetection.ScreenshotDetectionDelegate

open class ScreenshotDetectionActivity : AppCompatActivity(), ScreenshotDetectionDelegate.ScreenshotDetectionListener {
    private val screenshotDetectionDelegate = ScreenshotDetectionDelegate(this, this)

    override fun onStart() {
        super.onStart()
        screenshotDetectionDelegate.startScreenshotDetection()
    }

    override fun onStop() {
        super.onStop()
        screenshotDetectionDelegate.stopScreenshotDetection()
    }

    override fun onScreenCaptured(path: String) {
        // Do something when screen was captured
    }

    override fun onScreenCapturedWithDeniedPermission() {
        // Do something when screen was captured but read external storage permission has denied
    }
}

But above example will not work because read the external storage permission has denied. To fix this, you need to add the code for runtime permission request.

import android.Manifest
import android.content.pm.PackageManager
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat

open class ScreenshotDetectionActivity : AppCompatActivity(), ScreenshotDetectionDelegate.ScreenshotDetectionListener {
    /* ... */

    companion object {
        private const val REQUEST_CODE_READ_EXTERNAL_STORAGE_PERMISSION = 3009
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        checkReadExternalStoragePermission()
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        when (requestCode) {
            REQUEST_CODE_READ_EXTERNAL_STORAGE_PERMISSION -> {
                if (grantResults.getOrNull(0) == PackageManager.PERMISSION_DENIED) {
                    showReadExternalStoragePermissionDeniedMessage()
                }
            }
            else -> super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        }
    }

    private fun checkReadExternalStoragePermission() {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            requestReadExternalStoragePermission()
        }
    }

    private fun requestReadExternalStoragePermission() {
        ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), REQUEST_CODE_READ_EXTERNAL_STORAGE_PERMISSION)
    }

    private fun showReadExternalStoragePermissionDeniedMessage() {
        Toast.makeText(this, "Read external storage permission has denied", Toast.LENGTH_SHORT).show()
    }
}

Then extends your target activity with that base activity class and declare onScreenCaptured(path: String) and onScreenCapturedWithDeniedPermission() when you want to detect the screenshot.

import android.os.Bundle
import android.widget.Toast

class MainActivity : ScreenshotDetectionActivity() {
	/* ... */

    override fun onScreenCaptured(path: String) {
        Toast.make(this, path, Toast.LENGTH_SHORT).show();
        // Do something when screen was captured
    }

    override fun onScreenCapturedWithDeniedPermission() {
        Toast.make(this, "Please grant read external storage permission for screenshot detection", Toast.LENGTH_SHORT).show()
        // Do something when screen was captured but read external storage permission has denied
    }
}

Demo

Demo

Licence

Copyright 2021 Akexorcist

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with the License. You may obtain a copy of the License in the LICENSE file, or at:

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Comments
  • There is fatal exception on ScreenshotDetectionDelegate line 142

    There is fatal exception on ScreenshotDetectionDelegate line 142

    https://github.com/akexorcist/ScreenshotDetection/blob/8d80751d77b73ab5b2cba34b73215038e01d6bf0/screenshotDetection/src/main/java/com/akexorcist/screenshotdetection/ScreenshotDetectionDelegate.kt#L142

    this code makes android.database.CursorIndexOutOfBoundsException. I think it reports when no media file on device.

    opened by crust87 8
  • onScreenCapturedWithDeniedPermission may be incorrect

    onScreenCapturedWithDeniedPermission may be incorrect

    Hi, I have seen all the source codes of this project, and I notice that onScreenCapturedWithDeniedPermission may cause some unexpected results.

    For example, if the external disk is put something new, then you will detect a new file and invoke onContentChanged, but it's actually not the screen capture.

    opened by Lewin671 1
  • Hello, I found that after denying the storage permission, the screenshot will call the onScreenCapturedWithDeniedPermission method twice.

    Hello, I found that after denying the storage permission, the screenshot will call the onScreenCapturedWithDeniedPermission method twice.

    Hello, I found that after denying the storage permission, the screenshot will call the onScreenCapturedWithDeniedPermission method twice. After the permission is granted, the onScreenCaptured method is called only once. sorry for my pool english

    image image

    opened by MRDHR 1
  • Fix a crash for CursorIndexOutOfBoundsException

    Fix a crash for CursorIndexOutOfBoundsException

    Problem

    cursor.getString can make the CursorIndexOutOfBoundsException when the cursor's length of the database is zero.

    Situation

    The situation can happen when the READ_EXTERNAL_STORAGE permission is not allowed by the OS ( >= Android 12)

    Solution

    Add a guard for the case that the cursor's length of the database is zero.

    opened by jason-hwang 0
  • Hello, there is a crash in the use of this library.

    Hello, there is a crash in the use of this library.

    android.database.AbstractCursor.checkPosition(AbstractCursor.java:515) android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:138) android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:52) android.database.CursorWrapper.getString(CursorWrapper.java:141) com.akexorcist.screenshotdetection.ScreenshotDetectionDelegate.getFilePathFromContentResolver(ScreenshotDetectionDelegate.kt:142) com.akexorcist.screenshotdetection.ScreenshotDetectionDelegate.onContentChanged(ScreenshotDetectionDelegate.kt:107) com.akexorcist.screenshotdetection.ScreenshotDetectionDelegate.access$onContentChanged(ScreenshotDetectionDelegate.kt:32) com.akexorcist.screenshotdetection.ScreenshotDetectionDelegate$startScreenshotDetection$1$invokeSuspend$$inlined$collect$1.emit(Collect.kt:134) kotlinx.coroutines.flow.FlowKt__DelayKt$debounceInternal$1$3$1.invokeSuspend(Delay.kt:235) kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106) android.os.Handler.handleCallback(Handler.java:883) android.os.Handler.dispatchMessage(Handler.java:100) android.os.Looper.loop(Looper.java:237) android.app.ActivityThread.main(ActivityThread.java:7830) java.lang.reflect.Method.invoke(Native Method) com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1040)

    opened by MRDHR 0
  • Catch error on delete file from screenshot

    Catch error on delete file from screenshot

    fixes #3 .

    • Catch general Error instead of IllegalStateException on getFilePathFromContentResolver method.
    • Avoid using MediaStore.Images.Media.DATA due to deprecated API.
      • Just workaround, I can't find a way to migrate method for getting full path of screenshot file.
    opened by Kurogoma4D 0
  • android.database.CursorIndexOutOfBoundsException

    android.database.CursorIndexOutOfBoundsException

    I found this error in some devices like Samsung, Xiaomi, Oppo, and Realme

    com.akexorcist.screenshotdetection.ScreenshotDetectionDelegate.getFilePathFromContentResolver (ScreenshotDetectionDelegate.kt:142) com.akexorcist.screenshotdetection.ScreenshotDetectionDelegate.onContentChanged (ScreenshotDetectionDelegate.kt:107) com.akexorcist.screenshotdetection.ScreenshotDetectionDelegate.access$onContentChanged (ScreenshotDetectionDelegate.kt:32) com.akexorcist.screenshotdetection.ScreenshotDetectionDelegate$startScreenshotDetection$1$invokeSuspend$$inlined$collect$1.emit (Collect.kt:133) kotlinx.coroutines.flow.FlowKt__DelayKt$debounceInternal$1$3$1.invokeSuspend (Delay.kt:235)

    opened by wahyukharisma 1
  • android.database.CursorIndexOutOfBoundsException

    android.database.CursorIndexOutOfBoundsException

    com.akexorcist.screenshotdetection.ScreenshotDetectionDelegate.getFilePathFromContentResolver(ScreenshotDetectionDelegate.kt:142)

    This problem occurs on some devices

    opened by rs5173 0
Releases(1.0.2)
  • 1.0.2(Nov 10, 2021)

    • Update Gradle plugin and dependencies
      • Kotlin 1.5.31
      • Kotlin Coroutines Android 1.5.0
      • Core KTX 1.6.0
    • Using MavenCentral instead of JCenter
    • Add more screenshot directory checking (#2)
    • Remove onScreenCapturedWithDeniedPermission (#4 #5)
    • Merge pull request (#6)
    Source code(tar.gz)
    Source code(zip)
  • 1.0.1(Dec 26, 2020)

    • Update target version to 30
    • Migrate from Android Support to AndroidX
    • Migrate from Java to Kotlin
    • Add debounce (Coroutines Flow) to screen capture listener (Prevent multiple event emit)
    • Move from MavenCentral to JCenter
    Source code(tar.gz)
    Source code(zip)
Owner
Akexorcist
Lovely android developer who enjoys learning in android technology, habitual article writer about Android development for Android developers in Thailand
Akexorcist
An Android project containing image recognition and object detection models.

An Android project containing image recognition and object detection models. Users can input images into the deep learning model by taking photos, opening photo albums, and real-time previews on the Android side. After the calculation on the Android side is completed, the model will output the prediction result and show it to the user.

null 7 Nov 27, 2022
Custom view for circular images in Android while maintaining the best draw performance

CircularImageView Custom view for circular images in Android while maintaining the best draw performance Usage To make a circular ImageView, add this

Pkmmte Xeleon 1.2k Dec 28, 2022
A small customizable library useful to handle an gallery image pick action built-in your app. :sunrise_over_mountains::stars:

Louvre A small customizable image picker. Useful to handle an gallery image pick action built-in your app. *Images from Google Image Search Installati

André Mion 640 Nov 19, 2022
Bring out the best in your phone's camera

DNG Processor How does this app work? It waits for new RAW images captured using a supported camera app, and then processes them in the background. It

Amir Zaidi 97 Dec 15, 2022
A library for auto removing background from your photos.

This is an android library for removing background from the image. You have to give the bitmap of the image to this library and the library will retur

Ghayas Ahmad 47 Jan 5, 2023
A simple implementation of rectangle detector on Android using OpenCV.

A simple implementation of rectangle detector on Android using OpenCV.

SmartBank, Inc. 4 Oct 7, 2022
A pixel art creator for Android using RecyclerView.

PyxlMoose A pixel art creator for Android using RecyclerView. Contributing Guidelines I would love your input! I have a goal of making contributing to

Tom Joney 128 Dec 31, 2022
Phimp.me Android Phimp.me is an Android image editor app

Phimp.me Android Phimp.me is an Android image editor app that aims to replace proprietary photographing and image apps on smart phones. It offers feat

FOSSASIA 2.6k Jan 6, 2023
Android app for implementing vision transformer(computationally heavy) in production.

Android app for implementing vision transformer(computationally heavy) in production.

Mann Patel 3 Nov 14, 2022
Image classifier app build in Android Studio.

Android Image Classifier App Strongly based on https://github.com/microsoft/onnxruntime-inference-examples/tree/main/mobile/examples/image_classificat

Luiz Santos 3 Feb 17, 2022
Note saver app which can save images as well with customization.

Note-With-Images-App Note saver app which can save images as well with customization. Demo final.demo.mp4 What i used? Kotlin Paging 3 library flow li

agam koradiya 9 Oct 31, 2022
🐶 Simple app which shows random dog image from Dog API

?? Doggy App ?? ?? Simple app which shows random dog image from Dog API with Retrofit2 and Glide ?? ❤️ Retrofit @GET Request YouTube Tutorial! (Stevdz

Yağmur Erdoğan 10 Nov 1, 2022
Opencv Android SDK application for Deep Neural Networks to run on Android.

This application allows you to deploy deep nets in Android environment using OpenCV Android SDK. With OpenCV, images are taken from the camera on your phone, and then these images are passed through the neural network and visualized on the front side. In this application, we will search for faces in the images taken and draw the found faces on the screen.

Ahmet Furkan DEMIR 10 Nov 1, 2022
Android filters based on OpenGL (idea from GPUImage for iOS)

GPUImage for Android Idea from: iOS GPUImage framework Goal is to have something as similar to GPUImage as possible. Vertex and fragment shaders are e

CATS Open Source Softwares 8.6k Dec 28, 2022
Android library project for cropping images

I guess people are just cropping out all the sadness An Android library project that provides a simple image cropping Activity, based on code from AOS

Jamie McDonald 4.5k Jan 7, 2023
some android image filters

android-image-filter some android image filters in some filter, I use NDK to implement to make it more efficient Setup Install Android NDK and properl

RagnarokStack 643 Dec 27, 2022
An android image compression library.

Compressor Compressor is a lightweight and powerful android image compression library. Compressor will allow you to compress large photos into smaller

Zetra 6.7k Dec 31, 2022
Custom shaped android imageview components

Shape Image View Provides a set of custom shaped android imageview components, and a framework to define more shapes. Implements both shader and bitma

Siyamed SINIR 2.6k Jan 3, 2023
Android widget for cropping and rotating an image.

Cropper The Cropper is an image cropping tool. It provides a way to set an image in XML and programmatically, and displays a resizable crop window on

Edmodo 2.9k Nov 14, 2022