1

I am trying to detect screenshots on Android app using fileObserver, fileObserver does not work on Android 6 as expected.

Here is the snippet which detects the screenshot:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_screenshot_detection);

    observer = new FileObserver(Environment.getExternalStorageDirectory() + File.separator + Environment.DIRECTORY_PICTURES
            + File.separator + "Screenshots" + File.separator, FileObserver.ALL_EVENTS) {

        @Override
        public void onEvent(int event, String path) {
            if (event == FileObserver.CREATE) {
                Log.i(TAG, "Screenshot detected @ " + path);
            }
        }
    };
    observer.startWatching();
}

I observe that the same code works on Nexus 5 running 4.4.4 where as does not work (the onEvent is never triggered) on Nexus 5 running 6.0.1 though I have taken care of run-time permissions for API 23+.

I see a known issue with fileObserver for Android M, is there a better alternative for detecting screenshots? I tried contentObserver, faced issues with it as well.

Community
  • 1
  • 1
user7365614
  • 469
  • 2
  • 4
  • 14
  • There is no requirement for an Android device to store screenshots in the directory you are checking, and there is no requirement for an Android device to trigger a `FileObserver` when a screenshot is taken. On Android 5.0+, take the screenshots yourself using the media projection APIs. – CommonsWare Jan 02 '17 at 18:37
  • I would want to detect if there was a screenshot taken while a person is on my app and then prompt them to share stuff from app. Does media protection API provide a way to detect that? I believe we can create screenshots but would not be able to detect a screenshot trigger using media protection API. – user7365614 Jan 03 '17 at 08:37
  • "I believe we can create screenshots but would not be able to detect a screenshot trigger using media protection API" -- correct. Perhaps `FileObserver` has been tweaked to ignore screenshots, for privacy reasons. – CommonsWare Jan 03 '17 at 12:32
  • Is there a better way to detect the screenshot? – user7365614 Jan 03 '17 at 16:29
  • 1
    Other than by taking the screenshot yourself via the media projection APIs, I am not aware of another option. – CommonsWare Jan 03 '17 at 16:30
  • I believe contentObserver is a better option, but there is an issue with it too: http://stackoverflow.com/questions/41428875/android-contentobserver-content-uri-does-not-contain-the-resource-id. – user7365614 Jan 04 '17 at 07:56
  • BTW, I observed that fileObserver isn't working for any directory, the [fileObserver code](http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.1.1_r1/android/os/FileObserver.java#105) does not seem to have any exceptions for screenshots folder. – user7365614 Jan 04 '17 at 09:58

2 Answers2

0

You can check if, the

com.android.systemui:screenshot

process is running or not. If this is running then there is good chance that screen shot was taken while the user was on your app.

Try this code block,

private void screenShotTaken(Activity activity) {
    final Handler handler = new Handler();
    final int delay = 3000;
    final ActivityManager am = (ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE);

    handler.postDelayed(new Runnable() {
        public void run() {

            List<ActivityManager.RunningServiceInfo> services = am.getRunningServices(200);

            for (ActivityManager.RunningServiceInfo ar : services) {
                if (ar.process.equals("com.android.systemui:screenshot")) {
                    Toast.makeText(activity, "Screenshot is taken!!", Toast.LENGTH_SHORT).show();
                }
            }
            handler.postDelayed(this, delay);
        }
    }, delay);
}

This would be something which would keep on running with some delay and will give you enough chance to detect if the screenshot was taken or not. Also, you may like to check this git, where the whole code for the screenshot is there, I think it would take a just a little understanding how things are working.

Ankush Sharma
  • 913
  • 11
  • 20
-2

Android 6.0 have extra security features, that is why it does not allow any application from unknown source to access any thing.

For the time being you can go the application manager then to your app and then go to permissions and then allow storage permission.

I hope this might help you now for the time being.

Waqas Ahmed
  • 153
  • 11
  • Thanks for the response, as mentioned I have the required permissions for reading and writing the external storage, but not able to detect the changes using fileObserver. – user7365614 Jan 03 '17 at 08:41
  • The request is about finding an alternative way to detect file/content observers. – Botond Kopacz Jun 02 '17 at 22:04
  • Android versions later then M e.g. N, O and P are even more secure but they do provide a mechanism for FileObserver working i am also facing the same issue where FileObserver is not a good choice – Zain Ul Abidin Mar 13 '20 at 07:51