我是 android 新手,这是我的第一个项目,并且有点卡在Handlers和FileObservers 上。该应用程序将观察文件系统上的一个文件夹,当文件被修改时,该文件夹内的新图像将显示在 UI 上。
目前代码没有中断,但我一直在摸不着头脑,为什么我在FileObserver类中调用的处理程序只触发一次。
如果我删除Handler调用并修改监视文件夹中的多个文件,FileObserver 会获取所有更改并记录相关消息。
但是就像前面提到的那样,当我允许Handler触发FileObserver时,它只会获取对监视文件夹的第一次更改,而随后什么也没有。
主要活动
private static ImageView imgMAX;
private static ImageView imgMIN;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imgMAX = (ImageView)findViewById(R.id.imageViewMAX);
imgMIN = (ImageView)findViewById(R.id.imageViewMIN);
vidAD = (VideoView)findViewById(R.id.videoViewAD);
//Sorting out media player playback options
MediaPlayer.OnPreparedListener PreparedListener = new MediaPlayer.OnPreparedListener(){
@Override
public void onPrepared(MediaPlayer m) {
try {
if (m.isPlaying()) {
m.stop();
m.release();
m = new MediaPlayer();
}
m.setVolume(0f, 0f);
m.setLooping(true);
m.start();
} catch (Exception e) {
e.printStackTrace();
}
}
};
//Set up media controller for videos
MediaController mediaController = new MediaController(this);
mediaController.setAnchorView(vidAD);
vidAD.setMediaController(new MediaController(this));
vidAD.setOnPreparedListener(PreparedListener);
//Create Message Handler
handler = new Handler(Looper.getMainLooper())
{
@Override
public void handleMessage(Message msg) {
String type = msg.getData().getString("typeoperation");
String path = msg.getData().getString("path");
Log.d("MESSAGE HANDLER", "Message Recieved: "+ type + " " + path);
String splitchar = "/";
String[] parts = path.split(splitchar);
String file = parts[parts.length-1];
if (file.equals("min.jpg")){
Bitmap bmp = BitmapFactory.decodeFile(path);
imgMIN.setImageBitmap(bmp);
PathFileObserver pfo = new PathFileObserver(filepath,handler);
pfo.startWatching();
} else if (file.equals("max.jpg")){
Bitmap bmp = BitmapFactory.decodeFile(path);
imgMAX.setImageBitmap(bmp);
PathFileObserver pfo = new PathFileObserver(filepath,handler);
pfo.startWatching();
} else if (file.equals("video.mp4")){
vidAD.stopPlayback();
vidAD.setVideoPath(path);
vidAD.requestFocus();
vidAD.start();
}
}
};
//Check if Storage is available
if(isExternalStorageReadable()){
filepath = Environment.getExternalStorageDirectory()+File.separator;
File f = new File(Environment.getExternalStorageDirectory());
if(f.exists()){
Bitmap bmp = BitmapFactory.decodeFile(filepath+"max.jpg");
imgMAX.setImageBitmap(bmp);
bmp = BitmapFactory.decodeFile(filepath+"min.jpg");
imgMIN.setImageBitmap(bmp);
vidAD.setVideoPath(filepath+"video.mp4");
vidAD.requestFocus();
vidAD.start();
PathFileObserver pfo = new PathFileObserver(filepath,handler);
pfo.startWatching();
}else{
new AlertDialog.Builder(this).setTitle("Error").setMessage("Error Loading Content.").setNeutralButton("Close", null).show();
}
}
}
文件观察者
public class PathFileObserver extends FileObserver{
static final String TAG="FILEOBSERVER";
String rootPath;
static final int mask = (FileObserver.CREATE |
FileObserver.DELETE |
FileObserver.DELETE_SELF |
FileObserver.MODIFY |
FileObserver.MOVED_FROM |
FileObserver.MOVED_TO |
FileObserver.MOVE_SELF |
FileObserver.CLOSE_WRITE);
private Handler handler;
public PathFileObserver(String root,Handler handler){
super(root, mask);
if (! root.endsWith(File.separator)){
root += File.separator;
}
rootPath = root;
this.handler = handler;
}
public void onEvent(int event, String path) {
Message msg = Message.obtain(handler);
Bundle b = new Bundle();
switch(event){
case FileObserver.CREATE:
Log.d(TAG, "CREATE:" + rootPath + path);
break;
case FileObserver.DELETE:
Log.d(TAG, "DELETE:" + rootPath + path);
break;
case FileObserver.DELETE_SELF:
Log.d(TAG, "DELETE_SELF:" + rootPath + path);
break;
case FileObserver.MODIFY:
Log.d(TAG, "MODIFY:" + rootPath + path);
break;
case FileObserver.MOVED_FROM:
Log.d(TAG, "MOVED_FROM:" + rootPath + path);
break;
case FileObserver.MOVED_TO:
Log.d(TAG, "MOVED_TO:" + path);
break;
case FileObserver.MOVE_SELF:
Log.d(TAG, "MOVE_SELF:" + path);
break;
case FileObserver.CLOSE_WRITE:
Log.d(TAG, "CLOSE_WRITE:" + path);
b.putString("typeoperation","CLOSE_WRITE");
b.putString("path",rootPath + path);
msg.setData(b);
handler.sendMessage(msg);
break;
default:
// just ignore
break;
}
}
public void close(){
super.finalize();
}
}
编辑
因此,经过更多的开发和处理视频视图后,我发现通过将FileObserver中的 onevent 更改为:
case FileObserver.CLOSE_WRITE:
Log.d(TAG, "CLOSE_WRITE:" + path);
b.putString("typeoperation","CLOSE_WRITE");
b.putString("path",rootPath + path);
msg.setData(b);
handler.sendMessage(msg);
break;
并在我的处理程序上为VideoView填写代码:
else if (file.equals("video.mp4")){
Toast.makeText(getBaseContext(), "Buffering New Video...", Toast.LENGTH_LONG).show();
vidAD.stopPlayback();
vidAD.setVideoPath(path);
vidAD.requestFocus();
vidAD.start();
}
当一个新视频被加载到文件夹中并被它加载的FileObserver拾取时,视频会按预期进行,然后如果我尝试在视频之后立即加载图像,FileObserver 会立即拾取新图像,而无需创建实例文件观察者。