我正在尝试检测Android应用上的屏幕截图。 我正在使用contentObserver来检测媒体目录中的更改,而不是使用FileObserver,因为在Android M上有known issue它。
以下是代码段:
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 void onChange(boolean selfChange, Uri uri) {
Log.d(TAG, "URL : " + uri.toString());
//Code to query using content resolver
if (uri.toString().matches(MediaStore.Images.Media.EXTERNAL_CONTENT_URI.toString())) {
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()) {
//Logic to filter if it is a screenshot file
}
} finally {
if (cursor != null) {
cursor.close();
}
}
}
super.onChange(selfChange, uri);
}
}
);
调用onChange时(截取屏幕截图/媒体文件夹中的任何其他更改)后,URI为“ content:// media / external / images / media ”,而不是包含资源ID,例如: content:// media / external / images / media / 12345 ,对于我尝试的大多数设备都会出现这种情况 - Moto G3(Android 6.0.1),Nexus 5 (Android 6.0),我在三星S5上运行6.0.1获得整个URI(包括ID)。
这是一个已知问题吗?
我如何获得身份证?
迭代整个媒体目录并查找是否在应用处于活动状态时拍摄屏幕截图不是优化的解决方案,而是在内容URI中获取资源ID可以解决问题,因为我们可以直接获取文件的路径并且检测它是否是截图文件,观察者仍然观察所有媒体内容的变化(例如,它还观察到在后台发生的WhatsApp图像下载)。
答案 0 :(得分:2)
不幸的是,我认为在插入Uri
中指定的表格时,您无法指望接收正确的MediaStore
。
这是Android 5.1.1的MediaProvider#insert()
方法的来源(取自here):
@Override
public Uri insert(Uri uri, ContentValues initialValues) {
int match = URI_MATCHER.match(uri);
ArrayList<Long> notifyRowIds = new ArrayList<Long>();
Uri newUri = insertInternal(uri, match, initialValues, notifyRowIds);
notifyMtp(notifyRowIds);
// do not signal notification for MTP objects.
// we will signal instead after file transfer is successful.
if (newUri != null && match != MTP_OBJECTS) {
getContext().getContentResolver().notifyChange(uri, null);
}
return newUri;
}
请注意以下一行:getContext().getContentResolver().notifyChange(uri, null)
。
以上意味着在插入MediaProvider
后,将为指定插入的Uri
发送通知,该通知始终为“目录”Uri
。这可能是一个错误:如果不是uri
,他们会使用newUri
- 它会完全按照您的预期工作。
如果它适用于带有Marshmallow的三星,那么要么在Android 6+中修复了这个问题,要么三星将它固定在他们的AOSP版本中。但我不认为你真的可以依靠它来可靠地工作。