android中的FileObserver文件监控

来源:互联网 发布:温州网络学堂登不了 编辑:程序博客网 时间:2024/06/10 01:06
android.os.FileObserver
Monitors files (using inotify) to fire an event after files are accessed or changed by by any process on the device (including this one). FileObserver is an abstract class; subclasses must implement the event handler onEvent(int, String).
Each FileObserver instance monitors a single file or directory. If a directory is monitored, events will be triggered for all files and subdirectories inside the monitored directory.
An event mask is used to specify which changes or actions to report. Event type constants are used to describe the possible changes in the event mask as well as what actually happened in event callbacks.


FileObserver类是一个用于监听文件访问、创建、修改、删除、移动等操作的监听器,基于linux的inotify。 
FileObserver 是个抽象类,必须继承它才能使用。每个FileObserver对象监听一个单独的文件或者文件夹,如果监视的是一个文件夹,
那么文件夹下所有的文件和级联子目录的改变都会触发监听的事件。

其实不然,经过测试并不支持递归,对于监听目录的子目录中的文件改动,FileObserver 对象是无法收到事件回调的,不仅这样,
监听目录的子目录本身的变动也收不到事件回调。原因是由 linux 的 inotify 机制本身决定的,基于 inotify 实现的 FileObserver 自然也不支持递归监听。

1、概述用法

FileObserver 是个抽象类,必须继承它才能使用

可以监听的事件类型:
ACCESS : 即文件被访问
MODIFY : 文件被修改
ATTRIB : 文件属性被修改,如 chmod、chown、touch 等
CLOSE_WRITE : 可写文件被 close
CLOSE_NOWRITE : 不可写文件被 close
OPEN : 文件被 open
MOVED_FROM : 文件被移走,如 mv
MOVED_TO : 文件被移来,如 mv、cp
CREATE : 创建新文件
DELETE : 文件被删除,如 rm
DELETE_SELF : 自删除,即一个可执行文件在执行时删除自己
MOVE_SELF : 自移动,即一个可执行文件在执行时移动自己
CLOSE : 文件被关闭,等同于(IN_CLOSE_WRITE | IN_CLOSE_NOWRITE)
ALL_EVENTS : 包括上面的所有事件

可以SDK DEVELOP上有更详细的介绍

