ConversationsFileObserver.java

 1package eu.siacs.conversations.utils;
 2
 3
 4import android.os.FileObserver;
 5
 6import java.io.File;
 7import java.util.ArrayList;
 8import java.util.List;
 9import java.util.Stack;
10
11/**
12 * Copyright (C) 2012 Bartek Przybylski
13 * Copyright (C) 2015 ownCloud Inc.
14 * Copyright (C) 2016 Daniel Gultsch
15 */
16
17public abstract class ConversationsFileObserver {
18
19    private final String path;
20    private final List<SingleFileObserver> mObservers = new ArrayList<>();
21
22    public ConversationsFileObserver(String path) {
23        this.path = path;
24    }
25
26    public synchronized void startWatching() {
27        Stack<String> stack = new Stack<>();
28        stack.push(path);
29
30        while (!stack.empty()) {
31            String parent = stack.pop();
32            mObservers.add(new SingleFileObserver(parent, FileObserver.DELETE| FileObserver.MOVED_FROM));
33            final File path = new File(parent);
34            final File[] files = path.listFiles();
35            if (files == null) {
36                continue;
37            }
38            for(File file : files) {
39                if (file.isDirectory() && file.getName().charAt(0) != '.') {
40                    final String currentPath = file.getAbsolutePath();
41                    if (depth(file) <= 8 && !stack.contains(currentPath) && !observing(currentPath)) {
42                        stack.push(currentPath);
43                    }
44                }
45            }
46        }
47        for(FileObserver observer : mObservers) {
48            observer.startWatching();
49        }
50    }
51
52    private static int depth(File file) {
53        int depth = 0;
54        while((file = file.getParentFile()) != null) {
55            depth++;
56        }
57        return depth;
58    }
59
60    private boolean observing(String path) {
61        for(SingleFileObserver observer : mObservers) {
62            if(path.equals(observer.path)) {
63                return true;
64            }
65        }
66        return false;
67    }
68
69    public synchronized void stopWatching() {
70        for(FileObserver observer : mObservers) {
71            observer.stopWatching();
72        }
73        mObservers.clear();
74    }
75
76    abstract public void onEvent(int event, String path);
77
78    public void restartWatching() {
79        stopWatching();
80        startWatching();
81    }
82
83    private class SingleFileObserver extends FileObserver {
84        private final String path;
85
86        public SingleFileObserver(String path, int mask) {
87            super(path, mask);
88            this.path = path;
89        }
90
91        @Override
92        public void onEvent(int event, String filename) {
93            ConversationsFileObserver.this.onEvent(event, path+'/'+filename);
94        }
95
96    }
97}