我目前正在为android开发一个应用程序,想知道如何检测屏幕截图。我试过使用fileobserver,但问题是所有事件都被检测到(当设备进入睡眠、消息等状态时)。如何只检测截图?
提前谢谢你!

最佳答案

如何使用FileObserver检测屏幕快照创建?使用FileObserver时,仅监视屏幕快照目录中的文件创建事件。

    String path = Environment.getExternalStorageDirectory()
            + File.separator + Environment.DIRECTORY_PICTURES
            + File.separator + "Screenshots" + File.separator;
    Log.d(TAG, path);

    FileObserver fileObserver = new FileObserver(path, FileObserver.CREATE) {
        @Override
        public void onEvent(int event, String path) {
            Log.d(TAG, event + " " + path);
        }
    };

    fileObserver.startWatching();

别忘了声明访问SD卡内容的相应权限。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

另一种检测屏幕快照的解决方案是使用ContentObserver,因为屏幕快照后会有一条记录插入到系统媒体数据库中。下面是使用ContentObserver监视事件的代码段。通过使用ContentObserver,不需要声明write/read external storage权限,但您必须对文件名进行一些筛选,以确保它是一个屏幕截图事件。
    HandlerThread handlerThread = new HandlerThread("content_observer");
    handlerThread.start();
    final Handler handler = new Handler(handlerThread.getLooper()) {

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
        }
    };

    getContentResolver().registerContentObserver(
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
            true,
            new ContentObserver(handler) {
                @Override
                public boolean deliverSelfNotifications() {
                    Log.d(TAG, "deliverSelfNotifications");
                    return super.deliverSelfNotifications();
                }

                @Override
                public void onChange(boolean selfChange) {
                    super.onChange(selfChange);
                }

                @Override
                public void onChange(boolean selfChange, Uri uri) {
                    Log.d(TAG, "onChange " + uri.toString());
                    if (uri.toString().matches(MediaStore.Images.Media.EXTERNAL_CONTENT_URI.toString() + "/[0-9]+")) {

                        Cursor cursor = null;
                        try {
                            cursor = getContentResolver().query(uri, new String[] {
                                    MediaStore.Images.Media.DISPLAY_NAME,
                                    MediaStore.Images.Media.DATA
                            }, null, null, null);
                            if (cursor != null && cursor.moveToFirst()) {
                                final String fileName = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME));
                                final String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
                                // TODO: apply filter on the file name to ensure it's screen shot event
                                Log.d(TAG, "screen shot added " + fileName + " " + path);
                            }
                        } finally {
                            if (cursor != null)  {
                                cursor.close();
                            }
                        }
                    }
                    super.onChange(selfChange, uri);
                }
            }
    );

更新
如果使用第二种方法,则必须在android m版本之后请求READ_EXTERNAL_STORAGE,否则它将抛出SecurityException。有关如何请求运行时权限的详细信息,请参阅here

07-24 09:48
查看更多