【问题标题】:Can FileObserver on file be used to detect observed path renames?文件上的 FileObserver 可以用来检测观察到的路径重命名吗?
【发布时间】:2014-05-06 07:28:12
【问题描述】:

我正在使用 android FileObserver 来检测公共目录中文件的更改,包括重命名。一切正常,但重命名包含目录或其任何父目录不会触发正在观察的文件的 onEvent。我尝试将事件掩码设置为 ALL_EVENTS,但无济于事。实际上,可以重命名目录,这将有效地修改观察到的文件路径,但不会调度任何事件。这是它应该如何工作的吗?我能想到的唯一解决方案是将所有目录上的观察者添加到根目录,但这似乎有点奇怪。

代码如下:

    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)); 
    }

【问题讨论】:

    标签: android fileobserver


    【解决方案1】:

    如果您重命名观察到的文件,则有效。这是我的测试观察者:

        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");
                }
            }
        };
    

    这是 logcat 的输出:

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

    如您所见,收到了 2 个事件。第一个包含标志MOVE_SELFALL_EVENTS。第二个很奇怪,没有任何标志。

    如果重命名目录,事件在目录而不是子文件上触发似乎是合乎逻辑的。您需要将观察者附加到目录。

    编辑: 根据the docsFileObserver是使用Inotify实现的,根据wiki:

    Inotify 不支持递归监视目录,这意味着必须为每个子目录创建单独的 inotify 监视。

    【讨论】:

    • 是的,正如我提到的观察文件重命名的部分工作,但这不是问题。
    • 我已经编辑了几次答案。如果您阅读底部的最新更新,我认为这可以解决您的问题。
    最近更新 更多