Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FileObserver CREATE or DELETE received only for files

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.

like image 492
Yaroslav Mytkalyk Avatar asked Dec 08 '13 15:12

Yaroslav Mytkalyk


1 Answers

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;
        }
    }
}
like image 108
Eugene Loy Avatar answered Sep 19 '22 05:09

Eugene Loy