您的位置:首页 > 移动开发 > Android开发

Android文件监控FileObserver介绍

2016-07-07 09:55 986 查看

转载地址:http://blog.csdn.net/yangwen123/article/details/36379763

在前面的Linux文件系统Inotify机制 中介绍了Linux对文件变更监控过程。Android系统在此基础上封装了一个FileObserver类来方便使用Inotify机制。FileObserver是一个抽象类,需要定义子类实现该类的onEvent抽象方法,当被监控的文件或者目录发生变更事件时,将回调FileObserver的onEvent()函数来处理文件或目录的变更事件。

事件监控过程

在FileObserver类中定义了一个静态内部类ObserverThread,该线程类才是真正实现文件或目录监控过程。各种类型的FileObserver都拥有一个ObserverThread实例:

frameworks\base\core\Java\android\os\FileObserver.java

[java] view
plain copy

public abstract class FileObserver {  

    //可监控的事件类型  

    public static final int ALL_EVENTS = ACCESS | MODIFY | ATTRIB | CLOSE_WRITE  

            | CLOSE_NOWRITE | OPEN | MOVED_FROM | MOVED_TO | DELETE | CREATE | DELETE_SELF | MOVE_SELF;  

    //静态创建并启动一个文件监控线程  

    private static ObserverThread s_observerThread;  

    static {  

        s_observerThread = new ObserverThread();  

        s_observerThread.start();  

    }  

    // instance  

    private String m_path;  

    private Integer m_descriptor;  

    private int m_mask;  

}  

FileObserver类通过静态方式构造了一个ObserverThread对象:

[java] view
plain copy

public ObserverThread() {  

    super("FileObserver");  

    m_fd = init();//初始化一个inotify实例,Observer线程就是对该inotify实例进行监控  

}  

frameworks\base\core\jni\android_util_FileObserver.cpp

[java] view
plain copy

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机制 有详细介绍,然后启动ObserverThread线程,ObserverThread线程运行体:

frameworks\base\core\java\android\os\FileObserve$ObserverThread

[java] view
plain copy

public void run() {  

    observe(m_fd);//监控inotify实例句柄  

}  

frameworks\base\core\jni\android_util_FileObserver.cpp

[cpp] view
plain copy

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;  

        //从inotify实例句柄中读取事件  

        int num_bytes = read(fd, event_buf, sizeof(event_buf));  

        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)  

            {  

                path = env->NewStringUTF(event->name);  

            }  

            //调用ObserverThread的onEvent函数通知上层响应  

            env->CallVoidMethod(object, method_onEvent, event->wd, event->mask, path);  

            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函数来处理事件。

frameworks\base\core\java\android\os\FileObserve$ObserverThread

[java] view
plain copy

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) {  

        //根据wfd句柄从m_observers表中查找出注册的FileObserver对象  

        WeakReference weak = m_observers.get(wfd);  

        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 {  

            //调用对应的FileObserver对象的onEvent函数来处理事件  

            observer.onEvent(mask, path);  

        } catch (Throwable throwable) {  

            Log.wtf(LOG_TAG, "Unhandled exception in FileObserver " + observer, throwable);  

        }  

    }  

}  

注册监控watch

FileObserver类提供了startWatching()函数来启动文件监控

frameworks\base\core\java\android\os\FileObserver.java

[java] view
plain copy

public void startWatching() {  

    if (m_descriptor < 0) {  

        m_descriptor = s_observerThread.startWatching(m_path, m_mask, this);  

    }  

}  

由ObserverThread线程对象启动监控

frameworks\base\core\java\android\os\FileObserver$ObserverThread

[java] view
plain copy

public int startWatching(String path, int mask, FileObserver observer) {  

    //在Inotify实例中添加一个watch对象,并得到一个watch对象句柄  

    int wfd = startWatching(m_fd, path, mask);  

    Integer i = new Integer(wfd);  

    if (wfd >= 0) {  

        //将watch对象句柄和响应该watch事件的FileObserver以键值对的形式保存在m_observers成员变量中  

        synchronized (m_observers) {  

            m_observers.put(i, new WeakReference(observer));  

        }  

    }  

    return i;  

}  

ObserverThread又调用native方法android_os_fileobserver_startWatching()来添加一个watch

frameworks\base\core\jni\android_util_FileObserver.cpp

[java] view
plain copy

static jint android_os_fileobserver_startWatching(JNIEnv* env, jobject object, jint fd, jstring pathString, jint mask)  

{  

    int res = -1;  

#ifdef HAVE_INOTIFY  

    if (fd >= 0)  

    {  

        const char* path = env->GetStringUTFChars(pathString, NULL);  

        //在Inotify实例上添加一个watch对象  

        res = inotify_add_watch(fd, path, mask);  

        env->ReleaseStringUTFChars(pathString, path);  

    }  

#endif // HAVE_INOTIFY  

    return res;  

}  

注销监控watch

FileObserver类提供了使用stopWatching()函数来停止文件监控。

frameworks\base\core\java\android\os\FileObserver$ObserverThread

[java] view
plain copy

public void stopWatching() {  

    if (m_descriptor >= 0) {  

        s_observerThread.stopWatching(m_descriptor);  

        m_descriptor = -1;  

    }  

}  

frameworks\base\core\java\android\os\FileObserve$ObserverThread

[cpp] view
plain copy

public void stopWatching(int descriptor) {  

    stopWatching(m_fd, descriptor);  

}  

frameworks\base\core\jni\android_util_FileObserver.cpp

[cpp] view
plain copy

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  

}  

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: