About Android media resource change monitoring (ContentResolver) application

background

Media monitoring is a very common function. For example, the gallery that comes with a mobile phone will automatically refresh the gallery when it monitors the generation of photographed pictures. It is used to display the latest data to users in a timely manner. For example, in the chat page, it monitors the photo album. If there are new pictures, there will be a small pop-up window asking the user whether to send the taken pictures and so on.
! ! ! The code is at the end of the article! ! ! !
This article will show how to monitor the generated pictures and videos

environment

win10
as 4.0+
jdk 1.8

Ideas

In fact, the code to implement monitoring is nothing more than the same kind of code that comes and goes. One is query comparison, and the other is calling system methods. This article will use ContentResolver for monitoring.

accomplish

First, to monitor the generation of an image, you can monitor it through the registerContentObserver method of ContentReslver, and finally call back to the onChange() method.

The core code is as follows:

getBaseContext().getContentResolver().registerContentObserver(
MediaStore.Images.Media.INTERNAL_CONTENT_URI,
true, this);
getBaseContext().getContentResolver().registerContentObserver(
 MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
true, this);

As you can see, the URL distinguishes between internal and external. The actual meaning is to monitor the body storage and external storage. From the perspective of compatibility, both need to be written.
Looking at the source code:

    /**
     * Register an observer class that gets callbacks when data identified by a
     * given content URI changes.
     * <p>
     * Starting in {@link android.os.Build.VERSION_CODES#O}, all content
     * notifications must be backed by a valid {@link ContentProvider}.
     *
     * @param uri The URI to watch for changes. This can be a specific row URI,
     *            or a base URI for a whole class of content.
     * @param notifyForDescendants When false, the observer will be notified
     *            whenever a change occurs to the exact URI specified by
     *            <code>uri</code> or to one of the URI's ancestors in the path
     *            hierarchy. When true, the observer will also be notified
     *            whenever a change occurs to the URI's descendants in the path
     *            hierarchy.
     * @param observer The object that receives callbacks when changes occur.
     * @see #unregisterContentObserver
     */
    public final void registerContentObserver(@NonNull Uri uri, 
    		boolean notifyForDescendants,
            @NonNull ContentObserver observer) {
        Objects.requireNonNull(uri, "uri");
        Objects.requireNonNull(observer, "observer");
        registerContentObserver(
                ContentProvider.getUriWithoutUserId(uri),
                notifyForDescendants,
                observer,
                ContentProvider.getUserIdFromUri(uri, mContext.getUserId()));
    }

For the boolean parameter notifyForDescendants, it can be understood that if it is set to true, the monitoring of changes related to the media type will be called back. It can be understood that it is a widespread setting and a highly relevant setting. If set to false, it is considered that only this class is specified. The setting can be understood as a specified directory. The correlation is low. Some models may fail due to this parameter.

Similarly, for video monitoring, the core code is as follows:

getBaseContext().getContentResolver().registerContentObserver(
MediaStore.Video.Media.INTERNAL_CONTENT_URI, true, this);
getBaseContext().getContentResolver().registerContentObserver(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI, true, this);

Likewise, the difference is that the Uri settings are different.

Notice

(1) Note that if there is registration, there should be release, otherwise memory leaks will occur. Not writing about memory leaks is the basic quality of an Android developer. Knowing how to modify memory leaks is the threshold for a qualified Android developer.
(2) When registering, the handler can customize the incoming thread, which is related to the type of thread during callback. The callback source code is as follows:

    /** @hide */
    public final void dispatchChange(boolean selfChange, @NonNull Collection<Uri> uris,
            @NotifyFlags int flags, @UserIdInt int userId) {
        if (mHandler == null) {
            onChange(selfChange, uris, flags, userId);
        } else {
            mHandler.post(() -> {
                onChange(selfChange, uris, flags, userId);
            });
        }
    }

You can see that during the callback, if we pass in a handler that is not null, it will be called.
(3) The callback delay belongs to the system source code level and cannot be modified if it is not a customized room. I can only suggest here that you should not use the handler you pass in to avoid delays in some systems. Because under some systems, the handler you pass in will have a delay operation.

Code address
Search for CtxObserverManager class

that’s all----------------------------------------------------------------------------

Guess you like

Origin blog.csdn.net/motosheep/article/details/130542075