java - servicio - service android ejemplo
¿Cómo implementar un FileObserver desde un servicio de Android? (4)
¿Cómo se estructura una aplicación de Android para iniciar un Service
para usar un FileObserver
modo que cuando se modifica el directorio observado (es decir, el usuario toma una foto) se ejecuta algún otro código? Al depurar, el método onEvent nunca se activa.
Aquí está el evento onStart que tengo en mi Servicio. La Toast
dispara para "Mi servicio comenzó ..."
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);
//}
}
};
}
Pero después de ese Toast, si tomo una foto, el Evento de nunca se dispara. Esto se determina mediante la depuración. Nunca llega a ese punto de ruptura y la tostada nunca se dispara.
Cuando se navega ese directorio, la nueva imagen se guarda allí.
¿Cómo lograr que un FileObserver
funcione en un Service
?
Añadir .show()
después de toast
, es decir
Toast.makeText(getBaseContext(), file + " was saved!", toast.LENGTH_LONG).show();
Aquí está el código completo para crear un servicio que escuche el nuevo archivo en un directorio.
En primer lugar, debe crear el servicio que escuche la entrada de un nuevo archivo en el directorio. (Ej. Cámara)
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''s 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();
}
}
El siguiente paso, debe declarar el servicio en la etiqueta interna AndroidManifest.xml
<service
android:name=".service.MediaListenerService"
android:enabled="true"
android:exported="false" >
</service>
Y también no olvides añadir un permiso:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
Si está escribiendo para Android 6 o superior, también deberá solicitar el permiso dinámicamente, según estas instrucciones: https://developer.android.com/training/permissions/requesting
Ahora inicia el servicio desde tu Actividad.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService(new Intent(getBaseContext(), MediaListenerService.class));
}
Si desea que su servicio se inicie durante el inicio, simplemente cree un receptor que escuche android.intent.action.BOOT_COMPLETED y luego inicie el servicio desde ahí.
Espero que esto ayude.
Por favor, see este post. Creo que le falta la llamada observer.startWatching()
después de configurar su observador.
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
Una cosa más que FileObserver no observa subdirectorio. Si desea observar también los subdirectorios, consulte this publicación.
Un RecursiveFileObserver de código abierto actúa como FileObserver avanzado que es recursivo para todos los directorios debajo del directorio que eligió
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);
}
}
}