Файловый обозреватель перестает работать через некоторое время - PullRequest
3 голосов
/ 16 марта 2010

Я хочу прослушать изменения, произошедшие в файловой системе. Я использую FileObserver. Вот мой код:

Код:

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 ===");
}

он останавливается через некоторое время. Я не получаю точное время, но не получаю работать всегда, хотя я вызываю startWatching () в сервисе в цикле, который выполняется для всех папок sdcard и вызывает startWatching () для каждой из них. Он демонстрирует непредсказуемое поведение и останавливает прослушивание одних папок и отлично работает для других.

Надеюсь, вы, ребята, помогите мне. Я пробовал много способов, но это не работает в совершенстве. Я делаю что-то неправильно? Или есть какой-то другой способ сделать это.

Ответы [ 4 ]

8 голосов
/ 20 апреля 2011

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

Предупреждение: Если FileObserver собирается мусором, он прекращает отправку событий. Чтобы убедиться, что вы продолжаете получать события, вы должны хранить ссылку на экземпляр FileObserver из какого-либо другого живого объекта.

1 голос
/ 12 июня 2015

Я представлю вам часть кода в моем приложении, которое отправляет каждое изображение, которое вы делаете с помощью телефона, по электронной почте в заранее определенный список писем. Отправляющее электронное письмо и список получаемых электронных писем хранятся в общих настройках. Я использую класс обслуживания и FileObserver, чтобы посмотреть каталог картинок телефона. В моем случае эта схема решает также проблему с FileObserver, который прекращает работу через некоторое время.

  1. Используйте действие (StartServicesActivity) для запуска службы (FileObserverService) в качестве службы Foreground.
  2. Используйте класс BroadcastReceiver (в примере CommonReceiver) для перезапуска вашего сервиса в некоторых особых ситуациях и в случае его уничтожения.
  3. Каждый раз, когда служба перезапускается (выполняет onStartCommand), воссоздайте объект FileObserver для просмотра каталога с изображениями.

Я использовал этот код в своем приложении «Автоматически отправлять фотографии по электронной почте» https://play.google.com/store/apps/details?id=com.alexpap.EmailPicturesFree

Вот класс CommonReceiver.

public class CommonReceiver extends BroadcastReceiver {

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

Вот его определение в AndroidManifest.xml непосредственно перед тегом закрытия приложения.

<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>

Запуск службы в действии StartServicesActivity.

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

Вот метод onCreate () службы 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";
    }

}

Вот метод onStartCommand () службы 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;
}

Служба перезапускается также при каждом включении телефона и после перезагрузки.

1 голос
/ 19 февраля 2015

Объявите FileObserver как статический и глобальный, который сохранит экземпляр Fileobserver и ограничит ОС для передачи обслуживания в сборщик мусора.

0 голосов
/ 10 июня 2014

Попробуйте связать ссылку на Observer в вашем классе Application как это

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

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

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

Это работает для меня!

...