Android如何監(jiān)測(cè)文件夾內(nèi)容變化詳解
一. 概述:
android.os包下的FileObserver類(lèi)是一個(gè)用于監(jiān)聽(tīng)文件訪(fǎng)問(wèn)、創(chuàng)建、修改、刪除、移動(dòng)等操作的監(jiān)聽(tīng)器,基于linux的INotify。FileObserver是個(gè)抽象類(lèi),必須繼承它才能使用。每個(gè)FileObserver對(duì)象監(jiān)聽(tīng)一個(gè)單獨(dú)的文件或者文件夾,如果監(jiān)視的是一個(gè)文件夾,那么文件夾下所有的文件和級(jí)聯(lián)子目錄的改變都會(huì)觸發(fā)監(jiān)聽(tīng)的事件。
FileObserver簡(jiǎn)介Android.os包下的FileObserver類(lèi)是一個(gè)用于監(jiān)聽(tīng)文件訪(fǎng)問(wèn)、創(chuàng)建、修改、刪除、移動(dòng)等操作的監(jiān)聽(tīng)器,基于Linux的INotify。
FileObserver是個(gè)抽象類(lèi),必須繼承它才能使用。每個(gè)FileObserver對(duì)象監(jiān)聽(tīng)一個(gè)單獨(dú)的文件或者文件夾,如果監(jiān)視的是一個(gè)文件夾,那么文件夾下所有的文件和級(jí)聯(lián)子目錄的改變都會(huì)觸發(fā)監(jiān)聽(tīng)的事件。
二. 監(jiān)聽(tīng)的事件類(lèi)型:
ACCESS,即文件被訪(fǎng)問(wèn)
? ? ?MODIFY,文件被 修改
? ? ?ATTRIB,文件屬性被修改,如 chmod、chown、touch 等
? ? ?CLOSE_WRITE,可寫(xiě)文件被 close
? ? ?CLOSE_NOWRITE,不可寫(xiě)文件被 close
? ? ?OPEN,文件被 open
? ? ?MOVED_FROM,文件被移走,如 mv
? ? ?MOVED_TO,文件被移來(lái),如 mv、cp
? ? ?CREATE,創(chuàng)建新文件
? ? ?DELETE,文件被刪除,如 rm
? ? ?DELETE_SELF,自刪除,即一個(gè)可執(zhí)行文件在執(zhí)行時(shí)刪除自己
? ? ?MOVE_SELF,自移動(dòng),即一個(gè)可執(zhí)行文件在執(zhí)行時(shí)移動(dòng)自己
? ? ?CLOSE,文件被關(guān)閉,等同于(IN_CLOSE_WRITE | IN_CLOSE_NOWRITE)
? ? ?ALL_EVENTS,包括上面的所有事件
三.實(shí)例
import com.example.androidemail.R; import com.example.androidemail.R.layout; import android.app.Activity; import android.os.Bundle; import android.os.Environment; import android.os.FileObserver; public class AndroidFileListenerActivity extends Activity { private FileObserver mFileObserver; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if(null == mFileObserver) { mFileObserver = new SDCardFileObserver(Environment.getExternalStorageDirectory().getPath()); mFileObserver.startWatching(); //開(kāi)始監(jiān)聽(tīng) } } public void onDestory() { if(null != mFileObserver) mFileObserver.stopWatching(); //停止監(jiān)聽(tīng) } static class SDCardFileObserver extends FileObserver { //mask:指定要監(jiān)聽(tīng)的事件類(lèi)型,默認(rèn)為FileObserver.ALL_EVENTS public SDCardFileObserver(String path, int mask) { super(path, mask); } public SDCardFileObserver(String path) { super(path); } @Override public void onEvent(int event, String path) { final int action = event & FileObserver.ALL_EVENTS; switch (action) { case FileObserver.ACCESS: System.out.println("event: 文件或目錄被訪(fǎng)問(wèn), path: " + path); break; case FileObserver.DELETE: System.out.println("event: 文件或目錄被刪除, path: " + path); break; case FileObserver.OPEN: System.out.println("event: 文件或目錄被打開(kāi), path: " + path); break; case FileObserver.MODIFY: System.out.println("event: 文件或目錄被修改, path: " + path); break; case FileObserver.CREATE: System.out.println("event: 文件或目錄被創(chuàng)建, path: " + path); break; } } } }
onEvent是回調(diào),系統(tǒng)監(jiān)聽(tīng)到事件后會(huì)觸發(fā)此事件,參數(shù)event就是上面所說(shuō)的事件類(lèi)型,參數(shù)path就是觸發(fā)事件的目錄,鑒定只針對(duì)于該層目錄,其他層次無(wú)效。
我們大多數(shù)需要監(jiān)聽(tīng)path目錄下的所有文件對(duì)象的相關(guān)操作,那該如何是好呢?解決問(wèn)題方法之一就是重新實(shí)現(xiàn)FileObserver類(lèi),
下面是對(duì)FileObserver類(lèi)的重寫(xiě)實(shí)現(xiàn)過(guò)程
import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Stack; import android.os.FileObserver; import android.util.Log; @SuppressWarnings(value = { "rawtypes", "unchecked" }) public class MultiFileObserver extends FileObserver { /** Only modification events */ public static int CHANGES_ONLY = CREATE | MODIFY |DELETE | CLOSE_WRITE | DELETE_SELF | MOVE_SELF | MOVED_FROM | MOVED_TO; private List<SingleFileObserver> mObservers; private String mPath; private int mMask; public MuityFileObserver(String path) { this(path, ALL_EVENTS); } public MuityFileObserver(String path, int mask) { super(path, mask); mPath = path; mMask = mask; } @Override public void startWatching() { if (mObservers != null) return; mObservers = new ArrayList<SingleFileObserver>(); Stack<String> stack = new Stack<String>(); stack.push(mPath); while (!stack.isEmpty()) { String parent = stack.pop(); mObservers.add(new SingleFileObserver(parent, mMask)); File path = new File(parent); File[] files = path.listFiles(); if (null == files) continue; for (File f : files) { if (f.isDirectory() && !f.getName().equals(".") && !f.getName().equals("..")) { stack.push(f.getPath()); } } } for (int i = 0; i < mObservers.size(); i++) { SingleFileObserver sfo = mObservers.get(i); sfo.startWatching(); } }; @Override public void stopWatching() { if (mObservers == null) return; for (int i = 0; i < mObservers.size(); i++) { SingleFileObserver sfo = mObservers.get(i); sfo.stopWatching(); } mObservers.clear(); mObservers = null; }; @Override public void onEvent(int event, String path) { switch (event) { case FileObserver.ACCESS: Log.i("RecursiveFileObserver", "ACCESS: " + path); break; case FileObserver.ATTRIB: Log.i("RecursiveFileObserver", "ATTRIB: " + path); break; case FileObserver.CLOSE_NOWRITE: Log.i("RecursiveFileObserver", "CLOSE_NOWRITE: " + path); break; case FileObserver.CLOSE_WRITE: Log.i("RecursiveFileObserver", "CLOSE_WRITE: " + path); break; case FileObserver.CREATE: Log.i("RecursiveFileObserver", "CREATE: " + path); break; case FileObserver.DELETE: Log.i("RecursiveFileObserver", "DELETE: " + path); break; case FileObserver.DELETE_SELF: Log.i("RecursiveFileObserver", "DELETE_SELF: " + path); break; case FileObserver.MODIFY: Log.i("RecursiveFileObserver", "MODIFY: " + path); break; case FileObserver.MOVE_SELF: Log.i("RecursiveFileObserver", "MOVE_SELF: " + path); break; case FileObserver.MOVED_FROM: Log.i("RecursiveFileObserver", "MOVED_FROM: " + path); break; case FileObserver.MOVED_TO: Log.i("RecursiveFileObserver", "MOVED_TO: " + path); break; case FileObserver.OPEN: Log.i("RecursiveFileObserver", "OPEN: " + path); break; default: Log.i("RecursiveFileObserver", "DEFAULT(" + event + " : " + path); break; } } /** * Monitor single directory and dispatch all events to its parent, with full * path. */ class SingleFileObserver extends FileObserver { String mPath; public SingleFileObserver(String path) { this(path, ALL_EVENTS); mPath = path; } public SingleFileObserver(String path, int mask) { super(path, mask); mPath = path; } @Override public void onEvent(int event, String path) { String newPath = mPath + "/" + path; MultiFileObserver .this.onEvent(event, newPath); } } }
總結(jié)
到此這篇關(guān)于Android如何監(jiān)測(cè)文件夾內(nèi)容變化的文章就介紹到這了,更多相關(guān)Android監(jiān)測(cè)文件夾內(nèi)容內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android-如何將RGB彩色圖轉(zhuǎn)換為灰度圖方法介紹
本文將詳細(xì)介紹Android-如何將RGB彩色圖轉(zhuǎn)換為灰度圖方法,需要了解更多的朋友可以參考下2012-11-11Android 開(kāi)發(fā)實(shí)現(xiàn)EditText 光標(biāo)居右顯示
這篇文章主要介紹了Android 開(kāi)發(fā)實(shí)現(xiàn)EditText 光標(biāo)居右顯示的相關(guān)資料,需要的朋友可以參考下2017-02-02Android FrameWork之Zygote啟動(dòng)示例詳解
這篇文章主要為大家介紹了Android FrameWork之Zygote啟動(dòng)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07Android自定義view Path 的高級(jí)用法之搜索按鈕動(dòng)畫(huà)
這篇文章主要介紹了Android自定義view Path 的高級(jí)用法之搜索按鈕動(dòng)畫(huà),需要的朋友可以參考下2017-06-06Android判斷手機(jī)是否是小米MIUI系統(tǒng)的方法
這篇文章主要介紹了Android判斷手機(jī)是否是小米MIUI系統(tǒng)的方法的相關(guān)資料,需要的朋友可以參考下2016-02-02Android實(shí)現(xiàn)網(wǎng)頁(yè)圖片瀏覽功能
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)網(wǎng)頁(yè)圖片瀏覽功能,輸入圖片的url然后點(diǎn)擊按鈕加載出來(lái)圖片,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05android現(xiàn)有項(xiàng)目輕微改動(dòng)適配平板心得
這篇文章主要介紹了android現(xiàn)有項(xiàng)目輕微改動(dòng)適配平板心得,對(duì)android適配感興趣的同學(xué)可以參考下2021-04-04