Es esta receta explicaré como configurar y activar el KMS (Kernel Mode Setting) con el driver Intel i915 en una HP Pavilion dm4 . Las instrucciones están hechas para Debian Wheezy (testing a la fecha) y requiere de un kernel >= 2.6.29.

Instalar dependencias

Suponiendo que tenemos Xorg instalado y corriendo (quizás funcionando con el driver vesa) procedemos instalar el driver intel y sus dependencias:
# aptitude install libgl1-mesa-glx libglu1-mesa xserver-xorg-video-intel mesa-utils

Activar el KMS

Luego vamos al archivo /etc/modprobe.d/i915-kms.conf y agregamos la línea:
options i915 modeset=1

Regeneramos la imagen del kernel con:
# update-initramfs -u

Editamos el archivo /etc/default/grub y modificamos esta línea:
GRUB_CMDLINE_LINUX_DEFAULT="quiet i915.modeset=1 video=LVDS-1:e"

El parámetro i915.modeset=1 habilita el KMS al momento del booteo y para que la pantalla no se quede en negro luego de cargar el módulo, debemos agregar el parámetro video=LVDS-1:e.

Es importante no cargar ningún otro driver para framebuffer que no sea el de Intel y eliminar de los parámetros de booteo cualquier opción del tipo vga=xxx o video=xxx.

El parámetro video=LVDS-1:e tiene una razón de ser muy particular. El BIOS de esta máquina tiene un bug; cuando inicia, indica erróneamente que la tapa de la laptop está cerrada. El kernel, basándose en esa información, manda a apagar la pantalla y por eso todo se queda en negro, no es que se congela ni que deja de funcionar. Pueden corroborar esto cerrando y abriendo la tapa de la laptop cuando se apaga. Verán que el video vuelve mágicamente y que el equipo no se había detenido, seguía funcionando pero a ciegas.

Es bien conocido que el kernel no usa el BIOS para casi ninguna de sus tareas, sin embargo a partir del kernel 2.6.32 los desarrolladores decidieron "escuchar" al BIOS en este tipo de eventos, así que hasta que no se masifique el patch que corrige la situación debemos aplicar este correctivo.

Si desean más información pueden revisar el reporte y la resolución del bug en Launchpad o el reporte del error en fredesktop.org

Luego de ese paréntesis técnico continuamos con nuestra configuración. Reconfiguramos el grub para que se apliquen los cambios anteriores:
# update-grub

Configuración de Xorg

Lo siguiente es crear y personalizar el archivo de configuración de Xorg.

A partir de la versión 1.8, Xorg ya no necesita archivos de configuración. En lugar de eso intenta detectar y configurar todo el hardware (video y dispositivos de entrada) por si mismo. Sin embargo existen casos especiales que requieren algunos "ajustes". Este es uno de esos casos.

Procedemos entonces a detener el servidor X. Si tenemos un entorno de escritorio basta con detener el gestor de sesión (gdm, kdm, slim, xdm, etc), sino matamos las X.

Hecho esto pasamos a ejecutar:
# Xorg -configure

Eso debería generarnos un archivo xorg.conf.new que servirá como base. A ese archivo le editamos la sección "Device" para que nos quede algo como:
Section "Device"
Option "DRI" "True"
Option "Tiling" "True"
Option "XAANoOffscreenPixmaps" "True"
Identifier "Card0"
Driver "intel"
BusID "PCI:0:2:0"
EndSection

Y agregamos al final del archivo la siguiente sección:
Section "Extensions"
Option "Composite" "enable"
EndSection

Observen que indicamos el driver de video y algunas opciones para mejorar el desempeño gráfico. Si conocen otras opciones (que apliquen para tarjetas Intel) también pueden agregarlas acá.

Con esto terminamos nuestra configuración del servidor X.

Reiniciar

Reiniciamos y ya deberíamos disfrutar de nuestro video usando KMS. Verán que la transición entre modos de video es casi instantánea y el parpadeo se redujo considerablemente. Además de que compiz y todas esas yerbas aromáticas se ven con una suavidad asombrosa.

Deshabilitar el KMS

Si desean deshabilitar el KMS basta con desactivar el modeset en la línea:
GRUB_CMDLINE_LINUX_DEFAULT="quiet i915.modeset=0 video=LVDS-1:e"

Reconfiguramos el grub:
# update-grub

Y KMS desactivado.

Espero que esta receta les haya servido de ayuda. En un próximo post explicaré cómo configurar el Touchpad Synaptics.

Fuentes:
¿No les ha pasado que a veces encuentran en Youtube videos que son unas verdaderas joyas musicales y les gustaría tenerlos en su colección musical? Bueno con este truco es muy fácil hacerlo.

