Android 文件管理系列 (03) – 监控文件变化

文件管理器有个关键问题是,当用户浏览某个目录时,有可能这个目录中发生了文件的 新建 / 删除 / 修改 等操作,因此需要及时的将这类变化的信息更新,在 Android 上则有两种办法实现:

  1. 继承并实现 android.os.FileObserver;
  2. 使用 org.apache.commons.io 提供的 FileAlterationMonitor, FileAlterationObserver 以及 FileAlterationListener.

系列

Android 文件管理系列 (00) – 存储系统概述
Android 文件管理系列 (01) – 获取挂载点和权限
Android 文件管理系列 (02) – FileProvider
Android 文件管理系列 (03) – 监控文件变化 [当前]

使用 FileObserver

继承 FileObserver 并实现 onEvent(int event, String path) 方法.
参数 path 为相对路径,如果需要绝对路径需要记录下正在监视的路径;
参数 event 为监视目录下发生的事件, 具体有以下值

public abstract class FileObserver {
    ...
    /** Event type: Data was read from a file */
    public static final int ACCESS = 0x00000001;
    /** Event type: Data was written to a file */
    public static final int MODIFY = 0x00000002;
    /** Event type: Metadata (permissions, owner, timestamp) was changed explicitly */
    public static final int ATTRIB = 0x00000004;
    /** Event type: Someone had a file or directory open for writing, and closed it */
    public static final int CLOSE_WRITE = 0x00000008;
    /** Event type: Someone had a file or directory open read-only, and closed it */
    public static final int CLOSE_NOWRITE = 0x00000010;
    /** Event type: A file or directory was opened */
    public static final int OPEN = 0x00000020;
    /** Event type: A file or subdirectory was moved from the monitored directory */
    public static final int MOVED_FROM = 0x00000040;
    /** Event type: A file or subdirectory was moved to the monitored directory */
    public static final int MOVED_TO = 0x00000080;
    /** Event type: A new file or subdirectory was created under the monitored directory */
    public static final int CREATE = 0x00000100;
    /** Event type: A file was deleted from the monitored directory */
    public static final int DELETE = 0x00000200;
    /** Event type: The monitored file or directory was deleted; monitoring effectively stops */
    public static final int DELETE_SELF = 0x00000400;
    /** Event type: The monitored file or directory was moved; monitoring continues */
    public static final int MOVE_SELF = 0x00000800;
    /** Event mask: All valid event types, combined */
    public static final int ALL_EVENTS = ACCESS | MODIFY | ATTRIB | CLOSE_WRITE
            | CLOSE_NOWRITE | OPEN | MOVED_FROM | MOVED_TO | DELETE | CREATE
            | DELETE_SELF | MOVE_SELF;
    ...
}

为了取出具体的值,需要用 event &= FileObserver.ALL_EVENTS; 来计算。
开始监视时使用 startWatching(), 结束时使用 stopWatching() 即可。
优点:

  • 由于使用了 Android 系统内部的方法,因此变化事件非常丰富。
    缺点:

  • 在部分系统(部分厂商的某些版本)中存在问题,无法正确被触发。

  • 无法监视子目录或多个目录,需要自己实现相关功能(可参考 OwnCloud 客户端中 RecursiveFileObserver 的实现)

使用 Apache Commons IO – FileAlterationMonitor

Commons IO 内部的实现其实就是遍历文件目录,然后以一定的时间间隔进行比较,从而获得变化信息,并通过 FileAlterationListener 反馈:

public interface FileAlterationListener {
    /**
     * File system observer started checking event.
     *
     * @param observer The file system observer
     */
    void onStart(final FileAlterationObserver observer);
    /**
     * Directory created Event.
     *
     * @param directory The directory created
     */
    void onDirectoryCreate(final File directory);
    /**
     * Directory changed Event.
     *
     * @param directory The directory changed
     */
    void onDirectoryChange(final File directory);
    /**
     * Directory deleted Event.
     *
     * @param directory The directory deleted
     */
    void onDirectoryDelete(final File directory);
    /**
     * File created Event.
     *
     * @param file The file created
     */
    void onFileCreate(final File file);
    /**
     * File changed Event.
     *
     * @param file The file changed
     */
    void onFileChange(final File file);
    /**
     * File deleted Event.
     *
     * @param file The file deleted
     */
    void onFileDelete(final File file);
    /**
     * File system observer finished checking event.
     *
     * @param observer The file system observer
     */
    void onStop(final FileAlterationObserver observer);
}

使用例子:
开始监视:

FileAlterationMonitor fileMonitor = new FileAlterationMonitor(interval);
fileMonitor.start();
FileAlterationObserver observer = new FileAlterationObserver(path, new SingleLevelFileFilter(new File(path)));
observer.initialize();
observer.addListener(new FileAlterationListener() {...});
fileMonitor.addObserver(observer);

停止:

fileMonitor.stop(5000);

优点:

  • 通用性较强,不受厂商具体系统底层实现影响
  • 可以便捷地监视多个目录或目录树
  • 通过 FileFilter 可以实现更精细的监视过滤配置

缺点:

  • 事件不如 FileObserver 详细
  • 需要正确设置 interval, 过于频繁会导致性能问题,而间隔过长则可能影响监视效果
  • 需要引入额外 package, 并且包含了大量的 method

发表评论

电子邮件地址不会被公开。 必填项已用*标注