Asus ZenFone 2

(0 comentarios)

El ZenFone 2 llegó a España hace un par de semanas, aunque en Asia ya llevan disfrutando de él desde Marzo. Se trata de un gama media-alta a un precio muy ajustado, que se hizo famoso por ser el primer dispositivo en incluir 4GB de RAM.

El mes pasado, como ya os comenté, tuve la oportunidad de asistir a su presentación en el Palacio de Cibeles de Madrid, evento del que me fuí con el móvil bajo el brazo y del que paso a comentaros mis impresiones.

[Pulsa para continuar]

Malware preinstalado en móviles Xiaomi, Huawei y Lenovo

(0 comentarios)

Hoy me he despertado con la noticia de que una firma de seguridad alemana ha descubierto malware preinstalado en distintos teléfonos de algunas empresas chinas populares, como Xiaomi, Huawei y Lenovo. No parece que las marcas hayan tenido ningún tipo de responsabilidad, pero independientemente de ello, si pensáis comprar móviles de estos fabricantes, os aconsejaría que tuvierais mucho cuidado con los intermediarios.

Este es un problema que se está convirtiendo en algo demasiado común y normalizado, y que tiene muy difícil solución, porque el consumidor medio no está demasiado informado y tampoco valora demasiado su privacidad.

Hexa Clock Live Wallpaper: un reloj RGB para Android

(4 comentarios)

Hace un par de semanas estuve jugando un poco con la API de fondos de pantalla animados para Android, lo que ellos llaman live wallpapers. Como resultado, cree una tonta aplicación que cambia el color del fondo de pantalla al color resultante de expresar la hora como un número hexadecimal RGB, al estilo de la web Hexclock.

¡Echadle un vistazo!

Hexa clock live wallpaper, un fondo de pantalla animado para Android

¡Nexus 4 para todos!

(16 comentarios)

Da igual que te acabes de comprar un móvil, que ya tengas dos Nexus 4, o que vivas en algún lugar recóndito sin cobertura. ¿Cómo no vas a comprarte un Nexus 4 ahora que Google ha rebajado 100€ más su ya de por si escandaloso precio?

¿199€ por uno de los mejores teléfonos del mercado? ¿por un procesador quad-core y 2GB de RAM? ¿por un Android actualizado siempre a la última versión y sin capas extra que lo ralenticen? Parece mejor negocio que la famosa compra de Manhattan por unos cuantos abalorios.

Desarrollo rápido en Android con anotaciones

(4 comentarios)

Si llevas un tiempo programando en Java recordarás esas decenas de líneas de código de inicialización y aquellos enormes XML de configuración con los que teníamos que lidiar en frameworks como Spring, JPA o JSF antes de que se popularizaran las anotaciones. En Android esa tendencia todavía no ha impuesto, pero os alegrará saber que sí existen librerías externas con las que reducir enormemente el código auxiliar y centrarnos en lo que realmente importa.

La opción más interesante es AndroidAnnotations, ya que es muy completa, no impone penalización alguna en el rendimiento y no nos obliga a que nuestras actividades extiendan de una cierta clase, lo que al carecer Java de herencia múltiple complicaría ligeramente el uso de librerías como ActionBarSherlock. ¿Suena bien? Entonces genera un proyecto con AndroidAnnotations en AndroidKickstarR y sigue leyendo; te aseguro que no te vas a arrepentir.

Asociar un layout a una actividad o fragmento

Sin AndroidAnnotations:

public class Actividad extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.actividad);
    }
}

Con AndroidAnnotations podemos usar la anotación @EActivity (de enhanced activity o actividad mejorada) y pasarle el identificador del layout:

@EActivity(R.layout.actividad)
public class MyActivity extends Activity {}

De forma parecida a las actividades, con la anotación @EFragment podemos obviar el método onCreateView del fragmento. Sin AndroidAnnotations:

public class Fragmento extends Fragment {
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragmento, container, false);
        return view;
    }
}

Con AndroidAnnotations:

@EFragment(R.layout.fragmento)
public class Fragmento extends Fragment {
}

Inyección de vistas

Sin AndroidAnnotations:

public class Actividad extends Activity {
	Button btnGuardar;
	EditText txtNombre;

	@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.actividad);
		
		btnGuardar = (Button) findViewById(R.id.btnGuardar);
		txtNombre = (EditText) findViewById(R.id.txtNombre);
    }
}

Con AndroidAnnotations usaríamos la anotación @ViewById pasando como parámetro el identificador de la vista

