Как вы реализуете FileObserver из службы Android
Как вы структурируете приложение для Android, чтобы запустить Service
, чтобы использовать FileObserver
, чтобы при изменении наблюдаемого каталога (т.е. пользователь делает снимок) выполняется другой код. При отладке метод onEvent никогда не запускается.
Вот событие onStart, которое у меня есть в моей службе. Toast
запускается для "My Service Started..."
public final String TAG = "DEBUG";
public static FileObserver observer;
@Override
public void onStart(Intent intent, int startid) {
Log.d(TAG, "onStart");
final String pathToWatch = android.os.Environment.getExternalStorageDirectory().toString() + "/DCIM/Camera/";
Toast.makeText(this, "My Service Started and trying to watch " + pathToWatch, Toast.LENGTH_LONG).show();
observer = new FileObserver(pathToWatch) { // set up a file observer to watch this directory on sd card
@Override
public void onEvent(int event, String file) {
//if(event == FileObserver.CREATE && !file.equals(".probe")){ // check if its a "create" and not equal to .probe because thats created every time camera is launched
Log.d(TAG, "File created [" + pathToWatch + file + "]");
Toast.makeText(getBaseContext(), file + " was saved!", Toast.LENGTH_LONG);
//}
}
};
}
Но после этого Тоста, если я сделаю снимок, onEvent никогда не срабатывает. Это определяется путем отладки. Он никогда не попадает в точку останова, и Тост никогда не срабатывает.
Когда этот каталог просматривается, новое изображение сохраняется там.
Как вы получаете FileObserver
, работающий в Service
?
Ответы
Ответ 1
Пожалуйста, см. этот пост. Я думаю, что вам не хватает вызова observer.startWatching()
после настройки вашего наблюдателя.
observer = new FileObserver(pathToWatch) { // set up a file observer to watch this directory on sd card
@Override
public void onEvent(int event, String file) {
//if(event == FileObserver.CREATE && !file.equals(".probe")){ // check if its a "create" and not equal to .probe because thats created every time camera is launched
Log.d(TAG, "File created [" + pathToWatch + file + "]");
Toast.makeText(getBaseContext(), file + " was saved!", Toast.LENGTH_LONG).show();
//}
}
};
observer.startWatching(); //START OBSERVING
Ответ 2
Добавьте .show()
после toast
, то есть
Toast.makeText(getBaseContext(), file + " was saved!", toast.LENGTH_LONG).show();
Ответ 3
Еще одна вещь, FileObserver не наблюдает подкаталог. Если вы хотите наблюдать подкаталоги тоже Проверьте этот пост.
RecursiveFileObserver с открытым исходным кодом действует как расширенный FileObserver, который является рекурсивным для всех каталогов ниже выбранного вами каталога.
package com.owncloud.android.utils;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import android.os.FileObserver;
public class RecursiveFileObserver extends FileObserver {
public static int CHANGES_ONLY = CLOSE_WRITE | MOVE_SELF | MOVED_FROM;
List<SingleFileObserver> mObservers;
String mPath;
int mMask;
public RecursiveFileObserver(String path) {
this(path, ALL_EVENTS);
}
public RecursiveFileObserver(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.empty()) {
String parent = stack.pop();
mObservers.add(new SingleFileObserver(parent, mMask));
File path = new File(parent);
File[] files = path.listFiles();
if (files == null) continue;
for (int i = 0; i < files.length; ++i) {
if (files[i].isDirectory() && !files[i].getName().equals(".")
&& !files[i].getName().equals("..")) {
stack.push(files[i].getPath());
}
}
}
for (int i = 0; i < mObservers.size(); i++)
mObservers.get(i).startWatching();
}
@Override
public void stopWatching() {
if (mObservers == null) return;
for (int i = 0; i < mObservers.size(); ++i)
mObservers.get(i).stopWatching();
mObservers.clear();
mObservers = null;
}
@Override
public void onEvent(int event, String path) {
}
private class SingleFileObserver extends FileObserver {
private String mPath;
public SingleFileObserver(String path, int mask) {
super(path, mask);
mPath = path;
}
@Override
public void onEvent(int event, String path) {
String newPath = mPath + "/" + path;
RecursiveFileObserver.this.onEvent(event, newPath);
}
}
}
Источник на GitHub
Ответ 4
Вот полный код для создания службы, которая прослушивает новый файл в каталоге.
Во-первых, вам нужно создать сервис, который прослушивает новую запись файла в каталоге. (Например, камера)
MediaListenerService.java
import android.app.Service;
import android.content.Intent;
import android.os.FileObserver;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
import java.io.File;
public class MediaListenerService extends Service {
public static FileObserver observer;
public MediaListenerService() {
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
startWatching();
}
private void startWatching() {
//The desired path to watch or monitor
//E.g Camera folder
final String pathToWatch = android.os.Environment.getExternalStorageDirectory().toString() + "/DCIM/Camera/";
Toast.makeText(this, "My Service Started and trying to watch " + pathToWatch, Toast.LENGTH_LONG).show();
observer = new FileObserver(pathToWatch, FileObserver.ALL_EVENTS) { // set up a file observer to watch this directory
@Override
public void onEvent(int event, final String file) {
if (event == FileObserver.CREATE || event == FileObserver.CLOSE_WRITE || event == FileObserver.MODIFY || event == FileObserver.MOVED_TO && !file.equals(".probe")) { // check that it not equal to .probe because thats created every time camera is launched
Log.d("MediaListenerService", "File created [" + pathToWatch + file + "]");
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
Toast.makeText(getBaseContext(), file + " was saved!", Toast.LENGTH_LONG).show();
}
});
}
}
};
observer.startWatching();
}
}
Следующим шагом вам нужно объявить службу в AndroidManifest.xml внутри тега
<service
android:name=".service.MediaListenerService"
android:enabled="true"
android:exported="false" >
</service>
А также не забудьте добавить разрешение:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
Если вы пишете для Android 6 или более поздней версии, вам также потребуется динамически запрашивать разрешение в соответствии с этими инструкциями: https://developer.android.com/training/permissions/requesting
Теперь запустите сервис из вашей активности.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService(new Intent(getBaseContext(), MediaListenerService.class));
}
Если вы хотите, чтобы ваш сервис запускался при загрузке, просто создайте приемник, который прослушивает android.intent.action.BOOT_COMPLETED, а затем запустите сервис из этого.
Надеюсь это поможет.