Primero instalamos el Youtube Downloader. Desde Debian sería:
# aptitude install youtube-dl
Instalamos el ffmpeg (en caso de no tenerlo):
# aptitude install ffmpeg
Luego descargamosel video desde Youtube y extraemos el audio:
$ youtube-dl --extract-audio
Eso nos generará un archivo .aac, ahora procedemos a convertirlo a mp3 (o al formato de nuestra preferencia):
$ ffmpeg -i .aac -ar 22050 -ab 32 .mp3
Y ya podremos disfrutar de la pieza de audio en nuestro reproductor favorito a partir del video de Youtube
RVM (Ruby Version Manager) es una fantástica herramienta que te permite gestionar muchas versiones de Ruby (y de sus gemas) en un mismo equipo. Las gemas se manejan mediante contenedores (gemsets), allí puedes instalar lo que desees sin afectar el resto de los componentes. Es un principio muy parecido al de las máquinas virtuales.

La receta es para Debian pero se puede aplicar para cualquier distro, solo hay que tener en cuenta los nombres de los paquetes a instalar.

Comencemos entonces con las dependencias. Necesitamos git, las herramientas básicas para compilar, los fuentes del readline y del ssl:

# aptitude install libreadline5-dev git curl build-essential libssl-dev

Luego, como usuario ejecutamos el siguiente script:

