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
- Android--文件监控FileObserver
- android中的FileObserver文件监控
- Android文件监控FileObserver介绍
- Android文件监控FileObserver介绍
- Inotify与Android文件监控FileObserver原理
- Inotify与Android文件监控FileObserver原理
- Android使用FileObserver对sdcard文件或文件夹监控
- Android使用FileObserver对sdcard文件或文件夹监控
- Android使用FileObserver对sdcard文件或文件夹监控
- Android使用FileObserver对sdcard文件或文件夹监控
- Android使用FileObserver对sdcard文件或文件夹监控
- Android 智能文件观察者 FileObserver
- Android FileObserver对文件或文件夹监听
- Android FileObserver
- Android FileObserver
- Android FileObserver
- Android FileObserver
- android FileObserver
- Win7*64+androidstudio ndk-build.cmd finished with non-zero exit value 1 问题原因
- 工程文件目录及程序的启动原理
- 慕课玩儿转swift笔记02-字符串
- 生成5位序列号
- HDU1276士兵队列
- Android--文件监控FileObserver
- 用指针正确的操纵动态数组与正确用delete释放内存的方法
- java 子类重写父类的方法应注意的问题
- poj 1324 Holedox Moving(bfs+状态压缩)
- 黑马程序员------异常小结
- 费用流 csu1506 Double Shortest Paths
- pat(A) 2-06. 数列求和(模拟摆竖式相加)
- NYOJ 2 括号配对问题 (栈 stack)
- 黑马程序员------Foundatin之求单个文件的代码行数