sábado, 9 de abril de 2011

Interfaz gráfica y los servicios

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.

martes, 5 de abril de 2011

Como java.io.Serializable

Bueno, yo poco a poco sigo con mis pequeños descubrimientos, y quiero pensar que a alguien le puede venir bien encontrarse con posts como este, que cuenta cosas que una vez sabidas parecen obvias.

Todo empezó porque un compañero del curso de Android se le ocurrió la brillante idea de serializar un objeto para pasarlo de una Activity a otra por medio de Intent. Y claro, yo quise copiarle.
Como llegué tarde a clase y además no presté atención al profesor (no leas esto Rocapal ;) ), es ahora cuando descubro cómo funciona el interfaz java.io.Serializable.

Mi clase:

public class RestaurantItem implements java.io.Serializable{
    public String mName;
    public String mDescription;
    public int mPicture;
    public Location mLocation;
}

Y después de un rato de darle vueltas he visto que si la clase tiene un atributo de un tipo no básico como "Location" no se va a poder serializar de forma automática.
He probado cambiando el Location por dos doubles:

public double mLatitude;
public double mLongitude;

y funcionaba, pero prefiero no serializar a quitar el Location :p

Por cierto, para quien quiera pasar un objeto serializado en un Intent, simplemente tiene que hacer:

Intent i = new Intent();
i.putExtra("ObjetoName", myObject);

Siendo myObject un objeto de la clase que implementa java.io.Serializable.
Y para recuperar el objeto del Intent, supuestamente en la otra Activity:

ObjSerializable obj = (ObjSerializable) i.getSerializableExtra("ObjetoName");

Y ya está.
Related Posts Plugin for WordPress, Blogger...