Android |contentObserver |内容URI不包含资源ID [英] Android | contentObserver | Content URI does not contain the resource ID

查看:103
本文介绍了Android |contentObserver |内容URI不包含资源ID的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试检测Android应用程序上的屏幕截图.由于

I am trying to detect screenshot on an Android app. I am using contentObserver to detect the change in the media directory, not using FileObserver because of known issue with it on Android M.

这是代码段:

    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 ",而不是包含以下内容的整个URI:资源ID,例如: content://media/external/images/media/12345 ,这种情况发生在我尝试过的大多数设备上-Moto G3(Android 6.0.1),Nexus 5(Android 6.0),我在运行6.0.1的Samsung S5上获得了整个URI(包括ID).

When onChange is called (after screenshot is taken / any other changes in media folder) the URI is "content://media/external/images/media" instead of the whole URI containing the resource ID as well, something like: content://media/external/images/media/12345, this happens for most of the devices I tried - Moto G3 (Android 6.0.1), Nexus 5 (Android 6.0), where as, I get the whole URI (including ID) on Samsung S5 running 6.0.1.

这是一个已知问题吗?

我也如何获取ID?

这不是一种优化的解决方案,它可以遍历整个媒体目录并查找在应用程序处于活动状态时是否截屏,而在内容URI中获取资源ID可以解决问题,因为我们可以直接获取文件的路径并检测它是否是屏幕快照文件,但观察者仍然观察所有媒体内容的变化(例如,它还观察到后台发生的WhatsApp图像下载).

It is not an optimized solution to iterate over the whole media directory and find if a screenshot was taken when the app was active, rather getting the resource ID in the content URI would solve the problem as we can directly fetch the file's path and detect if it is a screenshot file, the observer still observes for all the media content changes though (for example, it also observes a WhatsApp image download happening in the background).

推荐答案

不幸的是,我认为当您插入 MediaStore中指定的表时,您将无法指望收到正确的 Uri .

Unfortunately, I think you won't be able to count on receiving correct Uri upon insertions into tables specified in MediaStore.

这是Android 5.1.1的 MediaProvider#insert()方法的来源(摘自

This is the source of MediaProvider#insert() method for Android 5.1.1 (taken from 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 .这可能是一个错误:如果他们使用 newUri 代替 uri ,它将完全按照您的预期工作.

The above means that upon insertion into MediaProvider, notifications will be send for Uri specified for insertion, which is always a "directory" Uri. This is, probably, a bug: if instead of uri they would use newUri - it would work exactly as you expected it to work.

如果它可以与棉花糖一起在三星上使用,则要么在Android 6+中已修复,要么在三星的AOSP版本中对其进行了修复.但是我认为您不能真正依靠它来可靠地工作.

If it works on Samsung with Marshmallow, then either this was fixed in Android 6+, or Samsung fixed it in their build of AOSP. But I don't think that you can really count on this to work reliably.

这篇关于Android |contentObserver |内容URI不包含资源ID的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