$ bash < <(curl -s https://rvm.beginrescueend.com/install/rvm)

Ese script descarga rvm de git, lo compila y lo instala. Antes de usarlo debemos agregar una línea a nuestro .bash_profile, para eso ejecutamos:

$ echo '[[ -s "$HOME/.rvm/scripts/rvm" ]] && . "$HOME/.rvm/scripts/rvm" # Load RVM function' >> ~/.bash_profile

Hacemos un:

$ source ~/.bash_profile

Y verificamos que todo haya salido bien:

$ type rvm | head -1

El resultado de ese comando debería ser: rvm es una función. Si no obtenemos ese resultado algo ha ido mal. Les recomiendo entonces revisar la documentación de instalación o la página de problemas solucionados.

Ahora podemos ejecutar rvm como un comando más de consola. Instalemos un par de paquetes que nos harán falta antes de instalar una versión de Ruby:

$ rvm package install openssl
$ rvm package install readline


Instalamos una versión de Ruby (por ejemplo: 1.8.7):

$ rvm install 1.8.7

Y configuramos la versión que deseamos usar por defecto en el sistema:

$ rvm use 1.8.7 --default
Using /home/tu_usuario/.rvm/gems/ruby-1.8.7-p334


Ahora podemos crear gemsets a placer, por ejemplo:

$ rvm gemset create pruebas1
'pruebas1' gemset created (/home/tu_usuario/.rvm/gems/ruby-1.8.7-p334@pruebas1).


Notese que el @ en el mensaje anterior nos indica que el gemset ha sido asociado a la versión 1.8.7 de Ruby que habíamos instalado (y seleccionado para usar) previamente. Ahora instalemos otro gemset de pruebas para entender la magia del asunto.

$ rvm gemset create pruebas2
'pruebas2' gemset created (/home/tu_usuario/.rvm/gems/ruby-1.8.7-p334@pruebas2).


Podemos movernos a través de los gemsets usando el comando use con la siguiente forma:

$ rvm use 1.8.7@pruebas1
Using /home/tu_usuario/.rvm/gems/ruby-1.8.7-p334 with gemset pruebas1


Ahora probemos instalar una gema en el contenedor 'pruebas1':

$ gem install xml-simple --no-rdoc --no-ri
Fetching: xml-simple-1.0.15.gem (100%)
Successfully installed xml-simple-1.0.15
1 gem installed


Particularmente uso los argumentos --no-rdoc --no-ri para evitar la instalación de la documentación y otros archivos adicionales que no utilizo y demoran considerablemente la puesta a punto de la gema.

Veamos entonces qué tenemos ahora en 'pruebas1':

$ gem list --local

*** LOCAL GEMS ***

rake (0.8.7)
xml-simple (1.0.15)


Una nueva gema instalada en nuestro gemset. Y en 'pruebas2' ¿qué tenemos?:

$ rvm use 1.8.7@pruebas2
Using /home/tu_usuario/.rvm/gems/ruby-1.8.7-p334 with gemset pruebas2

$ gem list --local

*** LOCAL GEMS ***

rake (0.8.7)


¡Oh! No tenemos nada instalado. Eso quiere decir que nuestros contenedores están aislados uno del otro y que podemos instalar cosas que cada uno de ellos sin temor a romper algo en el otro (siempre teniendo cuidado del gemset que está en uso).

Si en algún momento dañamos un gemset basta con ejecutar:

$ rvm gemset delete pruebas1
WARN: Are you SURE you wish to remove the entire gemset directory 'pruebas1' (/home/tu_usuario/.rvm/gems/ruby-1.8.7-p334@pruebas1)?
(anything other than 'yes' will cancel) >


Respondemos yes y listo, desaparece el gemset con todo lo que tenía adentro.

Muy bonito todo, pero se preguntarán ¿Cómo le digo a un determinado proyecto que use un gemset específico? ¿O es que debo especificarle manualmente que gemset utilizará cada vez que vaya a ejecutarlo?

Pues la respuesta es muy simple, basta con crear un archivo .rvmrc en la raíz del proyecto con algo parecido a esto:

rvm use 1.8.7@pruebas2

Y desde ese momento, todo lo que está dentro de esa carpeta usará la versión del Ruby y el gemset especificado en el archivo.


NOTA: Es importante aclarar que Ruby, RubyGems, las gemas o cualquier otras cosa relacionada NO debe instalarse usando la paquetería de la distribución. TODO debe manejarse a través RVM, de lo contrario corromperemos toda la instalación.

Espero que esta receta les sea de utilidad, a mi me ha cambiado la vida xD

Me ocurrió hace unos días que actualicé mi Debian y repentinamente me quedé sin conexión inalámbrica. Uso Debian Testing (Wheezy para la fecha) en una HP Pavilion dv2000 y la tarjeta de red inalámbrica es una Intel PRO/Wireless 4965 AG.

Leyendo y leyendo diferentes manuales todos afirmaban que con solo instalar el paquete firmware-iwlwifi del repo non-free la cosa funcionaba a la perfección y me constaba porque así lo había hecho en un principio. Sin embargo, luego de actualizar no anduvo más y lo curioso es que el lspci me devolvía señales de vida:

07:00.0 Network controller: Intel Corporation PRO/Wireless 4965 AG or AGN [Kedron] Network Connection (rev 61)

El paquete en efecto estaba instalado:

$ aptitude search iwl | grep ^i
i firmware-iwlwifi - Binary firmware for Intel Wireless 3945, 4


El lsmod me mostraba los módulos cargados y todo estaba bien:

$ lsmod | grep iwl
iwlagn 122417 0
iwlcore 50368 1 iwlagn
mac80211 160285 2 iwlagn,iwlcore
cfg80211 106889 3 iwlagn,iwlcore,mac80211


Incluso, los binarios del firmware también parecían estar en orden:

# find / -name "*ucode*"
/sys/module/iwlagn/parameters/ucode_alternative
/lib/firmware/iwlwifi-6050-5.ucode
/lib/firmware/iwlwifi-3945-2.ucode
/lib/firmware/iwlwifi-6000g2b-5.ucode
/lib/firmware/iwlwifi-5000-5.ucode
/lib/firmware/iwlwifi-5000-1.ucode
/lib/firmware/iwlwifi-4965-2.ucode
/lib/firmware/iwlwifi-5000-2.ucode
/lib/firmware/iwlwifi-4965-1.ucode
/lib/firmware/iwlwifi-6000-4.ucode
/lib/firmware/iwlwifi-6000g2a-5.ucode
/lib/firmware/iwlwifi-1000-3.ucode
/lib/firmware/iwlwifi-6050-4.ucode
/lib/firmware/iwlwifi-3945-1.ucode
/lib/firmware/iwlwifi-5150-2.ucode
/lib/firmware/iwlwifi-100-5.ucode


Luego intento ver el log del kernel y me encuentro con algo que me dio algunas pistas:

# tail -f /var/log/syslog
May 24 23:03:31 mpn82 kernel: [ 6214.119061] iwlagn: Intel(R) Wireless WiFi Link AGN driver for Linux, in-tree:
May 24 23:03:31 mpn82 kernel: [ 6214.119064] iwlagn: Copyright(c) 2003-2010 Intel Corporation
May 24 23:03:31 mpn82 kernel: [ 6214.119140] iwlagn 0000:07:00.0: PCI INT A -> GSI 19 (level, low) -> IRQ 19
May 24 23:03:31 mpn82 kernel: [ 6214.119153] iwlagn 0000:07:00.0: setting latency timer to 64
May 24 23:03:31 mpn82 kernel: [ 6214.119187] iwlagn 0000:07:00.0: Detected Intel(R) Wireless WiFi Link 4965AGN, REV=0x4
May 24 23:03:31 mpn82 kernel: [ 6214.157779] iwlagn 0000:07:00.0: device EEPROM VER=0x36, CALIB=0x5
May 24 23:03:31 mpn82 kernel: [ 6214.157782] iwlagn 0000:07:00.0: Device SKU: 0Xb
May 24 23:03:31 mpn82 kernel: [ 6214.157979] iwlagn 0000:07:00.0: Tunable channels: 11 802.11bg, 13 802.11a channels
May 24 23:03:31 mpn82 kernel: [ 6214.158062] iwlagn 0000:07:00.0: irq 46 for MSI/MSI-X
May 24 23:03:31 mpn82 NetworkManager[1140]: found WiFi radio killswitch rfkill4 (at /sys/devices/pci0000:00/0000:00:1c.3/0000:07:00.0/ieee80211/phy2/rfkill4) (driver )
May 24 23:03:31 mpn82 kernel: [ 6214.161805] iwlagn 0000:07:00.0: loaded firmware version 228.61.2.24
May 24 23:03:31 mpn82 kernel: [ 6214.162128] ieee80211 phy2: Selected rate control algorithm 'iwl-agn-rs'
May 24 23:03:31 mpn82 NetworkManager[1140]: SCPlugin-Ifupdown: devices added (path: /sys/devices/pci0000:00/0000:00:1c.3/0000:07:00.0/net/wlan0, iface: wlan0)
May 24 23:03:31 mpn82 NetworkManager[1140]: SCPlugin-Ifupdown: device added (path: /sys/devices/pci0000:00/0000:00:1c.3/0000:07:00.0/net/wlan0, iface: wlan0): no ifupdown configuration found.
May 24 23:03:31 mpn82 NetworkManager[1140]: (wlan0): driver supports SSID scans (scan_capa 0x01).
May 24 23:03:31 mpn82 NetworkManager[1140]: (wlan0): new 802.11 WiFi device (driver: 'iwlagn' ifindex: 6)
May 24 23:03:31 mpn82 NetworkManager[1140]: (wlan0): exported as /org/freedesktop/NetworkManager/Devices/3
May 24 23:03:31 mpn82 NetworkManager[1140]: (wlan0): now managed
May 24 23:03:31 mpn82 NetworkManager[1140]: (wlan0): device state change: 1 -> 2 (reason 2)
May 24 23:03:31 mpn82 NetworkManager[1140]: (wlan0): bringing up device.
May 24 23:03:31 mpn82 NetworkManager[1140]: (wlan0): deactivating device (reason: 2).


1.- El firmware se estaba cargando con la versión más actualizada según la página de Intel
May 24 23:03:31 mpn82 kernel: [ 6214.161805] iwlagn 0000:07:00.0: loaded firmware version 228.61.2.24

2.- Por alguna razón la interfaz se estaba apagando luego que cargaba el NetworkManager

Decidí buscar un poco en internet y me conseguí con este reporte de bug en Red Hat que involucraba al NetworkManager, la interfaz wireless y un mensaje de error muy similar al mío.

Probé entonces con:

# rfkill list
0: hp-wifi: Wireless LAN
Soft blocked: yes
Hard blocked: no
2: hp-bluetooth: Bluetooth
Soft blocked: yes
Hard blocked: no
4: phy2: Wireless LAN
Soft blocked: yes
Hard blocked: yes


Jum... phy2 y hp-wifi bloqueados por software, adicionalmente phy2 bloqueado por hardware. Raro, raro.

Hago un:

# rfkill unblock 0 && rfkill unblock 4

Y voilá, volvió a enceder el led de la interfaz inalámbrica e inmediatamente se conectó a internet :D

Cosas tontas pero que te salvan la vida. Espero que les sea de utilidad

Si usando rvm, intentas abrir una consola de Rails (con rails c o con script/console) y te escupe un error como este:

no such file to load -- readline (LoadError)

Entonces sigue estos pasos y resolverás el problema.

Primero, debemos instalar el paquete del readline en rvm (y no en el Sistema Operativo). Para eso removemos la versión actual de Ruby que podamos tener:

$ rvm remove 1.8.7

Instalamos el paquete readline:

$ rvm install package

E instalamos Ruby pero indicándole la ubicación del paquete readline:

$ rvm install 1.8.7 --with-readline-dir=$rvm_path/usr

Acto seguido, entramos a la carpeta en donde rvm almacena los fuentes de las extensiones de Ruby, específicamente del readline. En mi caso:

$ cd ~/.rvm/src/ruby-1.8.7-p302/ext/readline

Luego (como root) instalamos las dependencias necesarias. En Debian sería:

# aptitude update
# aptitude install libreadline5-dev


Procedemos (como usuario) a compilar e instalar la extensión en cuestión:

$ ruby extconf.rb
$ make
$ make install


Y con eso ya deberíamos disfrutar nuevamente de la consola interactiva de Rails sin problemas.

En estos días estaba usando mi netbook y me di cuenta que al hacer tap sobre el touchpad no se ejecutaba el click del ratón y no fue hasta hoy que me digné a buscar la solución. Es tan simple como agregar una línea en un archivo de texto.

Buscamos el archivo /etc/modprobe.d/options.conf, si no existe lo creamos y copiamos la siguiente línea:

options psmouse proto=imps

Luego hacemos (como root):

# modprobe -r psmouse
# modprobe psmouse proto=imps


Y a disfrutar del tap xD
Trabajando con Ruby On Rails me ha tocado escribir código usando HAML. Particularmente no me agrada mucho (entre otras cosas porque no tiene soporte multilínea, porque no identa correctamente las cadenas de texto plano, porque agrega otra capa más de interpretación a la aplicación, etc) pero cuando toca usarlo es bueno hacerlo con un buen soporte. Y cuando hablo de soporte me refiero al resaltado de sintaxis.

Para escribir código usualmente uso un editor de texto (Gedit o Geany), así que en ésta receta explicaré como agregar soporte para el resaltado de sintaxis en Gedit.

Primero agregamos soporte para que las extensiones usadas comúnmente en Rails sean reconocidas por el sistema. Abrimos una terminal y escribimos:

wget http://dl.dropbox.com/u/16349833/rails.xml 
sudo cp rails.xml /usr/share/mime/packages/rails.xml
sudo update-mime-database /usr/share/mime

Luego agregamos los archivos de definición de sintaxis en la carpeta del sourceview de GTK ejecutando:

wget http://dl.dropbox.com/u/16349833/gedit_rails_syntax.zip
sudo unzip gedit_rails_syntax.zip -d /usr/share/gtksourceview-2.0/language-specs


Ahora con nuestro editor de texto favorito (y como root) abrimos el archivo /usr/share/gtksourceview-2.0/language-specs/ruby.lang para modificar el sourceview de GTK y agregar soporte para nuevas extensiones. Buscamos la línea:

*.rb

Y la cambiamos por:

*.rb;*.rake;*.rjs

Por último, abrimos el archivo /usr/share/gtksourceview-2.0/language-specs/html.lang y buscamos la línea que dice:

*..html;*.htm

Y la cambiamos por:

*.html;*.htm;*.erb;*.rhtml

Cerramos todas las instancias de Gedit y al abrir de nuevo ya nuestro código HAML debería verse resaltado.


Existen recetas que instalan una serie de plugins (con soporte para haml, rjs, etc) y te dejan al Gedit como TextMate, pero como no me gusta TextMate entonces prefiero hacerlo a patica xD

Espero que la receta les haya servido de ayuda.

Referencias:
http://groups.google.com/group/haml/browse_thread/thread/6c8babd81a46b6b8/b5100d80d9182c71?pli=1
http://blog.adsdevshop.com/2008/04/19/erb-syntax-highlighting-in-gedit/
En la entrega anterior expliqué como instalar el ambiente de desarrollo para trabajar con Android. Ahora explicaré algunos fundamentos necesarios para poder entrar en calor.

Podemos decir que Android está compuesto por varias capas (muy al estilo del modelo OSI).

Esas capas las podemos diferenciar en 5 grupos:

  • Capa 1 - Kernel: La base de Android es sólida como una roca. Claro, esa base es el kernel Linux. Android usa Linux para manejar todo lo relacionado con el hardware (drivers), gestionar la memoria, los procesos y muchas otras tareas operativas. Sin embargo nuestra aplicación nunca tocará el kernel.
  • Capa 2 - Librerías nativas: La siguiente capa que se ubica por encima del kernel son las librerías nativas. Allí tenemos una serie de herramientas que vienen precompiladas por el fabricante y que nos permiten manejar desde renderizado web hasta bases de datos.
  • Capa 3 - Núcleo: Sobre ésta capa tenemos el núcleo de Android. Allí reside la máquina virtual Dalvik y las librerías de la plataforma.
  • Capa 4 - Framework para aplicaciones: Más arriba está el conjunto de herramientas que nos permite crear y manejar las aplicaciones, notificaciones, recursos y muchas otras cosas.
  • Capa 5 - Aplicaciones: Y por último tenemos la capa de aplicaciones, aquí es donde se encuentran los widgets y todas las aplicaciones que tienen contacto con el usuario.

Ya conocemos un poco mejor la arquitectura de Android, ahora veamos con qué contamos para desarrollar. Parte del framework para aplicaciones son los componentes. Estuadiaremos los más importantes por el momento, ellos son:

  • Activities: Los activities (o actividades) son las interfaces que permiten al usuario interactuar con la aplicación. Generalmente una aplicación está compuesta de muchas actividades. Una actividad puede ser mostrar la lista de contactos y otra puede ser enviar mensajes de texto
  • Intents: Un intent (o como se diría en español, una "intención") no es más que una acción. En Android todas las acciones se manejan con intenciones ;)
  • Services: Es una tarea que se ejecuta en segundo plano, sin interfaz gráfica y sin interacción directa con el usuario. Podemos pensar en el ejemplo típico: un reproductor de música. A todos nos gusta que la música siga sonando incluso si dejamos de ver el reprouctor para pasarnos al navegador web. Eso es un servicio
  • Content Providers: Es un contenedor que permite agrupar un conjunto de datos de una aplicación y ponerlos a disposición de otras aplicaciones. Podemos verlo como una manera de compartir información global entre aplicaciones

