我目前正在为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。