@EActivity(R.layout.actividad)
public class Actividad extends Activity {
	@ViewById(R.id.btnGuardar)
	Button btnGuardar;
	
	@ViewById(R.id.txtNombre)
	EditText txtNombre;
}

Si el nombre de la variable es igual al identificador de la vista el parámetro se puede obviar:

@EActivity(R.layout.actividad)
public class Actividad extends Activity {
	@ViewById Button btnGuardar;
	@ViewById EditText txtNombre;
}

También podemos inyectar fragmentos con @FragmentById

@EActivity(R.layout.actividad)
public class Actividad extends Activity {
	@ViewById Button btnGuardar;
	@ViewById EditText txtNombre;
	@FragmentById Fragmento fragmento;
}

Manipular las vistas

Si usamos @ViewById para inyectar la vistas, por la manera que tiene de funcionar AndroidAnnotations, no tendremos todavía las instancias asociadas en onCreate, por lo que si tenemos que hacer algo con las vistas tendremos que anotar uno o varios métodos con @AfterViews. Esto, que a alguno le puede parecer un incordio, a mí personalmente me gusta, porque prefiero extraer el resto del código a otros métodos siguiendo el Principio de Responsabilidad Única.

De esta forma un código como

public class Actividad extends Activity {
	TextView txtVersion;
	TextView txtFecha;

	@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.actividad);
		
		txtVersion = (TextView) findViewById(R.id.txtVersion);
		txtFecha = (TextView) findViewById(R.id.txtFecha);
		
		establecerVersion();
		establecerFecha();
    }
	
	void establecerVersion() {
		try {
			PackageInfo infoPaquete = getPackageManager().getPackageInfo(getPackageName(), 0);
			txtVersion.setText(infoPaquete.versionName);
		} catch(NameNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	void establecerFecha() {
		DateFormat formato = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
		Date fecha = new Date();
		String strFecha = formato.format(fecha);
		txtFecha.setText(strFecha);
	}
}

se convertiría en lo siguiente

@EActivity(R.layout.actividad)
public class Actividad extends Activity {
	@ViewById TextView txtVersion;
	@ViewById TextView txtFecha;
	
	@AfterViews
	void establecerVersion() {
		try {
			PackageInfo infoPaquete = getPackageManager().getPackageInfo(getPackageName(), 0);
			txtVersion.setText(infoPaquete.versionName);
		} catch(NameNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	@AfterViews
	void establecerFecha() {
		DateFormat formato = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
		Date fecha = new Date();
		String strFecha = formato.format(fecha);
		txtFecha.setText(strFecha);
	}
}

Eventos

Android cuenta con un atributo XML android:onClick con el que es muy rápido y sencillo asociar un listener a un evento clic. El equivalente en AndroidAnnotations es la anotación @Click, a la que se le pasa el identificador de la vista a la que se asocia el listener (se puede obviar en caso de que el nombre del método coincida con el identificador de la vista o que sea igual pero con el sufijo Clicked).

@EActivity(R.layout.actividad)
public class Actividad extends Activity {
	@Click(R.id.button1)
	void mostrarVersion() {
		// ...
	}

	@Click
	void mostrarFecha() {
		// ...
	}

	@Click
	void guardarClicked() {
		// ...
	}
}

En este caso la ventaja de las anotaciones no es tan obvia; quizás el poder ver la asociación entre la vista y el método en un golpe de vista. Tiene mayor interés el que podamos asociar listeners para unos pocos eventos más de forma igual de sencilla, con @LongClick para pulsaciones largas o @TextChange para cambios de texto.

Menús

Con la anotación @OptionsMenu podemos inflar el XML de menú, ahorrándonos sobreescribir onCreateOptionsMenu. Con @OptionsItem asociamos las distintas opciones de menú con distintos listeners, pasando el id de la opción a la anotación (también se puede obviar el id si coincide con el nombre del método, o si es igual pero con el sufijo Selected).

Versión sin anotaciones:

public class Actividad extends Activity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.actividad);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.actividad, menu);
		return true;
	}

	
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
			case R.id.actualizar:
				actualizar();
				return true;
			case R.id.acercaDe:
				acercaDeSelected();
				return true;
			default:
			  return false;
		}
	}

	
	void actualizar() {
		// ...
	}	

	
	void acercaDeSelected() {
		// ...
	}	
}

Versión con anotaciones:

@EActivity(R.layout.actividad)
@OptionsMenu(R.menu.actividad)
public class Actividad extends Activity {
	@OptionsItem(R.id.actualizar)
	void actualizar() {
		// ...
	}	

	@OptionsItem
	void acercaDeSelected() {
		// ...
	}	
}

Inyección de recursos

Para cada tipo de recurso existe una anotación que permite inyectar dicho recurso en nuestra clase pasándole simplemente el identificador (o sin pasarle nada si el nombre del recurso coincide con el de la variable): AnimationRes, BooleanRes, ColorRes, ColorStateListRes, DimensionPixelOffsetRes, DimensionPixelSizeRes, DimensionRes, DrawableRes, HtmlRes, IntArrayRes, IntegerRes, LayoutRes, MovieRes, StringArrayRes, StringRes, TextArrayRes, TextRes.

De esta forma en lugar de:

String nombreApp = getResources().getString(R.string.nombreApp);

simplemente podríamos escribir:

@StringRes String nombreApp;

Además, en el caso concreto de que queramos obtener una cadena HTML de un archivo de recurso y establecerla como texto en un TextView, podemos llevar a cabo ambos pasos con una simple anotación @FromHtml.

Hilos de ejecución

¿Harto de usar AsyncTask o similares para ejecutar un cierto código en un hilo distinto del principal o de interfaz de usuario?

void ejecutarTareaSegundoPlano(URL urls) {
	new AsyncTask<URL, Integer, Long> {
		protected Long doInBackground(URL... urls) {
			int numUrls = urls.length;
			Long tamanyoDescarga = 0;
			for (int i = 0; i < numUrls; i++) {
				tamanyoDescarga += ClienteHttp.descargar(urls[i]);
				publishProgress((int) ((i / (float) numUrls) * 100));
			}
			return totalSize;
		}

		protected void onProgressUpdate(Integer... progreso) {
			actualizarProgreso(progreso[0]);
		}

		protected void onPostExecute(Long tamanyoDescarga) {
			mostrarDialogo("Descargados " + tamanyoDescarga[0] + " bytes");
		}
	}.execute();
}

¿Qué tal si pudieras usar la anotación @Background para indicar que un método debe ejecutarse en un hilo en segundo plano y @UiThread para que se ejecute en el hilo de interfaz de usuario? De esta forma el ejemplo anterior se reduciría a:

@Background
void descargarArchivos(URL urls) {
	int numUrls = urls.length;
	Long tamanyoDescarga = 0;
	for (int i = 0; i < numUrls; i++) {
		tamanyoDescarga += ClienteHttp.descargar(urls[i]);
		actualizarEstadoDescarga((int) ((i / (float) numUrls) * 100));
	}
	mostrarDialogoFinDescarga(tamanyoDescarga);
}

@UiThread
void actualizarEstadoDescarga(int progreso) {
	actualizarProgreso(progreso);
}

@UiThread
void mostrarDialogoFinDescarga(Long tamanyoDescarga) {
	mostrarDialogo("Descargados " + tamanyoDescarga + " bytes");
}

Guardar y recuperar el estado

Esta es otra de esas tareas repetitivas que suponen gran cantidad de código. Comparemos una implementación típica con su correspondiente versión con anotaciones.

public class Actividad extends Activity {
    Jugador jugador;
    int puntuacion;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        if(savedInstanceState != null) { 
            jugador = (Jugador)savedInstanceState.getSerializable("jugador");
			puntuacion = savedInstanceState.getInt("puntuacion");
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putSerializable("jugador", jugador);
        outState.putInt("puntuacion", puntuacion);
    }
}
@EActivity(R.layout.actividad)
public class Actividad extends Activity {
    @InstanceState
    Jugador jugador;

    @InstanceState
    int puntuacion;
}

Otras funcionalidades de interés

  • @Trace nos permite trazar la ejecución de un método escribiendo una entrada en el log cuando se entra y se sale del método.
  • @HierarchyViewerSupport permite utilizar la herramienta Hierarchy Viewer aunque no dispongamos de un teléfono con permisos de root o de desarrollo
  • @RoboGuice nos permite integrar AndroidAnnotation con el framework de inyección de dependencias del mismo nombre (basado en Guice, de Google)
  • @OrmLiteDao nos permite integrar AndroidAnnotation con el framework de mapeo objeto-relacional OrmLite
  • @EView y @EViewGroup facilitan la creación de vistas personalizadas
  • @SystemService nos permite inyectar un servicio del sistema