Por último vamos a mencionar las fases del ciclo de vida de una aplicación.

Lo primero que debemos entender es que (a diferencia de un sistema operativo de escritorio) en Android una aplicación no está casada con un proceso. En Android existe una sola aplicación que obtiene el foco y se presenta frente al usuario. Mientras ésta aplicación se encuentra en el frente, las demás aplicaciones entran en estados de pausa, detención o incluso, si la memoria es escasa, Android puede llegar a cerrarlas para liberar recursos y sin estar mediando muchas palabras.

Pero no se asusten, si la aplicación es "asesinada" por Android su estado se almacena para que pueda recuperarse cuando el usuario la ejecute nuevamente. Es en este ínterin de cerrar y abrir aplicaciones en que se liberan los procesos. Debemos ver a un proceso como un simple contenedor desechable para las aplicaciones, no más. Siempre ten presente éste comportamiento al momento de diseñar tus aplicaciones.

El ciclo de vida de una aplicación lo podemos ver en la siguiente imagen.


A continuación describo brevemente cada una de sus fases:

  • onCreate(): Se ejecuta la primera vez que la aplicación se muestra. Aquí se pueden realizar toda la inicialización estática (conexiones a bases de datos, creación de interfaces, etc). Recibe un parámetro que puede contener el estado anterior de la aplicación (si fue almacenado correctamente)
  • onStart(): Se ejecuta justo antes de que la aplicación se haga visible al usuario
  • onRestart(): Llamado justo después que la aplicación ha sido detenida. Justo antes de comenzar de nuevo
  • onResume(): Se llamará cuando la aplicación esté lista para interactuar con el usuario. Acá se pueden inicializar cosas como música y animaciones
  • onPause(): Se ejecuta justo antes de que la aplicación pase a segundo plano porque otra aplicación ha sido ejecutada. Este método puede ser lo último que vea tu aplicación antes de morir, pues Android puede matar una aplicación pausado sin previo aviso. Es por eso que este es un buen lugar para guardar el estado de tu aplicación.
  • onStop(): Es llamado cuando la aplicación ya no es visible al usuario y no se necesitará por un rato. Tal como se indicó en el punto anterior, este método es posible que ni siquiera se ejecute
  • onDestroy(): Se llama justo después que la aplicación es destruida. Acá debes hacer el sepelio y esas cosas. Tal como se indicó en el punto anterior, este método es posible que ni siquiera se ejecute

