私はアンドロイドが初めてで、これが私の最初のプロジェクトであり、 Handlers と FileObservers に少し行き詰まっています。アプリはファイル システム上のフォルダーを監視し、ファイルが変更されると、フォルダー内の新しいイメージが UI に表示されます。
現時点ではコードは壊れていませんが、 FileObserverクラスで呼び出したHandlerが 1 回しか起動しない理由について頭を悩ませています。
Handler呼び出しを削除し、監視フォルダー内の複数のファイルを変更すると、 FileObserverはすべての変更を取得し、関連するメッセージをログに記録します。
しかし、前に述べたように、ハンドラーが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のHandlerにコードを入力して、次のことを行います。
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はインスタンスを作成することなくすぐに新しい画像をピックアップしますファイルオブザーバー。