Loading app/src/main/java/foundation/e/drive/EdriveApplication.java +29 −0 Original line number Diff line number Diff line Loading @@ -13,8 +13,11 @@ import android.accounts.AccountManager; import android.app.Application; import android.content.Context; import android.content.SharedPreferences; import android.os.Environment; import android.util.Log; import foundation.e.drive.FileObservers.FileEventListener; import foundation.e.drive.FileObservers.RecursiveFileObserver; import foundation.e.drive.utils.AppConstants; import foundation.e.drive.utils.CommonUtils; Loading @@ -25,6 +28,8 @@ import foundation.e.drive.utils.CommonUtils; public class EdriveApplication extends Application { private static final String TAG = "EdriveApplication"; private RecursiveFileObserver mFileObserver = null; @Override public void onCreate() { Loading @@ -33,9 +38,14 @@ public class EdriveApplication extends Application { Log.i(TAG, "Starting"); resetOperationManagerSetting(); final String pathForObserver = Environment.getExternalStorageDirectory().getAbsolutePath(); mFileObserver = new RecursiveFileObserver(getApplicationContext(), pathForObserver, new FileEventListener()); SharedPreferences prefs = getSharedPreferences(AppConstants.SHARED_PREFERENCE_NAME, Context.MODE_PRIVATE); if (prefs.getString(AccountManager.KEY_ACCOUNT_NAME, null) != null) { Log.d(TAG, "Account already registered"); startRecursiveFileObserver(); } else { Account mAccount = CommonUtils.getAccount(getString(R.string.eelo_account_type), AccountManager.get(this)); if (mAccount != null) { Loading @@ -56,6 +66,25 @@ public class EdriveApplication extends Application { .apply(); } /** * Start Recursive FileObserver if not already watching */ public void startRecursiveFileObserver(){ if (!mFileObserver.isWatching()) { mFileObserver.startWatching(); Log.d(TAG, "Starting RecursiveFileObserver on media's root folder"); } else { Log.w(TAG, "RecursiveFileObserver (for media's root folder) was already running"); } } public void stopRecursiveFileObserver(){ mFileObserver.stopWatching(); Log.d(TAG, "RecursiveFileObserver on media's root folder stops watching "); } @Override public void onLowMemory() { super.onLowMemory(); Loading app/src/main/java/foundation/e/drive/FileObservers/FileEventListener.java 0 → 100644 +30 −0 Original line number Diff line number Diff line /* * Copyright © Narinder Rana (/e/ foundation). * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/gpl.html */ package foundation.e.drive.FileObservers; import android.os.FileObserver; import android.util.Log; import java.io.File; /** * @author Narinder Rana * @author vincent Bourgmayer */ public class FileEventListener { private final static String TAG = FileEventListener.class.getSimpleName(); public void onEvent(int event, File file) { if (event == FileObserver.CLOSE_WRITE) { //Event triggered after modification/creation Log.d(TAG, "CLOSE_WRITE event for :" + file.getName()); } else if (event == FileObserver.DELETE) { Log.d(TAG, "DELETE event for :" + file.getName()); } } } app/src/main/java/foundation/e/drive/FileObservers/RecursiveFileObserver.java 0 → 100644 +174 −0 Original line number Diff line number Diff line /* * Copyright © Narinder Rana (/e/ foundation). * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/gpl.html */ package foundation.e.drive.FileObservers; import android.content.Context; import android.os.FileObserver; import java.io.File; import java.io.FileFilter; import java.util.HashMap; import java.util.List; import java.util.Stack; import foundation.e.drive.database.DbHelper; import foundation.e.drive.models.SyncedFolder; /** * @author Narinder Rana * @author Vincent Bourgmayer */ public class RecursiveFileObserver extends FileObserver { private final HashMap<String, FileObserver> observers = new HashMap<>(); private static final FileFilter WATCHABLE_DIRECTORIES_FILTER = new FileFilter() { @Override public boolean accept(File file) { return file.isDirectory() && !file.getName().startsWith("."); } }; private boolean watching = false; private final Context applicationContext; private String path; private int mask; private FileEventListener listener; public RecursiveFileObserver(Context applicationContext, String path, FileEventListener listener) { this(applicationContext, path, ALL_EVENTS, listener); } public RecursiveFileObserver(Context applicationContext, String path, int mask, FileEventListener listener) { super(path, mask); this.path = path; this.mask = mask | FileObserver.CREATE | FileObserver.DELETE_SELF; this.listener = listener; this.applicationContext = applicationContext; } @Override public void onEvent(int event, String path) { File file; if (path == null) { file = new File(this.path); } else { file = new File(this.path, path); } notify(event, file); } private void notify(int event, File file) { if (listener != null) { listener.onEvent(event & FileObserver.ALL_EVENTS, file); } } @Override public void startWatching() { Stack<String> stack = new Stack<>(); List<SyncedFolder> mSyncedFolders = DbHelper.getAllSyncedFolders(applicationContext); if (!mSyncedFolders.isEmpty()){ for (SyncedFolder syncedFolder:mSyncedFolders){ stack.push(syncedFolder.getLocalFolder()); stack.push(syncedFolder.getRemoteFolder()); } watching = true; } // Recursively watch all child directories while (!stack.empty()) { String parent = stack.pop(); startWatching(parent); File path = new File(parent); File[] files = path.listFiles(WATCHABLE_DIRECTORIES_FILTER); if (files != null) { for (File file : files) { stack.push(file.getAbsolutePath()); } } } } /** * Start watching a single file * @param path */ private void startWatching(String path) { synchronized (observers) { FileObserver observer = observers.remove(path); if (observer != null) { observer.stopWatching(); } observer = new SingleFileObserver(path, mask); observer.startWatching(); observers.put(path, observer); } } @Override public void stopWatching() { for (FileObserver observer : observers.values()) { observer.stopWatching(); } observers.clear(); watching = false; } /** * Stop watching a single file * @param path */ private void stopWatching(String path) { synchronized (observers) { FileObserver observer = observers.remove(path); if (observer != null) { observer.stopWatching(); } } } public boolean isWatching(){ return watching; } private class SingleFileObserver extends FileObserver { private String filePath; public SingleFileObserver(String path, int mask) { super(path, mask); filePath = path; } @Override public void onEvent(int event, String path) { File file; if (path == null) { file = new File(filePath); } else { file = new File(filePath, path); } switch (event & FileObserver.ALL_EVENTS) { case DELETE_SELF: RecursiveFileObserver.this.stopWatching(filePath); break; case CREATE: if (WATCHABLE_DIRECTORIES_FILTER.accept(file)) { RecursiveFileObserver.this.startWatching(file.getAbsolutePath()); } break; } RecursiveFileObserver.this.notify(event, file); } } } app/src/main/java/foundation/e/drive/models/FileObserver.java 0 → 100644 +33 −0 Original line number Diff line number Diff line /* * Copyright © Narinder Rana (/e/ foundation). * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/gpl.html */ package foundation.e.drive.models; import java.io.File; import java.io.Serializable; import java.util.List; /** * @author Narinder Rana */ public class FileObserver implements Serializable { private List<File> files; public FileObserver(List<File> files) { this.files = files; } public List<File> getFiles() { return files; } public void setFiles(List<File> files) { this.files = files; } } app/src/main/java/foundation/e/drive/services/InitializerService.java +2 −1 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import foundation.e.drive.EdriveApplication; import foundation.e.drive.models.SyncedFolder; import foundation.e.drive.operations.CreateInitialFolderRemoteOperation; import foundation.e.drive.utils.AppConstants; Loading Loading @@ -280,7 +281,7 @@ public class InitializerService extends Service implements OnRemoteOperationList CommonUtils.registerPeriodicFullScanWorker(WorkManager.getInstance(appContext)); //all folder have been created ((EdriveApplication) this.getApplication() ).startRecursiveFileObserver(); //Immediatly start ObserverService to not have to wait 30 minutes. Intent observersServiceIntent = new Intent(getApplicationContext(), foundation.e.drive.services.ObserverService.class); Loading Loading
app/src/main/java/foundation/e/drive/EdriveApplication.java +29 −0 Original line number Diff line number Diff line Loading @@ -13,8 +13,11 @@ import android.accounts.AccountManager; import android.app.Application; import android.content.Context; import android.content.SharedPreferences; import android.os.Environment; import android.util.Log; import foundation.e.drive.FileObservers.FileEventListener; import foundation.e.drive.FileObservers.RecursiveFileObserver; import foundation.e.drive.utils.AppConstants; import foundation.e.drive.utils.CommonUtils; Loading @@ -25,6 +28,8 @@ import foundation.e.drive.utils.CommonUtils; public class EdriveApplication extends Application { private static final String TAG = "EdriveApplication"; private RecursiveFileObserver mFileObserver = null; @Override public void onCreate() { Loading @@ -33,9 +38,14 @@ public class EdriveApplication extends Application { Log.i(TAG, "Starting"); resetOperationManagerSetting(); final String pathForObserver = Environment.getExternalStorageDirectory().getAbsolutePath(); mFileObserver = new RecursiveFileObserver(getApplicationContext(), pathForObserver, new FileEventListener()); SharedPreferences prefs = getSharedPreferences(AppConstants.SHARED_PREFERENCE_NAME, Context.MODE_PRIVATE); if (prefs.getString(AccountManager.KEY_ACCOUNT_NAME, null) != null) { Log.d(TAG, "Account already registered"); startRecursiveFileObserver(); } else { Account mAccount = CommonUtils.getAccount(getString(R.string.eelo_account_type), AccountManager.get(this)); if (mAccount != null) { Loading @@ -56,6 +66,25 @@ public class EdriveApplication extends Application { .apply(); } /** * Start Recursive FileObserver if not already watching */ public void startRecursiveFileObserver(){ if (!mFileObserver.isWatching()) { mFileObserver.startWatching(); Log.d(TAG, "Starting RecursiveFileObserver on media's root folder"); } else { Log.w(TAG, "RecursiveFileObserver (for media's root folder) was already running"); } } public void stopRecursiveFileObserver(){ mFileObserver.stopWatching(); Log.d(TAG, "RecursiveFileObserver on media's root folder stops watching "); } @Override public void onLowMemory() { super.onLowMemory(); Loading
app/src/main/java/foundation/e/drive/FileObservers/FileEventListener.java 0 → 100644 +30 −0 Original line number Diff line number Diff line /* * Copyright © Narinder Rana (/e/ foundation). * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/gpl.html */ package foundation.e.drive.FileObservers; import android.os.FileObserver; import android.util.Log; import java.io.File; /** * @author Narinder Rana * @author vincent Bourgmayer */ public class FileEventListener { private final static String TAG = FileEventListener.class.getSimpleName(); public void onEvent(int event, File file) { if (event == FileObserver.CLOSE_WRITE) { //Event triggered after modification/creation Log.d(TAG, "CLOSE_WRITE event for :" + file.getName()); } else if (event == FileObserver.DELETE) { Log.d(TAG, "DELETE event for :" + file.getName()); } } }
app/src/main/java/foundation/e/drive/FileObservers/RecursiveFileObserver.java 0 → 100644 +174 −0 Original line number Diff line number Diff line /* * Copyright © Narinder Rana (/e/ foundation). * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/gpl.html */ package foundation.e.drive.FileObservers; import android.content.Context; import android.os.FileObserver; import java.io.File; import java.io.FileFilter; import java.util.HashMap; import java.util.List; import java.util.Stack; import foundation.e.drive.database.DbHelper; import foundation.e.drive.models.SyncedFolder; /** * @author Narinder Rana * @author Vincent Bourgmayer */ public class RecursiveFileObserver extends FileObserver { private final HashMap<String, FileObserver> observers = new HashMap<>(); private static final FileFilter WATCHABLE_DIRECTORIES_FILTER = new FileFilter() { @Override public boolean accept(File file) { return file.isDirectory() && !file.getName().startsWith("."); } }; private boolean watching = false; private final Context applicationContext; private String path; private int mask; private FileEventListener listener; public RecursiveFileObserver(Context applicationContext, String path, FileEventListener listener) { this(applicationContext, path, ALL_EVENTS, listener); } public RecursiveFileObserver(Context applicationContext, String path, int mask, FileEventListener listener) { super(path, mask); this.path = path; this.mask = mask | FileObserver.CREATE | FileObserver.DELETE_SELF; this.listener = listener; this.applicationContext = applicationContext; } @Override public void onEvent(int event, String path) { File file; if (path == null) { file = new File(this.path); } else { file = new File(this.path, path); } notify(event, file); } private void notify(int event, File file) { if (listener != null) { listener.onEvent(event & FileObserver.ALL_EVENTS, file); } } @Override public void startWatching() { Stack<String> stack = new Stack<>(); List<SyncedFolder> mSyncedFolders = DbHelper.getAllSyncedFolders(applicationContext); if (!mSyncedFolders.isEmpty()){ for (SyncedFolder syncedFolder:mSyncedFolders){ stack.push(syncedFolder.getLocalFolder()); stack.push(syncedFolder.getRemoteFolder()); } watching = true; } // Recursively watch all child directories while (!stack.empty()) { String parent = stack.pop(); startWatching(parent); File path = new File(parent); File[] files = path.listFiles(WATCHABLE_DIRECTORIES_FILTER); if (files != null) { for (File file : files) { stack.push(file.getAbsolutePath()); } } } } /** * Start watching a single file * @param path */ private void startWatching(String path) { synchronized (observers) { FileObserver observer = observers.remove(path); if (observer != null) { observer.stopWatching(); } observer = new SingleFileObserver(path, mask); observer.startWatching(); observers.put(path, observer); } } @Override public void stopWatching() { for (FileObserver observer : observers.values()) { observer.stopWatching(); } observers.clear(); watching = false; } /** * Stop watching a single file * @param path */ private void stopWatching(String path) { synchronized (observers) { FileObserver observer = observers.remove(path); if (observer != null) { observer.stopWatching(); } } } public boolean isWatching(){ return watching; } private class SingleFileObserver extends FileObserver { private String filePath; public SingleFileObserver(String path, int mask) { super(path, mask); filePath = path; } @Override public void onEvent(int event, String path) { File file; if (path == null) { file = new File(filePath); } else { file = new File(filePath, path); } switch (event & FileObserver.ALL_EVENTS) { case DELETE_SELF: RecursiveFileObserver.this.stopWatching(filePath); break; case CREATE: if (WATCHABLE_DIRECTORIES_FILTER.accept(file)) { RecursiveFileObserver.this.startWatching(file.getAbsolutePath()); } break; } RecursiveFileObserver.this.notify(event, file); } } }
app/src/main/java/foundation/e/drive/models/FileObserver.java 0 → 100644 +33 −0 Original line number Diff line number Diff line /* * Copyright © Narinder Rana (/e/ foundation). * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/gpl.html */ package foundation.e.drive.models; import java.io.File; import java.io.Serializable; import java.util.List; /** * @author Narinder Rana */ public class FileObserver implements Serializable { private List<File> files; public FileObserver(List<File> files) { this.files = files; } public List<File> getFiles() { return files; } public void setFiles(List<File> files) { this.files = files; } }
app/src/main/java/foundation/e/drive/services/InitializerService.java +2 −1 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import foundation.e.drive.EdriveApplication; import foundation.e.drive.models.SyncedFolder; import foundation.e.drive.operations.CreateInitialFolderRemoteOperation; import foundation.e.drive.utils.AppConstants; Loading Loading @@ -280,7 +281,7 @@ public class InitializerService extends Service implements OnRemoteOperationList CommonUtils.registerPeriodicFullScanWorker(WorkManager.getInstance(appContext)); //all folder have been created ((EdriveApplication) this.getApplication() ).startRecursiveFileObserver(); //Immediatly start ObserverService to not have to wait 30 minutes. Intent observersServiceIntent = new Intent(getApplicationContext(), foundation.e.drive.services.ObserverService.class); Loading