美文网首页RxJava精选案例
FileObserver递归监听目录(解决无法监听目录的创建、删

FileObserver递归监听目录(解决无法监听目录的创建、删

作者: 知用改创 | 来源:发表于2017-04-13 11:39 被阅读294次

    FileObserver递归监听目录(解决无法监听目录的创建、删除问题)

    主要内容

    为了解决Android媒体数据库更新不及时的问题,我想打算通过FileObserver监听SD卡根目录下所有文件的变化,然后根据文件的变化对Android媒体数据库进行更新。而FileObserver无法做到递归监听。通过参考FileObserver 研究及其递归监听初步实现这篇博客,在其基础上,主要解决了几个问题:

    1. 无法监听目录的创建、删除
    2. 开启监听之后,新创建的目录无法监听
    3. 冗余注册监听的问题

    冗余注册监听我是通过用ArrayMap键值对来解决的,以监听目录的绝对路径作为key,以监听器作为value。(也可以使用ArraySet集合实现)而开启监听之后,新创建的目录无法监听的问题则是通过监听FileObserver.CREATE事件,当创建新目录且该目录还没注册监听时,就注册并启动监听。
    接下来,干货来了,代码如下:

    public class RecursiveFileObserver extends FileObserver
    {
        Map<String, 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 ArrayMap<>();
            Stack stack = new Stack();
            stack.push(mPath);
    
            while (!stack.isEmpty())
            {
                String temp = (String) stack.pop();
                mObservers.put(temp, new SingleFileObserver(temp, mMask));
                File path = new File(temp);
                File[] files = path.listFiles();
                if (null == files)
                    continue;
                for (File f: files)
                {
                    // 递归监听目录
                    if (f.isDirectory() && !f.getName().equals(".") && !f.getName()
                            .equals(".."))
                    {
                        stack.push(f.getAbsolutePath());
                    }
                }
            }
            Iterator<String> iterator = mObservers.keySet().iterator();
            while (iterator.hasNext()) {
                String key = iterator.next();
                mObservers.get(key).startWatching();
            }
        }
    
        @Override public void stopWatching()
        {
            if (mObservers == null)
                return ;
    
            Iterator<String> iterator = mObservers.keySet().iterator();
            while (iterator.hasNext()) {
                String key = iterator.next();
                mObservers.get(key).stopWatching();
            }
            mObservers.clear();
            mObservers = null;
        }
    
        @Override public void onEvent(int event, String path)
        {
            int el = event & FileObserver.ALL_EVENTS;
            switch (el)
            {
                case FileObserver.ATTRIB:
                    Log.i("RecursiveFileObserver", "ATTRIB: " + path);
                    break;
                case FileObserver.CREATE:
                    File file = new File(path);
                    if(file.isDirectory()) {
                        Stack stack = new Stack();
                        stack.push(path);
                        while (!stack.isEmpty())
                        {
                            String temp = (String) stack.pop();
                            if(mObservers.containsKey(temp)) {
                                continue;
                            } else {
                                SingleFileObserver sfo = new SingleFileObserver(temp, mMask);
                                sfo.startWatching();
                                mObservers.put(temp, sfo);
                            }
                            File tempPath = new File(temp);
                            File[] files = tempPath.listFiles();
                            if (null == files)
                                continue;
                            for (File f: files)
                            {
                                // 递归监听目录
                                if (f.isDirectory() && !f.getName().equals(".") && !f.getName()
                                        .equals(".."))
                                {
                                    stack.push(f.getAbsolutePath());
                                }
                            }
                        }
                    }
                    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;
            }
    
    
        }
    
        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)
            {
                if(path != null) {
                    String newPath = mPath + "/" + path;
                    RecursiveFileObserver.this.onEvent(event, newPath);
                }
            }
        }
    }
    

    总结

    这算是一个比较好的递归监听解决方案,当然还可以进行优化,比如监听目录的删除事件,并取消该目录的监听。最后,吐槽一下,博客就是个人感想和收获的总结,到处抄来抄去没什么意思。看完别人的博客之后,我们应该写出自己的见解,提出更好的解决方案,而不是收藏、转载和抄袭。最后,借鉴别人的东西,请注明出处。

    相关文章

      网友评论

      • 草蜢的逆袭:不错,问一个问题哈,app运行的过程中,目录的删除,可以监听到吗?我们遇到这个问题,目录无法创建,有的手机甚至是要重启
        知用改创:@syusikoku 可以监听到。除此之外,你还可以通过监听开机广播来启动服务,然后在服务中启动FileObserver监听。

      本文标题:FileObserver递归监听目录(解决无法监听目录的创建、删

      本文链接:https://www.haomeiwen.com/subject/brlbattx.html