Con toda ésta base teórica podemos decir que estamos listos para empezar a escribir el código de nuestra primera aplicación. Ese será el tema de la próxima entrega.

Para más información sobre éste tema puedes consultar la documentación oficial de Android

¿Cómo desarrollar para Android? - Parte I

Estuve unas cuantas horas investigando sobre la posibilidad de desarrollar con Python sobre Android y a continuación les daré un resumen de los resultados y conclusiones que obtuve.

Acá les dejo el script que usé para probar una parte de los widgets disponibles en la API por si quieren probarlo y echarle un ojo (no me detendré a explicarlo mucho porque el código prácticamente se explica a sí mismo). Además supongo que siguieron los pasos de mi tutorial sobre ¿Cómo desarrollar para Android? y tienen configurado su entorno de desarrollo y saben cómo usar el emulador.

droid = android.Android()

tiempo = droid.dialogGetInput("Escriba la cantidad de tiempo que desea para el demo (10-100)","Tiempo:")
print tiempo

tiempo = int(tiempo[1])
if tiempo < 10: tiempo = 10 elif tiempo > 100:
tiempo = 100

droid.dialogCreateHorizontalProgress('Barra de Progreso', 'Hola, estoy progresando...', tiempo)
droid.dialogShow()
for i in range(tiempo):
time.sleep(0.5)
droid.dialogSetCurrentProgress(i)
droid.dialogDismiss()

