FileObserver 当我们要对一个文件或者文件夹进行监听的时候,我们可以使用android api中的android.os.FileObserver ,在前面的Linux文件系统Inotify机制 中介绍了Linux对文件变更监控过程。android 系 统在此基础上封装了一个FileObserver类来方便使用Inotify机制。FileObserver是一个抽象类,需要定义子类实现该类的 onEvent抽象方法,当被监控的文件或者目录发生变更事件时,将回调FileObserver的onEvent()函数来处理文件或目录的变更事件。名思议,就是监听文件的事件啦,根据官方给出的文档,有以下几种事件的响应,对应不同的事件常量。
常量名 | 对应事件 |
---|---|
ACCESS | 打开文件后读取文件的操作 |
ALL_EVENTS | 事件列表中的所有事件 |
ATTRIB | 未明操作 |
CLOSE_NOWRITE | 只读文件被关闭 |
CLOSE_WRITE | 读写文件被编辑并关闭 |
CREATE | 文件被创建创建 |
DELETE | 文件被删除 |
DELETE_SELF | 自删除事件 |
MODIFY | 文件被修改 |
MOVED_FROM | 移出事件 |
MOVED_TO | 移入事件 |
MOVE_SELF | 自移动事件 |
OPEN | 文件被打开 |
这些常量都是在FileObserver类里面的,因此可以通过FileObserver.XXX来调用。
FileObserver可以监听两种类型的文件:一种是单个文件,另一种是文件目录。需要注意的是监听文件目录的时候有个不能递归子目录的问题,因此要么确保监听的文件下没有子目录,要么做特殊的操作,手动递归监听每一个子目录。
构造函数如下:
/**
*Equivalent to FileObserver(path, FileObserver.ALL_EVENTS).
*/
publicFileObserver(String path) {
this(path,ALL_EVENTS);
}
/**
*Create a new file observer for a certain file or directory.
*Monitoring does not start on creation! You must call
*{@link #startWatching()}before you will receive events.
*
*@parampath The file or directory to monitor
*@parammask The event or events (added together) to watch for
*/
publicFileObserver(String path, intmask) {
m_path= path;
m_mask= mask;
m_descriptor= -1;
}
/*
* Created by Spreadst.
*/
packagecom.test.settings;
importandroid.app.Activity;
importandroid.content.Intent;
importandroid.os.Bundle;
importandroid.view.View;
importorg.apache.http.util.EncodingUtils;
importcom.android.settings.R;
importcom.android.settings.R.id;
importcom.android.settings.R.xml;
importandroid.widget.TextView;
importandroid.util.Log;
importjava.io.FileInputStream;
importjava.io.IOException;
importjava.io.FileNotFoundException;
importjava.io.PrintWriter;
importjava.io.RandomAccessFile;
importandroid.app.Activity;
importandroid.os.Bundle;
importandroid.os.FileObserver;
importandroid.os.Handler;
importandroid.os.Message;
importandroid.text.method.ScrollingMovementMethod;
importandroid.util.Log;
importandroid.view.Menu;
importandroid.view.MenuItem;
importandroid.widget.TextView;
publicclass LocationAgpsLogShow extends Activity {
privatestatic final String LOG_FILE_NAME = "/data/agps.log";
privatestatic final String TAG = "LocationAgpsLogShow";
privatestatic final int MENU_DELETE = 0;
privatestatic final int MSG_DELETE = 0;
privatestatic final int MSG_LOG_CHANGE = 1;
privateTextView mTextView;
RandomAccessFilemRaf;
privateStringBuilder mBuffer = new StringBuilder();
privateHandler mHandler = new Handler(){
publicvoid handleMessage(android.os.Message msg) {
switch(msg.arg1) {
caseMSG_DELETE:
deleteLogContent();
mTextView.setText("");
break;
caseMSG_LOG_CHANGE:
getAgpsLog();
break;
default:
Log.d(TAG,"handleMesage default");
break;
}
};
};
@Override
publicvoid onCreate(Bundle SavedInstanceState) {
super.onCreate(SavedInstanceState);
setContentView(R.xml.show_agps_log);
mTextView= (TextView) findViewById(R.id.agps_log_show);
mTextView.setMovementMethod(ScrollingMovementMethod.getInstance());
try{
mRaf= new RandomAccessFile(LOG_FILE_NAME, "rw");
}catch (FileNotFoundException e) {
e.printStackTrace();
}
mFileObserver.startWatching();
}
FileObservermFileObserver = new FileObserver(LOG_FILE_NAME) {
@Override
publicvoid onEvent(int event, String path) {
Log.d(TAG,event +" <-event ; path -> "+ path);
switch(event) {
caseFileObserver.MODIFY:
Messagemsg = Message.obtain();
msg.arg1= MSG_LOG_CHANGE;
mHandler.sendMessage(msg);
break;
default:
break;
}
}
};
@Override
publicvoid onResume() {
super.onResume();
Messagemsg = Message.obtain();
msg.arg1= MSG_LOG_CHANGE;
mHandler.sendMessage(msg);
}
@Override
publicboolean onCreateOptionsMenu(Menu menu) {
menu.add(0,MENU_DELETE, 0, R.string.delete);
returnsuper.onCreateOptionsMenu(menu);
}
@Override
publicboolean onPrepareOptionsMenu(Menu menu) {
Stringtext = mTextView.getText().toString();
if(text.length()==0){
menu.findItem(MENU_DELETE).setEnabled(false);
}else {
menu.findItem(MENU_DELETE).setEnabled(true);
}
returnsuper.onPrepareOptionsMenu(menu);
}
@Override
publicboolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()) {
caseMENU_DELETE:
Messagemsg = Message.obtain();
msg.arg1= MSG_DELETE;
mHandler.sendMessage(msg);
break;
default:
Log.d(TAG,"onOptionsItemSelected default ");
break;
}
returnsuper.onOptionsItemSelected(item);
}
privatevoid deleteLogContent(){
PrintWriterpw = null;
try{
pw= new PrintWriter(LOG_FILE_NAME);
pw.print("\n");
//clear the content of buffer
mBuffer.delete(0,mBuffer.length());
//in order to move pointer to the start line of file
mRaf.seek(0);
}catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
if(pw!= null){
pw.close();
}
}
}
@Override
publicvoid onPause() {
super.onPause();
}
@Override
publicvoid onDestroy() {
super.onDestroy();
mFileObserver.stopWatching();
if(mRaf != null) {
try{
mRaf.close();
}catch (IOException e) {
e.printStackTrace();
}
};
}
privatevoid getAgpsLog(){
try{
Stringcontent = "";
while((content= mRaf.readLine()) != null){
mBuffer.append(content+"\n");
}
Log.d(TAG,"buffer string = "+mBuffer.toString());
}catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
mTextView.setText(mBuffer.toString());
}
}