class MyFileObserver extends FileObserver {          // 这种构造方法是默认监听所有事件的,如果使用super(String,int)这种构造方法,则int参数是要监听的事件类型。          // 为了防止嵌套消息调用,建议使用 super(String,int) 按需创建监控消息值          public MyFileObserver(String path) {              super(path, FileObserver.CLOSE_WRITE | FileObserver.CREATE | FileObserver.DELETE                      | FileObserver.DELETE_SELF );              //super(path,FileObserver.ALL_EVENTS);          }            @Override          public void onEvent(int event, String path) {               switch (event)                {                case FileObserver.ACCESS:                        Log.i("MyFileObserver", "ACCESS: " + path);                        break;                case FileObserver.ATTRIB:                        Log.i("MyFileObserver", "ATTRIB: " + path);                        break;                case FileObserver.CLOSE_NOWRITE:                        Log.i("MyFileObserver", "CLOSE_NOWRITE: " + path);                        break;                case FileObserver.CLOSE_WRITE:                        Log.i("MyFileObserver", "CLOSE_WRITE: " + path);                        break;                case FileObserver.CREATE:                        Log.i("MyFileObserver", "CREATE: " + path);                        break;                case FileObserver.DELETE:                        Log.i("MyFileObserver", "DELETE: " + path);                        break;                case FileObserver.DELETE_SELF:                        Log.i("MyFileObserver", "DELETE_SELF: " + path);                        break;                case FileObserver.MODIFY:                        Log.i("MyFileObserver", "MODIFY: " + path);                        break;                case FileObserver.MOVE_SELF:                        Log.i("MyFileObserver", "MOVE_SELF: " + path);                        break;                case FileObserver.MOVED_FROM:                        Log.i("MyFileObserver", "MOVED_FROM: " + path);                        break;                case FileObserver.MOVED_TO:                        Log.i("MyFileObserver", "MOVED_TO: " + path);                        break;                case FileObserver.OPEN:                        Log.i("MyFileObserver", "OPEN: " + path);                        break;                default:                        Log.i("MyFileObserver", "DEFAULT(" + event + "): " + path);                        break;                }        }      };

2、给目录设置监听器

MyFileObserver listener = new MyFileObserver(Environment.getExternalStorageDirectory().getPath());//开始监听     listener.startWatching();     /*   * 在这里做一些操作,比如创建目录什么的   */     //停止监听  listener.stopWatching(); 

3、对于递归监听的实现代码


为了监听整个文件系统的变化,必须得实现这个递归监听,对每个子目录递归的调用 inotify,也就是说在 Android 中,也得通过遍历目录树,建立一系列 
FileObserver 对象来实现这个功能,这样做对系统的效率影响极大,但是实在没有找到好的方法,这里只是提供一种思路。

package com.rising.filemonitor;import java.io.File;import java.util.ArrayList;import java.util.List;import java.util.Stack;import android.os.FileObserver;import android.util.Log;/** * Enhanced FileObserver to support recursive directory monitoring basically. * @author              uestc.Mobius <mobius@toraleap.com> * @version     2011.0121 */public class RecursiveFileObserver extends FileObserver {        /** Only modification events */        public static int CHANGES_ONLY = CREATE | DELETE | CLOSE_WRITE | MOVE_SELF | MOVED_FROM | MOVED_TO;                List<SingleFileObserver> mObservers;        String mPath;        int mMask;        public RecursiveFileObserver(String path) {                this(path, ALL_EVENTS);        }                public RecursiveFileObserver(String path, int mask) {                super(path, mask);                mPath = path;                mMask = mask;        }        @Override        public void startWatching() {                if (mObservers != null) return;                                mObservers = new ArrayList<SingleFileObserver>();                Stack<String> stack = new Stack<String>();                stack.push(mPath);                                while (!stack.isEmpty()) {                        String parent = stack.pop();                        mObservers.add(new SingleFileObserver(parent, mMask));                        File path = new File(parent);                        File[] files = path.listFiles();                        if (null == files) continue;                        for (File f : files)                        {                                if (f.isDirectory() && !f.getName().equals(".") && !f.getName().equals("..")) {                                        stack.push(f.getPath());                                }                        }                }                                for (SingleFileObserver sfo : mObservers) {                        sfo.startWatching();                }        }        @Override        public void stopWatching() {                if (mObservers == null) return;                                for (SingleFileObserver sfo : mObservers) {                        sfo.stopWatching();                }                mObservers.clear();                mObservers = null;        }        @Override        public void onEvent(int event, String path) {                switch (event)                {                case FileObserver.ACCESS:                        Log.i("RecursiveFileObserver", "ACCESS: " + path);                        break;                case FileObserver.ATTRIB:                        Log.i("RecursiveFileObserver", "ATTRIB: " + path);                        break;                case FileObserver.CLOSE_NOWRITE:                        Log.i("RecursiveFileObserver", "CLOSE_NOWRITE: " + path);                        break;                case FileObserver.CLOSE_WRITE:                        Log.i("RecursiveFileObserver", "CLOSE_WRITE: " + path);                        break;                case FileObserver.CREATE:                        Log.i("RecursiveFileObserver", "CREATE: " + path);                        break;                case FileObserver.DELETE:                        Log.i("RecursiveFileObserver", "DELETE: " + path);                        break;                case FileObserver.DELETE_SELF:                        Log.i("RecursiveFileObserver", "DELETE_SELF: " + path);                        break;                case FileObserver.MODIFY:                        Log.i("RecursiveFileObserver", "MODIFY: " + path);                        break;                case FileObserver.MOVE_SELF:                        Log.i("RecursiveFileObserver", "MOVE_SELF: " + path);                        break;                case FileObserver.MOVED_FROM:                        Log.i("RecursiveFileObserver", "MOVED_FROM: " + path);                        break;                case FileObserver.MOVED_TO:                        Log.i("RecursiveFileObserver", "MOVED_TO: " + path);                        break;                case FileObserver.OPEN:                        Log.i("RecursiveFileObserver", "OPEN: " + path);                        break;                default:                        Log.i("RecursiveFileObserver", "DEFAULT(" + event + "): " + path);                        break;                }        }                /**         * Monitor single directory and dispatch all events to its parent, with full path.         * @author              uestc.Mobius <mobius@toraleap.com>         * @version     2011.0121         */        class SingleFileObserver extends FileObserver {                String mPath;                                public SingleFileObserver(String path) {                        this(path, ALL_EVENTS);                        mPath = path;                }                                public SingleFileObserver(String path, int mask) {                        super(path, mask);                        mPath = path;                }                @Override                public void onEvent(int event, String path) {                        String newPath = mPath + "/" + path;                        RecursiveFileObserver.this.onEvent(event, newPath);                }        }}


0 0