2010-03-16 99 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沒有得到確切的時間,但沒有 總是工作,雖然我在一個循環中調用startWatching()服務,該循環運行sdcard的所有文件夾,併爲每個文件夾調用startWatching()。它顯示不可預知的行爲,並停止監聽某些文件夾,並完美地運行其他文件夾。

我希望你們幫助我。我嘗試了很多方法,但它完美地不起作用 。難道我做錯了什麼?或者還有其他方式可以做到這一點。

+0

你確定觀察員還活着嗎?他們運行什麼線程?也許他們被垃圾堆砌機毀壞了? – cboese 2010-03-25 23:42:30

+0

你有沒有得到任何解決方案? – 2016-09-20 05:58:49

回答

8

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

警告:如果FileObserver是垃圾回收,它會停止發送事件。爲確保您繼續接收事件,您必須保留對某個其他活動對象的FileObserver實例的引用。

+2

在我的情況下,觀察員仍然活着,但在收到32768事件後,他們沒有收到任何事件。重啓設備後,一切正常,但重新啓動應用程序問題重現。受影響在4.4以上Android – iscariot 2014-06-10 12:10:32

+0

@iscariot在此處查看錯誤:https://code.google.com/p/android/issues/detail?id=29546 – StenaviN 2014-06-11 16:32:32

+0

這是GC中的一個錯誤,它會殺死觀察者 – iscariot 2014-06-12 14:18:59

0

嘗試將引用鏈接到您的Application類中的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的實例並限制OS將服務接入垃圾回收器。

0

我會在您的應用程序中爲您呈現部分代碼,該代碼會將您用手機拍攝的每張照片發送至預定義的電子郵件列表。發送電子郵件和接收電子郵件列表存儲在共享首選項中。我使用Service類和FileObserver來觀看手機的圖片目錄。 在我的情況下,這個方案也使用了FileObserver的問題,它在一段時間後會停止工作。

  1. 使用活動(StartServicesActivity)作爲Foreground服務啓動服務(FileObserverService)。
  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); 

以下是服務FileObserverService的onCreate()方法。

//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"; 
    } 

} 

這是服務FileObserverService的onStartCommand()方法。

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

每次打開手機並重新啓動後,服務也會重新啓動。