Como se hace un Service:
Esta semana hemos visto los servicios en el curso de Android. No me refiero a los aseos, no, me refiero a un tipo de objeto que se ejecuta en background y por definición no tiene interfaz gráfica ni puede modificar nada de ésta.
public class MyService extends Service {
@Override
public IBinder onBind(Intent arg0) {
// Este sirve para enlazarse con el Manager de Notificaciones
// para que otros programas usen este servicio.
return null;
}
@Override
public void onCreate() {
super.onCreate();
Log.d("MyService", "Arrancando el servicio");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d("MyService", "Cerrando el servicio");
}
}
Como se hace un Interface:
También vimos como hacer que nuestro servicio avisara a nuestras Activities del interfaz gráfico de algún cambio, como por ejemplo en las coordenadas del GPS.
Para el aviso vimos el uso de las interfaces, como esta:
public interface IMyServiceListener {
public void updateCurrentLocation(Location loc);
}
Una interfaz muy sencilla con un único método a implementar en las clases que la implementen.
En el servicio además hay que añadir un ArrayList, por ejemplo, de Listeners del tipo IMyServiceListener y un par de métodos públicos para poder añadir y quitar elementos del ArrayList.
public static void registerLocationListener(IMyServiceListener listener){
mArrayListeners.add(listener);
}
public static void unregisterLocationListener(IMyServiceListener listener){
mArrayListeners.remove(listener);
}
Para implementar la interfaz simplemente sería algo así:
public class AdvancedList extends ListActivity implements IMyServiceListener {
private Location mLocation;
@Override
public void updateCurrentLocation(Location loc) {
mLocation = loc;
Log.d("UpdatingLocation", loc.toString());
Toast.makeText(this, "New location: " +
String.valueOf(loc.getLatitude()) + "-" +
String.valueOf(loc.getLongitude()),
Toast.LENGTH_LONG);
new getImageTask().execute();
}
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Arrancanco el servicio creado.
startService(new Intent(this, MyService.class));
// Añado esta clase como listener del servicio, porque
// implementa la interfaz.
MyService.registerLocationListener(this);
myAdapter = new MyAdapter(this);
setListAdapter(myAdapter);
}
}
Y cuando desde el servicio se quiera avisar a todos los listeners de algún cambio, podemos crear un método como el siguiente en el servicio y llamarlo cuando se necesite.
private void notifyListeners(){
Log.d("NotifyListeners",
"Number of listeners " +
String.valueOf(mArrayListeners.size()));
for(int i = 0; i < mArrayListeners.size(); i++){
mArrayListeners.get(i).updateCurrentLocation(mLocation);
}
}
Problema:
Bueno, no quería contar toda la clase de ayer pero al final me he liado. Lo que yo quería contar es que aunque implementemos en nuestras Activities la interfaz del listener, cuando el Service llama a ese método de nuestra Activity, la ejecución sigue en la hebra del Service. Por lo cual ni el Toast que he puesto en la implementación del updateCurrentLocation, ni ningún cambio del interfaz gráfico será realizado.
Por suerte no he tardado mucho en darme cuenta jeje, habrá que ver otra forma de avisar desde el servicio si se quiere modificar el interfaz gráfico.