Mostrando entradas con la etiqueta curso-clua. Mostrar todas las entradas
Mostrando entradas con la etiqueta curso-clua. Mostrar todas las entradas

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.

jueves, 31 de marzo de 2011

Problema de acceso a la clase R

Este post lo escribo motivado por un pelín de odio y deseando que no le pase a nadie.
Después de estar un buen rato (una semanilla) mirando una posible solución a mi problema y pensando qué podría ser, he dado con la solución.

El problema:

Un proyecto de Android me daba error al acceder a la clase R autogenerada por el SDK desde la clase Main.
Pensaba que era por alguna cosa mal escrita en los recursos (ya sabes, no hay que escribir los nombres de archivo con letras mayúsculas) o por haber hecho un clean del proyecto o por tener activada la opción de autobuild. Lo intenté con "Android tools > Fix project properties", renombrando el paquete de la aplicación y nada.
Ya dudaba de todo.


Solución:

Desesperado ya he optado por empezar de nuevo un proyecto vacío.
Copiando el código del viejo proyecto he dado con el problema. Estaba importando android.R porque en algún momento lo habré necesitado o porque habré hecho un copy/paste mal, el caso es que si ya has probado de todo y estás apunto de tirarte por la ventana, prueba a borrar todos los "import" que tengas y autogenéralos pulsando las teclas:

Ctrl + Shift + O

Puede salvarte la vida, a mi me la salvó ;)

Curso Android

Buenas de nuevo!

Se que he tardado mucho en volver a escribir. He estado liado con proyectos web en los que he aprendido a desarrollar con CakePHP[1], un framework de PHP que me ha gustado enormemente. Simplifica muchísimo las tareas comunes y tiene muchas cosas implementadas que se usan comúnmente y que funcionan sin mucho esfuerzo, pero bueno, eso es para otro blog.
A ver si poco a poco retomo el blog de light byte :)

Sobre Android:

Quiero decir que estoy en un curso de Android en la Universidad Rey Juán Carlos[2] impartido por LibreSoft[3]. El curso se imparte los viernes de 16:00 a 21:00 y el tiempo se pasa volando. Ya llevamos 4 sesiones y tengo unas ganas tremendas de que llegue el próximo viernes para aprender más cosas.

Hasta ahora hemos visto bastantes cosas, la mayoría ya las había visto de forma autodidacta haciendo los ejemplos de la web de android[4]. Pero me gusta repasar conceptos y corregir fallos.
Algunas cosas que me han llamado la atención:

  • Que Android es una plataforma de software libre que no sigue al pie de la letra la filosofía de software libre, ya que Google es quien modifica el código y no permite modificaciones de fuera.

  • Que se puede programar directamente sobre las librerías de C que van sobre el kernel de linux por medio del NDK[5] y así obtener más velocidad, pero tiene la parte negativa de que nadie te asegura que vaya a funcionar igual en posteriores versiones de Android. En cambio si desarrollas sobre el SDK (la API de Android) te aseguras que tu aplicación funcione en posteriores versiones.

    En la siguiente imagen se puede ver en la parte azul el API de Android para trabajar de forma estandar (SDK) y en la parte verde, las librerías con las que trabajar en el NDK. Esto del NDK no lo he probado así que no se más jeje.


  • Vimos que hay varios markets pero que el market de Android no permite que se puedan descargar otra aplicación market de un tercero.

  • Como construir layouts complejos usando los LinearLayout, RelativeLayout, TabLayout, etc.

  • Como crear menús contextuales y de layout.

  • Como usar los Intents para llamar a otros layouts, digamos que es la forma de Android de abrir "ventanas" o "vistas" y con los que puedes pasar parámetros al layout que se llama.
  • Como crear nuestro propio Adapter para rellenar los ListView.

  • Como crear una View por código desde un recurso usando el LayoutInflater:
    LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    view = inflater.inflate(R.layout.advanced_list, null);
  • Como usar los mapas de Google así como obtener una clave para poder trabajar con los mapas[6].
    Aunque esto merece un post aparte diré que es necesario unos pasos básicos para no desesperarse:
    • En el AndroidManifest.xml añadir la siguiente línea dentro de la etiqueta "Application":
      <uses-library android:name="com.google.android.maps" />
    • Y añadir también en la etiqueta "manifest" los permisos:
      <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
      <uses-permission android:name="android.permission.INTERNET"></uses-permission>

Bueno, me dejo muchos detalles de como hacer las cosas, pero no se puede hacer todo en un día ;)


Enlaces:
[1] CakePHP
[2] Universidad Rey Juán Carlos
[3] LibreSoft 
[4] Android developers
[5] NDK
[6] Google Projects for Android: Google APIs
Related Posts Plugin for WordPress, Blogger...