FileObserver CREATE or DELETE received only for files
Asked Answered
A

3

7

I've registered a FileObserver for a directory.

this.observer = new DirectoryObserver(requested.getAbsolutePath(),
        FileObserver.CREATE | FileObserver.DELETE | FileObserver.DELETE_SELF);
this.observer.startWatching();

Tested on KitKat emulator. adb shell:

root@generic:/sdcard # echo "test" >> test.txt //notified CREATE
root@generic:/sdcard # rm test.txt //notified DELETE
root@generic:/sdcard # mkdir test //no events received
root@generic:/sdcard # rmdir test //no events received 

The DirectoryObserver for reference

private final class DirectoryObserver extends FileObserver {

    private DirectoryObserver(String path, int mask) {
        super(path, mask);
    }

    @Override
    public void onEvent(int event, String pathString) {
        switch (event) {
            case FileObserver.DELETE_SELF:
                //do stuff
                break;

            case FileObserver.CREATE:
            case FileObserver.DELETE:
                //do stuff
                break;
        }
    }
}

From docs

CREATE
Event type: A new file or subdirectory was created under the monitored directory 

DELETE
Event type: A file was deleted from the monitored directory 

So for CREATE I should receive for files and directories and on DELETE only for files? Well, I still don't receive CREATE for a subdirectory.

Amphictyon answered 8/12, 2013 at 15:57 Comment(0)
N
19

The reason of this is that android does not abstract over underlying file system well enough and returns underlying event code with some of the flags raised (some of the higher bits of the event). This is why comparing the event value with the event type directly does not work.

To solve this you can drop extra flags by applying FileObserver.ALL_EVENTS event mask (using bitwise and) to actual event value stripping it down to event type.

Using the code you've provided in your question this will look something like this:

private final class DirectoryObserver extends FileObserver {

    private DirectoryObserver(String path, int mask) {
        super(path, mask);
    }

    @Override
    public void onEvent(int event, String pathString) {
        event &= FileObserver.ALL_EVENTS;
        switch (event) {
            case FileObserver.DELETE_SELF:
                //do stuff
                break;

            case FileObserver.CREATE:
            case FileObserver.DELETE:
                //do stuff
                break;
        }
    }
}
Norwich answered 16/12, 2013 at 11:19 Comment(4)
Fantastic answer, would have never figured this out, thank you. Worth noting that many devices require ALL_EVENTS to be used to actually get any sort of monitoring, and the above answer helps quickly filter out unwanted events. These events are delivered on a special thread for file observers.Korenblat
If you have an event code and would like to figure out the corresponding event code for a folder, you can bitwise or the event. FileObserver.DELETE | 0x40000000Japhetic
What happens when a file is DELETE and then CREATE again?Flyman
what if file can not be deleted because of any reason??Palette
O
2

I've tested on two devices, one with Ice Cream Sandwich and one with Lollipop. They always come out with the same int, so I just defined two new constants:

/**
 * Event type: A new subdirectory was created under the monitored directory<br>
 * For some reason this constant is undocumented in {@link FileObserver}.
 */
public static final int CREATE_DIR = 0x40000100;
/**
 * Event type: A subdirectory was deleted from the monitored directory<br>
 * For some reason this constant is undocumented in {@link FileObserver}.
 */
public static final int DELETE_DIR = 0x40000200;

Both of these are successfully received when filtering for CREATE and DELETE.

Oquendo answered 25/5, 2016 at 15:56 Comment(2)
Are you able to DELETE and then trigger CREATE?Flyman
If you are speaking of deleting then recreating a subfolder of the currently observed folder, then yes, as far as I remember.Oquendo
R
1

Ther's an issue on that. Seems the doc is wrong https://code.google.com/p/android/issues/detail?id=33659

on this answer Android: FileObserver monitors only top directory someone published a recursive file observer that should work for you

Rescissory answered 16/12, 2013 at 9:12 Comment(2)
I beleive OP's problem is not about listening for changes in target directory and all sub directories recursively (this is what your links are about) but about the fact that he cannot get notifications for directories being created/deleted in his target directory.Norwich
From the code it was not very clear which was the observed directory. Probably you are rightRescissory

© 2022 - 2024 — McMap. All rights reserved.