Cómo añadir el código fuente de Android a Eclipse

(5 comentarios)

Cuando se programa con alguna librería o framework de terceros siempre es fundamental poder contar con su código fuente, ya sea para aprender o para ver cómo funcionan las cosas por dentro. Android no es una excepción; por eso lo primero que hago nada más instalar Eclipse con las Android Developer Tools es añadir el código fuente del SDK. De otra forma, al intentar ver el código de cualquier clase de Android Eclipse nos mostrará una pantalla similar a esta, con el código decompilado en lugar del código fuente:

[Pulsa para continuar]

Tutorial de Android en español

(35 comentarios)

Me ha llevado algo más de tiempo de lo que preveía, pero al fin he terminado de traducir todos los tutoriales del sitio oficial de desarrolladores de Android que enseñan los conceptos básicos para la creación de aplicaciones. En total son 7 clases, en las que se tratan los siguientes temas:

  1. Construyendo tu primera aplicación
  2. Gestionando el ciclo de vida de la actividad
  3. Soportando distintos dispositivos
  4. Construyendo una interfaz de usuario dinámica con fragmentos
  5. Guardando información
  6. Interactuando con otras aplicaciones
  7. Compartiendo contenido

Traduciendo los tutoriales de Android al español

(26 comentarios)

Tutorial Android en español

Aunque el inglés es un idioma que yo considero que hablo bastante bien (academia, escuela oficial de idiomas, parte de la carrera en inglés…) siempre es agradable poder leer un texto en tu lengua materna. Esto es un problema cuando se trata de documentación técnica, porque las obras de referencia a menudo no se traducen al castellano o tardan mucho en publicarse, y en ocasiones los textos que podemos encontrar en nuestras tiendas cuentan con muy poca calidad.

En su día ya intenté aportar mi granito de arena publicando el libro “Python para todos” como Creative Commons, una iniciativa que no salió demasiado mal. Desde hace ya bastante tiempo tengo un especial interés por Android, y cuando empecé a dar mis primeros pasos comprobé que la situación no era mucho mejor.

Desde que Google creara el sitio de Android Training este ha sido un recurso que siempre ha estado muy bien considerado por los desarrolladores, hasta el punto de que muchos lo recomiendan como la mejor forma de comenzar con Android. Por eso, y porque una empresa que gana más de 10 000 millones de dólares al año todavía no se ha molestado, me he propuesto traducir estas clases al español, aprovechando su licencia Creative Commons.

Ya podéis encontrar las 3 primeras clases en Formación Android. No os deberían llevar más de 2 horas.

Si tenéis cualquier duda, fallo o sugerencia que comentarme, podéis utilizar, como siempre, el formulario de contacto o los propios comentarios de esta entrada. Y si os gusta la iniciativa y queréis darle un poco de publicidad en las redes sociales, mejor que mejor 😉

Cómo acelerar el emulador de Android

(15 comentarios)

Cuando desarrollamos aplicaciones para móviles o tablets y no tenemos acceso a un dispositivo físico, o queremos probar nuestra aplicación en distintos tamaños de pantalla o densidades tenemos dos alternativas principales: los “simuladores”, como el que incluye el SDK de iOS, y los emuladores, como el del SDK de Android.

[Pulsa para continuar]

Los herejes de Apple empiezan a ver la luz

(32 comentarios)

Guy Kawasaki, el que fuera primer gran evangelista de Apple en aquellos lejanos tiempos del Macintosh, parece que ha visto la luz últimamente: hace casi 1 año que se convirtió en fiel seguidor de Android, la religión única y verdadera. Estas son algunas de sus reflexiones al respecto:

Me enamoré de Android con los smartphones, luego me hice con un Nexus 7 y empecé a usar Android en los tablets. Para mí la gran ironía es que el eslogan de Apple era “Piensa diferente” pero hoy en día si piensas diferente lo buscas es un Android

En Apple se consideran la punta de lanza de los smartphones, ¿cómo es posible que todavía usen una red que es de 10 a 20 veces más lenta (que LTE)?

Otra cosa que me gusta de Android es que no tienen un estúpido cable propietario. Puedo ir a la recepción de cualquier hotel y si he olvidado mi cable siempre tendrán algún micro-USB. Puedo usar el mismo cable en mi Nexus 7 y mi Samsung Galaxy S3. ¡Menudo concepto! Un cable estándar…

No voy a volver, porque ahora pienso que Android es mejor

Página 1 de 41234