Android--文件监控FileObserver

来源:互联网 发布:域名一般多少钱 编辑:程序博客网 时间:2024/06/03 16:00

在Android系统中封装了一个FileObserver类,该类是基于Linux的Inotify机制实现的。

FileObserver是一个抽象类,必须定义一个子类继承FileObserver,并且实现该类的onEvent抽象方法,当被监控的文件或目录发生变更事件时,将回调FileObserver的onEvent()方法来处理文件或目录的变更事件。

事件类型

FileObserver类到底定义了监控文件或目录的哪些变更事件呢?在FileObserver类(frameworks\base\core\java\android\os\FileObserver.java)中给出了定义,如下:
    /** 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;
从上面代码中我们可以看出具体定义了哪些变更事件。

事件监控过程


在FileObserver类中定义了一个静态内部类ObserverThread,该线程类才是真正实现文件或目录的监控过程。各种类型的FileObserver都拥有一个ObserverThread实例。
    private static ObserverThread s_observerThread;    static {        s_observerThread = new ObserverThread();        s_observerThread.start();//静态创建并启动一个文件监控线程    }
FileObserver类通过静态方法创建一个ObserverThread对象。
    private static class ObserverThread extends Thread {        private HashMap<Integer, WeakReference> m_observers = new HashMap<Integer, WeakReference>();        private int m_fd;        public ObserverThread() {            super("FileObserver");            m_fd = init();<span style="font-family: Arial, Helvetica, sans-serif;">//初始化一个inotify实例,Observer线程就是对该inotify实例进行监控</span>        }        public void run() {            observe(m_fd);        }        public int startWatching(String path, int mask, FileObserver observer) {            int wfd = startWatching(m_fd, path, mask);//<span style="font-family: Arial, Helvetica, sans-serif;">在Inotify实例中添加一个watch对象,并得到一个watch对象句柄  </span>            Integer i = new Integer(wfd);            if (wfd >= 0) {                synchronized (m_observers) {                    m_observers.put(i, new WeakReference(observer));<span style="font-family: Arial, Helvetica, sans-serif;">//将watch对象句柄和响应该watch事件的FileObserver以键值对的形式保存在m_observers成员变量中  </span>                }            }            return i;        }        public void stopWatching(int descriptor) {            stopWatching(m_fd, descriptor);        }        public void onEvent(int wfd, int mask, String path) {            // look up our observer, fixing up the map if necessary...            FileObserver observer = null;            synchronized (m_observers) {                WeakReference weak = m_observers.get(wfd);//根据wfd句柄从m_observers中取出FileObserver对象                if (weak != null) {  // can happen with lots of events from a dead wfd                    observer = (FileObserver) weak.get();                    if (observer == null) {                        m_observers.remove(wfd);                    }                }            }            // ...then call out to the observer without the sync lock held            if (observer != null) {                try {                    observer.onEvent(mask, path);//调用对应的FileObserver对象的onEvent方法处理事件                } catch (Throwable throwable) {                    Log.wtf(LOG_TAG, "Unhandled exception in FileObserver " + observer, throwable);                }            }        }        private native int init();        private native void observe(int fd);        private native int startWatching(int fd, String path, int mask);        private native void stopWatching(int fd, int wfd);    }
在上面的ObserverThread的构造方法中调用native方法init(),我们进入jni层(frameworks\base\core\jni\android_util_FileObserver.cpp)看下函数具体实现,如下:
static jint android_os_fileobserver_init(JNIEnv* env, jobject object){#ifdef HAVE_INOTIFY    return (jint)inotify_init(); //初始化一个inotify实例#else // HAVE_INOTIFY    return -1;#endif // HAVE_INOTIFY}
inotify_init()函数使用到了Linux的Inotify机制,这里不做详细介绍。
在FileObserver类中静态创建ObserverThread对象后,开启该线程对象,即调用native方法observe(),如下:
static void android_os_fileobserver_observe(JNIEnv* env, jobject object, jint fd){#ifdef HAVE_INOTIFY     char event_buf[512];//定义事件数组    struct inotify_event* event;             while (1)    {        int event_pos = 0;        int num_bytes = read(fd, event_buf, sizeof(event_buf));//从inotify实例句柄中读取事件                if (num_bytes < (int)sizeof(*event))        {            if (errno == EINTR)                continue;            ALOGE("***** ERROR! android_os_fileobserver_observe() got a short event!");            return;        }                while (num_bytes >= (int)sizeof(*event))//循环处理读取到的事件        {            int event_size;            event = (struct inotify_event *)(event_buf + event_pos);            jstring path = NULL;                        if (event->len > 0)//len表示name字符串的长度            {                path = env->NewStringUTF(event->name);//name表示被监视目标的路径名            }            env->CallVoidMethod(object, method_onEvent, event->wd, event->mask, path);//调用ObserverThread对象的onEvent方法通知上层            if (env->ExceptionCheck()) {                env->ExceptionDescribe();                env->ExceptionClear();            }            if (path != NULL)            {                env->DeleteLocalRef(path);            }            event_size = sizeof(*event) + event->len;            num_bytes -= event_size;            event_pos += event_size;        }    }    #endif // HAVE_INOTIFY}
ObserverThread线程循环从inotify实例句柄中读取事件,然后回调ObserverThread的onEvent方法来处理事件。

注册监控watch


调用FileObserver对象的startWatching()方法来启动文件监控。
    /**     * Start watching for events.  The monitored file or directory must exist at     * this time, or else no events will be reported (even if it appears later).     * If monitoring is already started, this call has no effect.     */    public void startWatching() {        if (m_descriptor < 0) {            m_descriptor = s_observerThread.startWatching(m_path, m_mask, this);        }    }
这里会调用ObserverThread对象的startWatching()方法,该方法会在Inotify对象中添加一个watch对象,并将该对象的句柄和对应的FileObserver对象以键值对的形式保存。

注销监控watch


调用FileObserver对象的stopWatching()方法来停止文件监控。
    /**     * Stop watching for events.  Some events may be in process, so events     * may continue to be reported even after this method completes.  If     * monitoring is already stopped, this call has no effect.     */    public void stopWatching() {        if (m_descriptor >= 0) {            s_observerThread.stopWatching(m_descriptor);            m_descriptor = -1;        }    }
这里会调用ObserverThread对象的stopWatching()方法,接着调用native层的stopWatching()函数,如下:
static void android_os_fileobserver_stopWatching(JNIEnv* env, jobject object, jint fd, jint wfd){#ifdef HAVE_INOTIFY    inotify_rm_watch((int)fd, (uint32_t)wfd);#endif // HAVE_INOTIFY}

0 0
原创粉丝点击