FileObserver文件監聽

一、概述

FileObserver主要用來提供對文件或者文件夾的監控,一個FileObserver實例監控一個文件,能夠監控的文件或者文件夾的event type包括下表中的幾種。

類型值 類型名稱 含義
1 ACCESS 從文件中讀取數據
2 MODIFY 從文件中編輯數據
4 ATTRIB 文件元數據(權限,擁有者,時間戳)被明確改變
8 CLOSE_WRITE 有人打開文件或者目錄進行書寫,並且關閉它
16 CLOSE_NOWEITTE 有人打開文件或者目錄沒有編輯,並且關閉它
32 OPEN 一個文件或者目錄被打開
64 MOVE_FROM 一個文件或者子目錄從被監控目錄被移出
128 MOVE_TO 一個文件或者子目錄被移入到被監控的目錄
256 CREATE 一個文件或者子目錄在被監控的目錄下被創建
512 DELETE 文件從監控目錄被刪除
1024 DELETE_SELF 監控的文件或者目錄被刪除,監控停止
2048 MOVE_SELF 監控的文件或者目錄被移動,監控繼續

另外,在調試的過程中,FileObserveronEvent會返回未明確定義的event type,經過調試,對應的含義如下表。

類型值 含義
1073742080 “文件夾”的創建(Create)操作
1073742336 “文件夾”的刪除(Delete)操作
1073741888 “文件夾”的移出(MOVE_FROM) 操作
1073741952 “文件夾”的移入(MOVE_TO) 操作
32768 “文件夾” 的打開操作 (OPEN) 操作

如果發現新的類型,後期會進行完善。

二、FileObserver的使用

FileObserver的API相對簡單,可以繼承FileObserver實現自定義的MyFileObserver,目的是監控onEvent回調,然後執行startWatching啓動監控,在需要停止監控的時候執行stopWatching

三、FileObserver收不到onEvent回調

如果在開發的過程中,遇到onEvent無法接收的問題,先確認對以下幾種可能原因進行排除。

  1. FileObserver對象實例被回收 (思路:通過放在Application中進行測試)
  2. 初始化順序問題 (思路:儘早的對FileObserver進行初始化)
  3. 沒有讀寫文件權限問題 (思路: 文件監控需要文件讀寫權限)
  4. onEvent中做複雜操作 (思路: 先跑通,再實現邏輯)
  5. 妨礙 inotify的可能性
  6. 同一個進程中,如果有兩個不同的FileObserver同時監控一個Path,只有後調用startWatching的FileObserver能夠收到onEvent回調。(Android系統Bug)

我在開發的過程中,最終是最後一點導致的,這是Android framework的Bug,Android系統Bug地址,解決方案在地址中有提供。

四、FileObserver使用注意事項

因爲FileObserverstartWatchingstopWatching都存在加鎖操作。拿startWatching源碼舉例。

public int startWatching(String path, int mask, FileObserver observer) {
    int wfd = startWatching(m_fd, path, mask);
    Integer i = new Integer(wfd);
     if (wfd >= 0) {
         synchronized (m_observers) {
              m_observers.put(i, new WeakReference(observer));
         }
    }
    return i;
}

其中有m_observers對象鎖,所有在我們調用MyFileObserverstartWatching時,儘量不要放在自己實現的對象鎖中實現,可能會引發死鎖操作,從而導致ANR。思路如下:

public class MyFileObserver extends FileObserver{
   @Override
    public void onEvent(int event0, String path) {
     // TODO 處理自己的業務邏輯
   }
}

public class FileObserverTest{
     private static final Object ob_lock = new Object();
     public void  startWatching(String path){
           MyFileObserver observer = new MyFileObserver(path)
           observer.startWatching();
           synchronized(ob_lock){
                // TODO 這裏去執行程序中需要枷鎖進行同步的操作,不要將startWatching放在業務邏輯鎖中,防止死鎖。
           }
     }
}

五、FileObserver總結

文件操作相關的開發中,經常會用到FileObserver對文件的監控操作,從而去實現當文件有變化時,程序及時進行UI邏輯反饋給用戶的能力,上面我列出了自己在使用過程中的一些經驗和總結,如果有遺留的思路或者問題,歡迎進行留言反饋。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章