droid.dialogCreateSpinnerProgress('Spinner de progreso', 'Mirá, mirá... estoy girando')
droid.dialogShow()
time.sleep(tiempo)
droid.dialogDismiss()

droid.notify('Test de Python' , 'Oh! puedo notificar también')

droid.dialogCreateAlert(title, message)
droid.dialogSetPositiveButtonText('Si')
droid.dialogSetNegativeButtonText('No')
droid.dialogSetNeutralButtonText('Cancelar')
droid.dialogShow()
response = droid.dialogGetResponse().result
print response
droid.makeToast('El resultado de la ejecucion del boton es: %s' %response['which'])

droid.dialogCreateAlert('Selecciona un color')
colores = ('amarillo', 'azul', 'rojo')
droid.dialogSetItems(colores)
droid.dialogShow()
respuesta = droid.dialogGetResponse().result
print respuesta
droid.makeToast('El color seleccionado es: %s' %colores[respuesta['item']])

droid.makeToast('Bueno, chao')


Para correrlo deben instalar algunos paquetes en el cel. Pueden hacerlo con el comando del SDK:

$ adb install /ruta/del/archivo.apk

con los QR que están en la página del proyecto SL4A o con el método que mejor les parezca.

Ok, las cosas a instalar son:


Luego que las instalen van al dispositivo/emulador y buscan el icono de Python For Android, tap e instalan. Eso tardará unos minutos mientras descarga unas cosas. Al terminar entonces enviamos el script de prueba al cel, podemos usar el comando:

$ adb push /ruta/del/script.py /sdcard/sl4a/scripts/

Eso lo copiará en la carpeta del SL4A. Ahora cuando ejecutemos el Python For Android veremos en la lista de scripts nuestra infame creación, tap en el script y ejecutar. Lo demás es disfrutar las ventanitas y controles :P

Conclusiones


  1. La API de SL4A es reducida, es decir si bien está bastante adelantada aún faltan muchas cosas/funciones por implementar.
  2. Python For Android a diferencia de lo que pensaba no soporta widgets gráficos en Android, solamente notificaciones, toast y cosas básicas tipo entrada de texto, selección, etc. Así que nos olvidamos de interfaces gráficas ricas en imágenes y esas cosas.
  3. Sí existen algunos issues de performance, de hecho un pana que está trabajando duro con Android me dice que los desarrolladores todos los días se matan por tratar de mejorar el rendimiento pues de por si ya es algo lento (hablo de apps nativas). Sin embargo la versión de Python es cross-compiled y corre incluso más rápido que Jython
  4. Hay formas de empaquetar scripts en .apk y aunque son algo un poco experimentales funcionan bastante bien (son, digamos, "tweaks" del método de construcción de paquetes con Java)
  5. En cuanto a estabilidad no hay mayores issues, se puede usar para aplicaciones de producción


Finalmente puedo decir (muy a mi pesar) que no podemos contar con ésta alternativa para desarrollar aplicaciones ricas en interfaces gráficas, sin embargo es una opción interesante a tener en cuenta cuando madure un poco más. Personalmente le haré seguimiento tipo ninja y esperaré con ansias que en el futuro se puedan crear aplicaciones tan buenas como se hace con Java.

Más información en:

* http://code.google.com/p/android-scripting/
*http://code.google.com/p/android-scripting/wiki/FAQ
* http://code.google.com/p/android-scripting/wiki/Tutorials
* http://code.google.com/p/android-scripting/wiki/ApiReference



Actualmente me he visto en la necesidad de crear aplicaciones para Android y como no había incursionado en ese mundo, he decidido hacer una serie de artículos para documentar todo el proceso.

En ésta primera entrega explicaré los pasos que seguí para poner a punto el entorno de desarrollo. Debo resaltar que las recetas están hechas para Debian GNU/Linux, sin embargo puedes adaptarla a tu distro favorita con unos leves ajustes.

Para los que no están familiarizados con mis tutoriales les recuerdo que todas las instrucciones que comiencen con el caracter $ se ejecutan como usuario normal y las que comiencen con # se ejecutan como superusuario (root), por ejemplo:

$ ls -l (instrucción ejecutada como usuario)
# aptitude update (instrucción ejecutada como root)


Dicho esto comenzamos.

Instalar dependencias


Lo primero que debemos hacer es instalar los paquetes necesarios para el desarrollo, que básicamente son: la máquina virtual de Java (JRE) y el entorno de desarrollo (JDK). En una distribución Debian GNU/Linux bastaría con:

# aptitude update
# aptitude install sun-java6-jdk sun-java6-jre
# aptitude remove gcj-jdk


Si se dan cuenta usamos las implementaciones de SUN y removimos cualquier posible instalación del compilador GNU de Java (gcj) pues en la documentación oficial nos dicen que gcj NO es compatible con Android.

