How to track a folder for changing a file in the background?

I am trying to control a folder on a users disk in the background, just as you can control gallery changes using JobScheduler and contentobserver . I want to do this for any specified directory. However, I cannot figure out how to get the broadcast when there are any file changes in the directory.

+9
source share
2 answers

There are several things you must do to create a system file browser.

Firstly

You must create a service that will start at boot and will always work. For this to happen, you need to create a BroadcastReceiver , register it to receive ACTION_BOOT_COMPLETED and permission RECEIVE_BOOT_COMPLETED to your Manifest

 public class StartupReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Intent myIntent = new Intent(context, FileSystemObserverService.class); context.startService(myIntent); } } 

In your Manifest

 <manifest > <application > <service android:name=".FileSystemObserverService" android:enabled="true" android:exported="true" > </service> <!-- Declaring broadcast receiver for BOOT_COMPLETED event. --> <receiver android:name=".StartupReceiver" android:enabled="true" android:exported="false"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"/> </intent-filter> </receiver> </application> <!-- Adding the permission --> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> </manifest> 

secondly

The service must implement the android.os.FileObserver class. Since android.os.FileObserver only watches the path you submit to it and does not watch the path subdirectories, you must expand it and add SingleFileObserver watchers to SingleFileObserver . You must also start monitoring in another low priority thread.

  public class FileSystemObserverService extends Service { @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. throw new UnsupportedOperationException("Not yet implemented"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { observe(); return super.onStartCommand(intent, flags, startId); } public File getInternalStoragePath() { File parent = Environment.getExternalStorageDirectory().getParentFile(); File external = Environment.getExternalStorageDirectory(); File[] files = parent.listFiles(); File internal = null; if (files != null) { for (int i = 0; i < files.length; i++) { if (files[i].getName().toLowerCase().startsWith("sdcard") && !files[i].equals(external)) { internal = files[i]; } } } return internal; } public File getExtenerStoragePath() { return Environment.getExternalStorageDirectory(); } public void observe() { Thread t = new Thread(new Runnable() { @Override public void run() { //File[] listOfFiles = new File(path).listFiles(); File str = getInternalStoragePath(); if (str != null) { internalPath = str.getAbsolutePath(); new Obsever(internalPath).startWatching(); } str = getExtenerStoragePath(); if (str != null) { externalPath = str.getAbsolutePath(); new Obsever(externalPath).startWatching(); } } }); t.setPriority(Thread.MIN_PRIORITY); t.start(); } class Obsever extends FileObserver { List < SingleFileObserver > mObservers; String mPath; int mMask; public Obsever(String path) { // TODO Auto-generated constructor stub this(path, ALL_EVENTS); } public Obsever(String path, int mask) { super(path, mask); mPath = path; mMask = mask; // TODO Auto-generated constructor stub } @Override public void startWatching() { // TODO Auto-generated method stub if (mObservers != null) return; mObservers = new ArrayList < SingleFileObserver > (); Stack < String > stack = new Stack < String > (); stack.push(mPath); while (!stack.empty()) { String parent = stack.pop(); mObservers.add(new SingleFileObserver(parent, mMask)); File path = new File(parent); File[] files = path.listFiles(); if (files == null) continue; for (int i = 0; i < files.length; ++i) { if (files[i].isDirectory() && !files[i].getName().equals(".") && !files[i].getName().equals("..")) { stack.push(files[i].getPath()); } } } for (int i = 0; i < mObservers.size(); i++) { mObservers.get(i).startWatching(); } } @Override public void stopWatching() { // TODO Auto-generated method stub if (mObservers == null) return; for (int i = 0; i < mObservers.size(); ++i) { mObservers.get(i).stopWatching(); } mObservers.clear(); mObservers = null; } @Override public void onEvent(int event, final String path) { if (event == FileObserver.OPEN) { //do whatever you want } else if (event == FileObserver.CREATE) { //do whatever you want } else if (event == FileObserver.DELETE_SELF || event == FileObserver.DELETE) { //do whatever you want } else if (event == FileObserver.MOVE_SELF || event == FileObserver.MOVED_FROM || event == FileObserver.MOVED_TO) { //do whatever you want } } private class SingleFileObserver extends FileObserver { private String mPath; public SingleFileObserver(String path, int mask) { super(path, mask); // TODO Auto-generated constructor stub mPath = path; } @Override public void onEvent(int event, String path) { // TODO Auto-generated method stub String newPath = mPath + "/" + path; Obsever.this.onEvent(event, newPath); } } } 

That with this code you can observe the entire file system, both internal and external file system

+11
source

Just start the service that uses Fileobserver to detect file changes for the specified directory.

Class of service:

 public class FileObserverService extends Service { private FileObserver mFileObserver; @Override public int onStartCommand(Intent intent, int flags, int startId) { if((intent.hasExtra(INTENT_EXTRA_FILEPATH))) // we store the path of directory inside the intent that starts the service mFileObserver = new FileObserver(intent.getStringExtra(INTENT_EXTRA_FILEPATH)) { @Override public void onEvent(int event, String path) { // If an event happens we can do stuff inside here // for example we can send a broadcast message with the event-id Log.d("FILEOBSERVER_EVENT", "Event with id " + Integer.toHexString(event) + " happened") // event identifies the occured Event in hex } }; mFileObserver.startWatching(); // The FileObserver starts watching return Service.START_NOT_STICKY; } @Override public void onCreate() { super.onCreate(); } @Override public IBinder onBind(Intent intent) { //TODO for communication return IBinder implementation return null; } } 

Start the service somewhere inside your application using YOUR_FILEPATH / DIRECTORY, which you want to watch:

 Intent intent = new Intent(this, FileObserverService.class); intent.putExtra(INTENT_EXTRA_FILEPATH, "YOUR_FILEPATH"); this.startService(intent); 
+3
source

Source: https://habr.com/ru/post/1274397/


All Articles