【问题标题】:Android | contentObserver | Content URI does not contain the resource ID安卓 |内容观察者 |内容 URI 不包含资源 ID
【发布时间】:2017-01-02 14:45:36
【问题描述】:

我正在尝试检测 Android 应用上的屏幕截图。 我正在使用 contentObserver 来检测媒体目录中的更改,而不是使用 FileObserver,因为它在 Android M 上使用了 known issue

这里是sn-p的代码:

    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),其中,我在运行 6.0.1 的三星 S5 上获得了整个 URI(包括 ID)。

这是一个已知问题吗?

我怎样才能获得 ID?

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

【问题讨论】:

    标签: java android android-studio android-contentprovider fileobserver


    【解决方案1】:

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

    这是 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。这可能是一个错误:如果他们使用 newUri 而不是 uri - 它会完全按照您的预期工作。

    如果它在带有 Marshmallow 的三星上运行,那么要么在 Android 6+ 中修复了这个问题,要么三星在他们的 AOSP 版本中修复了它。但我不认为你真的可以指望它可靠地工作。

    【讨论】:

    • 那么这个问题就没有办法解决了吗?我正在使用相同的代码,并且在“Media/”之后没有返回任何 ID。在棉花糖里。
    猜你喜欢
    • 1970-01-01
    • 2011-11-09
    • 1970-01-01
    • 2013-05-14
    • 2011-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多