Gerrit Beuze
Gerrit Beuze

Reputation: 921

Can FileObserver on file be used to detect observed path renames?

I'm using an android FileObserver to detect changes in a file in a public directory, including renames. All works OK, but renaming the containing directory or any of its parent directories does not trigger the onEvent for the file being observed. I have tried setting the event mask to ALL_EVENTS, but to no avail. In effect a directory can be renamed, which would effectively modifiy the observed file path, but no events are dispatched. Is this how it is supposed to work? The only solution I could think of is adding observers on all directories downto the root, but that seems a bit odd.

Here's the code:

    protected class ExternalFileObserver extends FileObserver {
    public ExternalFileObserver(String path) {
        super(path, ALL_EVENTS);
    }
    @Override
    public void onEvent(int event, String path) {
        Log.d("Files", String.format("Change %d for path %s", event, path)); 
    }

Upvotes: 1

Views: 2318

Answers (1)

Mister Smith
Mister Smith

Reputation: 28168

Works if you rename the observed file. Here's my test observer:

    final FileObserver fo = new FileObserver(f.getPath()) {

        @Override
        public void onEvent(int event, String path) {
            System.out.println(">>> Event: " + event + "; path: " + path);

            if((event & FileObserver.ACCESS) > 0){
                System.out.println(">>> ACCESS");
            }

            if((event & FileObserver.ALL_EVENTS) > 0){
                System.out.println(">>> ALL_EVENTS");
            }

            if((event & FileObserver.ATTRIB) > 0){
                System.out.println(">>> ATTRIB");
            }

            if((event & FileObserver.CLOSE_NOWRITE) > 0){
                System.out.println(">>> CLOSE_NOWRITE");
            }

            if((event & FileObserver.CLOSE_WRITE) > 0){
                System.out.println(">>> CLOSE_WRITE");
            }

            if((event & FileObserver.CREATE) > 0){
                System.out.println(">>> CREATE");
            }

            if((event & FileObserver.DELETE) > 0){
                System.out.println(">>> DELETE");
            }

            if((event & FileObserver.DELETE_SELF) > 0){
                System.out.println(">>> DELETE_SELF");
            }

            if((event & FileObserver.MODIFY) > 0){
                System.out.println(">>> MODIFY");
            }

            if((event & FileObserver.MOVE_SELF) > 0){
                System.out.println(">>> MOVE_SELF");
            }

            if((event & FileObserver.MOVED_FROM) > 0){
                System.out.println(">>> MOVED_FROM");
            }

            if((event & FileObserver.MOVED_TO) > 0){
                System.out.println(">>> MOVED_TO");
            }

            if((event & FileObserver.OPEN) > 0){
                System.out.println(">>> OPEN");
            }
        }
    };

And here is the logcat output:

    >>> Event: 2048; path: null
    >>> ALL_EVENTS
    >>> MOVE_SELF
    >>> Event: 32768; path: null

As you can see, 2 events were received. The first one contains the flags MOVE_SELF and also ALL_EVENTS. The second one is very odd and does not contain any flag.

If you rename the directory, seems logical that the event is fired on the directory and not on the child files. You need to attach the observer to the directory.

EDIT: According to the docs, FileObserver is implemented using Inotify, and according to the wiki:

Inotify does not support recursively watching directories, meaning that a separate inotify watch must be created for every subdirectory.

Upvotes: 0

Related Questions