Para más información sobre los requerimientos del sistema visita: http://developer.android.com/sdk/requirements.html

Luego que instalamos los paquetes nos aseguramos de que el sistema seleccione las opciones correctas por defecto de cada ejecutable, pare eso usamos:

# update-alternatives --config javac
# update-alternatives --config java


Y en ambos casos, seleccionamos las opciones de SUN.

Instalar Ant


Ant es una herramienta que nos permite construir aplicaciones Java. En nuestro caso, nos permitirá compilar y construir archivos .apk (los instalables en Android) a partir de nuestro código fuente.

Nos vamos a la página de descargas de Ant, descargamos uno de los archivos comprimidos que se encuentran en la sección "Current Release of Ant" y lo descomprimimos en una carpeta de nuestra preferencia. En mi caso lo hice en /opt y me quedó la carpeta: /opt/apache-ant-1.8.1.

Instalar el Android SDK


Bueno, teniendo las herramientas y dependencias listas, vamos a instalar el entorno de desarrollo de Android. Nos vamos a la página del SDK de Android y descargamos la versión que corresponda a nuestra plataforma. Al igual que con Ant, descomprimimos el archivo en la carpeta de nuestra preferencia. Ésta vez también lo descomprimí en /opt, quedando en la carpeta: /opt/android-sdk-linux_x86.

Ahora editamos el archivo ~/.bashrc para agregar la ruta de los binarios al PATH del sistema y establecer las variables de entorno ANT_HOME y JAVA_HOME. Eso lo logramos agregando las siguientes líneas:

export PATH=${PATH}:/opt/android-sdk-linux_x86/tools
export PATH=${PATH}:/opt/apache-ant-1.8.1/bin
export ANT_HOME=/opt/apache-ant-1.8.1
export JAVA_HOME=/usr/lib/jvm/java-6-sun/jre


Recuerda cambiar las rutas de esas variables por las rutas donde se encuentran tus binarios. Si no sabes muy bien hacía dónde debe apuntar JAVA_HOME puedes ejecutar el comando:

# find / -name "tools.jar" | grep sun

Y entonces agrega la ruta que te arroje.

Nota: Debes cerrar las terminales abiertas y volverlas a abrir para que los cambios en las rutas surtan efecto.

Instalar plataformas de Android


¿Plataformas? ¿De qué me hablas? - Seguramente te estarás haciendo esas preguntas. Las plataformas son las "versiones" de Android disponibles (por ejemplo Android 1.6, Android 2.2) y necesitamos al menos una para poder compilar la aplicación y configurar un Android Virtual Device (AVD) para probarla.

Esto es muy simple, basta con abrir una terminal y ejecutar:

$ android

Nos aparecerá una aplicación (AVD Manager) como la que se muestra a continuación y allí nos vamos a la sección Available Packages, actualizamos el repositorio y seleccionamos la(s) plataforma(s) que deseamos instalar.


Finalmente creamos un nuevo dispositivo virtual en la sección Virtual Device. Hacemos clic en el botón New..., le asignamos un nombre, seleccionamos una plataforma y hacemos clic en Create AVD.


Para probar nuestro flamante dispositivo lo seleccionamos y hacemos clic en Start.... Luego clic en Launch y al cabo de unos segundos tendremos el emulador corriendo una instancia de Android :)


Desarrollo


Ahora viene la parte divertida, crear la aplicación. En las próximas entregas estaré hablando sobre el desarrollo, por los momentos pueden jugar creando un Hello World y pueden leer sobre cómo desarrollar con Eclipse y cómo desarrollar con otros IDEs

Compilar y construir el ejecutable


Luego de que tengamos nuestra aplicación lista debemos crear el instalador. Eso es tan simple como navegar hasta la carpeta raíz del proyecto (código fuente) y ejecutar:

$ ant debug

Si nuestro proyecto se llama "HelloAndroid" esto generará un archivo HelloAndroid-debug.apk y ese será nuestro instalador.

Probar en el emulador


Finalmente, una de las partes más esperadas. ¿Cómo se verá nuestra aplicación en un dispositivo? Pues fácil, en una consola ejecutamos:

$ android

E iniciamos nuestro dispositivo virtual. Luego que el dispositivo esté funcionando ejecutamos en otra consola:

$ adb install /ruta/de/nuestro/instalador/HelloAndroid-debug.apk

Y con eso enviaremos la aplicación al dispositivo. La buscamos en el menú y voilá! A jugar :D

Espero que les haya sido de utilidad éste tutorial. Próximamente seguiré documentando mis travesías en el mundo de Android. Cambio y fuera.