File observer stops working after some time
Asked Answered
I

4

3

I want to listen to the changes occured in file system.I am using FileObserver.Here is my code:

Code:

class MyDirObserver extends FileObserver {
    String superPath;
    public MyDirObserver(String path) {
        super(path, ALL_EVENTS);
        this.superPath = path;
    }


    public void onEvent(int event, String path) {
        Log.e("onEvent of Directory", "=== onEvent ===");
        try {
            _Dump("dir", event, path, superPath);
        } catch (NullPointerException ex) {
            Log.e("ERROR", "I am getting error");
        }
    }
}


private void _Dump(final String tag, int event, String path, String superPath) {
    Log.d(tag, "=== dump begin ===");
    Log.d(tag, "path=" + path);
    Log.d(tag, "super path=" + superPath);
    Log.d(tag, "event list:");
    if ((event & FileObserver.OPEN) != 0) {
        Log.d(tag, "  OPEN");
    }
    if ((event & FileObserver.CLOSE_NOWRITE) != 0) {
        Log.d(tag, "  CLOSE_NOWRITE");
    }
    if ((event & FileObserver.CLOSE_WRITE) != 0) {


        Log.d(tag, "  CLOSE_WRITE");
        Log.i("NEWFILEOBSERVER", "File is Modified");
        if (path != null) {
            Log.d("---------FilePath", superPath + path);
        }


    }
    if ((event & FileObserver.CREATE) != 0) {
        isCreate = true;
        Log.i("NEWFILEOBSERVER", "File is Created ");
        if (path != null) {
            Log.d("---------FilePath", superPath + path);
        }
        Log.d(tag, "  CREATE");


    }
    if ((event & FileObserver.DELETE) != 0) {
        Log.i("NEWFILEOBSERVER", "File is deleted");
        if (path != null) {
            Log.d("---------FilePath", superPath + path);
        }
        //  startMyActivity("A new file is deleted thats="+superPath); 


        Log.d(tag, "  DELETE");


    }

    if ((event & FileObserver.DELETE_SELF) != 0) {
        Log.d(tag, "  DELETE_SELF");
    }

    if ((event & FileObserver.ACCESS) != 0) {
        Log.d(tag, "  ACCESS");
    }

    if ((event & FileObserver.MODIFY) != 0) {
        if (!isModified)
            isModified = true;

        if (isModified && isOpen)
            isAgainModified = true;
        Log.d(tag, "  MODIFY");
    }

    if ((event & FileObserver.MOVED_FROM) != 0) {
        Log.d(tag, "  MOVED_FROM");
        if (path != null) {
            Log.d("---------FilePath", superPath + path);
        }
    }

    if ((event & FileObserver.MOVED_TO) != 0) {
        Log.d(tag, "  MOVED_TO");
        if (path != null) {
            Log.d("---------FilePath", superPath + path);
        }
    }

    if ((event & FileObserver.MOVE_SELF) != 0) {
        Log.d(tag, "  MOVE_SELF");
    }

    if ((event & FileObserver.ATTRIB) != 0) {
        Log.d(tag, "  ATTRIB");
    }

    Log.d(tag, "=== dump end ===");
}

it stops after some time.I dont get the exact time but doesnt work always though I call startWatching() in service in a loop which runs for all the folders of sdcard and calls startWatching() for each of them. It shows unpredictable behaviour and stops listening for some folders and runs perfectly for the others.

I hope you guys help me. I tried many ways but it doesn't work perfectly. Am I doing something wrong? Or is there some other way to do this.

Infante answered 16/3, 2010 at 7:20 Comment(2)
DAre you sure the Observers are still alive? What thread are they running in? Maybe they get destroyed by the garbage collcector?Vasta
Did you get any solution ?Evade
B
10

http://developer.android.com/reference/android/os/FileObserver.html

Warning: If a FileObserver is garbage collected, it will stop sending events. To ensure you keep receiving events, you must keep a reference to the FileObserver instance from some other live object.

