2010-03-16 4 views
2

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

Код:

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

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

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

+0

Вы уверены, что Наблюдатели все еще живы? Какой поток они работают? Может быть, они уничтожены мусорным трактором? – cboese

+0

Вы получили какое-либо решение? –

ответ

8

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

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

+2

Im мой случай, наблюдатели все еще живы, но после получения события 32768 они не получают никаких событий. После перезагрузки устройства все нормально, но проблема с перезагрузкой afters воспроизводится. Поврежден на 4.4+ android – iscariot

+0

@iscariot См. Здесь ошибку: https://code.google.com/p/android/issues/detail?id=29546 – StenaviN

+0

Это ошибка в GC, которая убивает наблюдателей – iscariot

0

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

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

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

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

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

0

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

0

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

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

Я использовал этот код в моем приложении "Электронная почта Pictures Автоматически" 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; 
} 

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

Смежные вопросы