Beacon answered 19/4, 2011 at 22:1 Comment(2)
Im my case, observers is still alive, but after receiving 32768 event, they are don't receive any events. After rebooting device, all ok, but afters rebooting app problem is reproduce. Affected on 4.4+ androidOrbital
It's a bug in GC, which kill observersOrbital
C
1

Declare FileObserver as Static and global which will retain the instance of Fileobserver and restrict OS to take service into garbage collector.

Clayberg answered 19/2, 2015 at 12:36 Comment(0)
C
1

I'll present you part of code in my application, which emails every picture you take with your phone to predefinded list of emails. The sending email and list of receiving emails are stored in Shared Preferences. I use Service class and FileObserver to watch pictures directory of the phone. In my case, this scheme resloves also the problem with FileObserver, which stops work after some period of time.

  1. Use an activity (StartServicesActivity) to start the service (FileObserverService) as Foreground service.
  2. Use BroadcastReceiver class (in example CommonReceiver) to restart your service in some special situations and in case it was killed.
  3. Each time the service is restarted (performs onStartCommand) recreate FileObserver object to watch the pictures directory.

I used this code in my app "Email Pictures Automatically" https://play.google.com/store/apps/details?id=com.alexpap.EmailPicturesFree

Here is CommonReceiver class.

public class CommonReceiver extends BroadcastReceiver {

    public void onReceive(Context paramContext, Intent paramIntent)
    {
        paramContext.startService(new Intent(paramContext, FileObserverService.class));
    }
}

Here is its definition in AndroidManifest.xml just before application closing tag.

<receiver android:name="com.alexpap.services.CommonReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
    </intent-filter>
    <intent-filter>
        <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.USER_PRESENT"/>
    </intent-filter>
</receiver>

Start service in StartServicesActivity activity.

Intent iFileObserver = new Intent(StartServicesActivity.this, FileObserverService.class);
StartServicesActivity.this.startService(iFileObserver);

Here is onCreate() method of the service FileObserverService.

//Class variables
MediaFileObserver observPictures = null;
String pathToWatchPic = "";

public void onCreate() {

    pathToWatchPic = Environment.getExternalStorageDirectory().toString() + "/DCIM/100MEDIA";       

    File  mediaStorageDir = new File(pathToWatchPic); 
    if (!mediaStorageDir.exists()){
        pathToWatchPic = Environment.getExternalStorageDirectory().toString() + "/DCIM/Camera";
    }

}

Here is onStartCommand() method of the service FileObserverService.

public int onStartCommand(Intent intent, int flags,  int startId) {

    int res = super.onStartCommand(intent, flags, startId);

    if (observPictures != null){
        observPictures.stopWatching();
    }
    //each time service is restarted, observPictures object is recreated
    //and observation is restarted. This way File Observer never stops.
    observPictures = new MediaFileObserver(this, pathToWatchPic);
    observPictures.startWatching();

    startServiceForeground(intent, flags, startId);

    return Service.START_STICKY;  
}

public int startServiceForeground(Intent intent, int flags, int startId) {

    Intent notificationIntent = new Intent(this, StartServicesActivity.class); 
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

    Notification notification = new NotificationCompat.Builder(this)
        .setContentTitle("File Observer Service")
        .setContentIntent(pendingIntent)
        .setOngoing(true)
            .build();

    startForeground(300, notification);

    return START_STICKY;
}

Service is restarted also each time you turn on the phone and after rebooting.

Carping answered 11/6, 2015 at 21:18 Comment(0)
O
0

Try to link reference to Observer in your Application class. like this

private ArrayList<FileObserver> mObservers = new ArrayList<FileObserver>();

public void addObserver(FileObserver observer){
    mObservers.add(observer);
}

public void removeObserver(FileObserver observer){
    mObservers.remove(observer);
}

This works for me!

Orbital answered 10/6, 2014 at 15:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.