jueves, 2 de diciembre de 2010

Android development tree with gource

Hacía tiempo que no escribía nada, he estado bastante liado, como podreis comprobar a continuación.

El post de hoy está dedicado a la visualización de la vida de un repositorio subversion con gource, es un proceso sencillo, descargas gource, lo configuras e instalas, para ello tendremos que ejecutar los siguientes comandos en una distribución que admita instalación de paquetes apt

sudo apt-get install libsdl1.2-dev libsdl-image1.2-dev libpcre3-dev libftgl-dev libpng12-dev libjpeg62-dev libglew1.5-dev
./configure
make
make install


Con lo que obtendremos el archivo ejecutable gource.

Ahora será cuestión de tener un repositorio subversion a mano, para pasárselo al siguiente script:

Guarda este texto en un archivo create_gource y ejecutas chmod u+x create_gource para poder ejecutarlo

#!/bin/bash
mkdir $1
svn log --verbose --xml $2 > $1/log
python svn-gource.py --filter-dirs $1/log > $1/gource.log
./gource --log-format custom $1/gource.log -s 0.3 --hide filenames,dirnames,usernames,users --follow-user Unknown --file-extensions --disable-progress --stop-at-end --output-ppm-stream - | ffmpeg -y -b 3000K -r 60 -f image2pipe -vcodec ppm -i - -sameq $1/$1.mov -pass 2
totem $1/$1.mp4


Ahora simplemente tienes que ejecutar ./create_gource Nombre ruta_projecto_svn para obtener un vídeo como el siguiente:



Este vídeo representa aproximadamente seis meses de desarrollo, aunque los proyectos fueron empezados antes, de ahí algunas importaciones iniciales. Se puede apreciar un ramal doble que es Universal Translator con su versión de contribución Universal Translator NoAds, y el resto son proyectos que están un poco dejados, que no abandonados, todo a su debido tiempo ;)

lunes, 9 de agosto de 2010

Comentarios en las aplicaciones

En todas mis aplicaciones suelo dejar siempre algún método de contacto o algo para que me dejen un comentario, por lo menos que si a alguien le parece una mierda que se pueda expresar o si le parece algo excelente pues que también me lo pueda decir.

Ayer recibí un mensaje en Bullet JNI Profiler muy interesante,
This did exactly what it was supposed to do, and a little more, just add descriptions to the options. And maybe different physics options for the sprites
estos son los tipos de comentarios que le suben a uno la moral.

Hay gente muy perdida, aunque reconozco que si no sabes qué es te puedes perder un poco al ver una aplicación que no hace nada (Bullet JNI Profiler):


what am i suppose to do with this application?

casar animales


Luego están los comentarios contradictorios (comentarios de Universal Translator):

by tony (August 6, 2010)

Goodbye language learning! it translates well enough for me

by AI KIAN (August 6, 2010)

烂死了没有发音解释


El segundo viene a decir: "Ninguna explicación racional muertos podridos", eso qué significa que no lo entiendes, que no te funciona o qué :/

La cuestión es que hay que hacer las aplicaciones para tontos para que nadie te vote negativo por no saber utilizarla, independientemente del cociente intelectual que tenga esa persona.

domingo, 25 de julio de 2010

Rootear htc hero en 1.5 o 2.1

Por fin he conseguido rootear la htc hero :D, ha sido un proceso complicado que me ha llevado 24 h literalmente. Recomiendo que se lea de cabo a rabo antes de empezar, paso a describirlo por si a alguien le viene bien.

Posibles estados:

htc orange 1.5
htc orange 2.1

Si tienes una 2.1 tendrás que crear una goldcard para volver a la versión 1.5

Aquí teneis las instrucciones de cómo hacerlo, importante para evitar problemas utilizar como lector de tarjetas el propio móvil.

http://www.htcmania.com/showthread.php?t=89723


Seguir por aqui si tienes la 1.5

Una vez que está en versión 1.5, seguimos el tutorial para sacar una copia de seguridad e instalar un recovery que nos abrirá la puerta a upgradear después el dispositivo a la versión 2.1

De este tutorial debemos seguir únicamente la parte de Custom recovery
http://www.htcmania.com/showthread.php?t=87173

Ahora necesitaremos descargar la actualización a 2.1 que podemos encontrar en un post de xda developers
http://forum.xda-developers.com/showthread.php?t=712743

Esta actualización tiene la peculiaridad de no tener radio, así es que necesitaremos una radio también,

http://www.htcmania.com/showthread.php?t=66838

Puedes descargar la que tu quieras. Reiniciamos el dispositivo en modo recóvery (encender+home) y seleccionar en Flash zip from sdcard seleccionamos primero la actualización de xda developers y luego la radio de htcmania, reiniciamos el móvil y volverá a entrar en modo recóvery, una vez que termina de limpiar la caché, vuelves a reiniciar el móvil.

Ahora tenemos la versión 2.1, pero con el recovery 1.6.2, con lo que volvemos a reiniciar en modo recovery (encender + home) y seguimos esta parte del tutorial de htcmanía que paso a fusilar directamente para eliminar las partes innecesarias:


Este tutorial es para hacer lo mismo que en al paso anterior, pero a través del PC.
1.-Descarga el HTCSync e instálalo.
2.-Descarga el SDK de Android.
3.-Descomprime el archivo en la carpeta HERO en la raiz del disco duro.
4.-Descarga el SuperUser (requiere registro).
5.-Copia el SuperUser en la carpeta tools del SDK (C:/HERO/SDK/android-sdk-windows/tools). Si estácomprimido, descomprímelo.

Reinicia en modo Recovery (encender + home) con el RA v1.6.2
6.-Ahora ejecutamos los siguientes comandos en cmd:
Código:

adb shell mount /system
adb push su /system/bin/
adb shell chmod 4755 /system/bin/su
adb push Superuser.apk /system/app/
adb shell reboot


Ya tenemos la versión 2.1 rooteada perfectamente.

Disclaimer:

No me hago responsable si tras seguir este manual obtienes un precioso ladrillo.

domingo, 11 de julio de 2010

Solved Unknown device

Ayer pasé de htc, de orange y de todo el mundo y actualicé el htc hero a Android 2.1. Hasta ahí todo más o menos bien, el problema llegó cuando intenté depurar una aplicación en em móvil.

El comando adb logcat se quedaba waiting for devices eternamente, y el resto de los comandos devolvían el mensaje "error: insufficient permissions for device".

Solución, reiniciar el servidor adb, la comúnmente llamada solución del informático :)


adb kill-server
sudo adb start-server
adb devices


E voila, ya tenemos de nuevo el dispositivo listo para seguir depurando

miércoles, 7 de julio de 2010

Android on orientation change

Existe un comportamiento en Android que resulta un poco desconcertante si no te ha sucedido nunca, tu estás programando una pantallita tranquilamente y resulta que cuando cambias la orientación del móvil se pierde toda la información insertada :/, un poco de investigación te lleva a la conclusión de que se está llamando al onStop, onDestroy y onCreate de la actividad, WTF! pero si yo sólo he girado la pantalla del móvil ...

Por lo visto es el comportamiento normal en Android y tiene una solución cuya complejidad depende de lo complicada que sea tu interface. La solución pasa por utilizar dos métodos de la clase Activity:

onRetainNonConfigurationInstance: Método que se llama cuando la actividad se está destruyendo, su objetivo es recopilar la información que el usuario haya insertado o que sea costosa de volver a recuperar. Este método debe estár declarado y devolverá un Object con la información descrita.

getLastNonConfigurationInstance Este otro método debe ser llamado en la inicialización de la actividad, lo suyo es en el onCreate, devolverá el Object que retornó el método anterior y tendremos que volver a cargar esa información en la Actividad manualmente.

Es un proceso sencillo, pero hay que conocerlo :)

sábado, 17 de abril de 2010

Limitaciones de widgets de android

O por qué te va a costar la vida misma encontrar widget de twitter para android que te permita pulsar enlaces desde la página principal :)

Ultimamente uso mucho twitter, en el ordenador de escritorio utilizo TweetDeck y en el android utilizo Peep, que es el cliente por defecto, la verdad es que si los comparas, peep queda bastante mal, no soporta muchas de las características que tienen las aplicaciones de pc.

Como decía un amigo cuando le enseñé orgulloso el stub de motor físico y de colisiones que estoy programando, esto es cuestión de montar un par de clases por aqui y otro par de clases por allá, así es que ni corto ni perezoso me documenté un poco y a tirar líneas.

Como base para el widget simplemente copié el que viene con el SDK de android dentro de la carpeta ApiDemos y para manipular la api de twitter he utilizado twitter4j, con lo que prácticamente tengo el 80% de la aplicación escrita, para el que quiera tiene el código fuente en http://code.google.com/p/androtwitt/

Ahora vienen los problemas y además todos juntos, me dije a mi mismo, jm, por qué no pones los enlaces en el propio widget, eso hará que sea más usable, así es que puse el atributo android:autoLink = true en los TextView del layout del widget, error, craso error, vamos, concretamente este:

android.util.AndroidRuntimeException: Calling startActivity() from
outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK
flag. Is this really what you want?


Hombre, pues la verdad es que el hecho de que me pegue un pellejazo no es precisamente lo que quería, pero bueno, si te pones así..., que significa esto, tengo una versión corta y una larga.

La larga es que cuando utilizas el atributo android:autoLink, el texto de los textview se convierte en hipertexto, por lo tanto puedes pulsar sobre los enlaces, esta pulsación se recoge en el evento onTouchEvent, que llama al método UrlSpan.onClick y éste a su vez crea una nueva actividad, esta actividad no tiene el flag FLAG_ACTIVITY_NEW_TASK y por lo tanto la máquina virtual no puede lanzar el navegador, por que no lo puede meter en la pila de llamadas del widget, o algo así ;)

La corta es que por ese camino estoy jodido :)

Por lo tanto yo, que soy el rey del workaround, decidí extender el objeto TextView para sobreescribir el maldito método con nocturnidad y alevosía, sería un corte limpio, sin sangre ;), ya sabeis como son estas cosas.

En android crear una vista es sencillo, sólo tienes que crear una clase que extienda de View o de alguna de sus subclases, en este caso extendería directamente de TextView y definir en ref/values/attrs.xml los atributos que vas a permitir en tu vista, además opcionalmente puedes definir un res/layout/vista.xml que defina el aspecto del widget, fácil, fácil, pero error, doble craso error, no puedes incluir una "custom view" en un widget por cuestiones de seguridad. Pos vaya mierda :(

Moraleja, ciñete al listado de layouts y vistas que se lista en la documentación, por que en cuestión de widgets no te puedes salir del tiesto.

sábado, 20 de marzo de 2010

DevSpace #11 “Desarrollo de videojuegos para Android”

Hoy ha tenido lugar el DevSpace #11, que ha girado entorno al desarrollo de videojuegos sobre la plataforma Android, la charla ha sido impartida por el grupo The Flying Cortijo quienes han estado promocionando y repartiendo copias de su juego Tile Land, un juego de puzles que consiste en formar parejas de tiles idénticos.

En cuestión de programación, hay que evitar en la medida de lo posible el garbage collector, este proceso puede llegar a consumir 600 ms y salta cuando hay del orden de 2000 objetos en memoria, lo que puede llegar a ser un performance killer.

Las técnicas para evitar este problema son la delegación de actividades costosas en memoria y proceso al código nativo, para lo que hay que utilizar el ndk de android y en general cualquier tipo de creación o eliminación de referencias, almacenar los objetos en listas para no perderlas.

Sobre el sonido, se recomienda el formato ogg y el uso de la clase SoundPool para almacenar los efectos del tipo disparos, explosiones, etc de la aplicación.

A nivel de gráficos la aplicación está construida con archivos pequeñitos en peso, el proceso de construcción básico es la creación de un boceto en coreldraw para la posterior edición con alguna herramienta de dibujo vectorial, ha dado tiempo a hacer una pequeña demo de como se realizaría una animación.

El vídeo de presentación se ha mostrado tras unas nociones de creación de sonidos, como aplicar efectos y como componer un theme en general.

Editado (3/5/10):

Aqui tenemos un enlace a algunos recursos más sobre la ponencia, donde podemos encontrar fotos y un vídeo del evento.
http://www.desea.es/?p=328

martes, 16 de marzo de 2010

BulletJni rules

Al final conseguí poner en pié la biblioteca jbox2d portada a android y la verdad es que el rendimiento no era nada del otro mundo, la probé con canvas y el código era android (no nativo) pero aún así el rendimiento era muy pobre, 1 o 2 frames con 10 objetos en pantalla colisionando en forma de pirámide.

Así es que estube probando otras opciones, una de ellas que es la que al final me convenció fué BulletJni, que es una biblioteca que hace uso de métodos nativos en c para el cálculo de colisiones y movimientos físicos, por ahora lo que se puede ver es una aplicación en la que 10 sprites se mueven por la pantalla al son del acelerómetro, pero rinde entre 25-50 fps, lo cual me la pone muy gorda.

Se puede ver el código fuente en http://code.google.com/p/android-2d-engine/source/browse/#svn/branches/bullet_jni

miércoles, 3 de marzo de 2010

Engine para juegos android

Estoy buscando la forma de hacer un jueguecillo para android y necesito un engine 2d, así es que a buscar tocan, hay poco esto es todo lo que estuve viendo

Si quieres desarrollar no puedes dar la espalda a la comunidad, así es que no te olvides de pasarte por anddev.org


Rokon es una biblioteca para desarrollo de juegos 2d, actualmente tiene un problema con la herencia entre Sprites y objetos dinámicos, un poco floja en dinámicas

ProAndEngine no tiene documentación pero lo único que hace es lo que se ve.

JBox2D tiene un sistema de colisiones y otro de físicas completo, está basado en box2d, una biblioteca c++, es genérico, así es que supongo que necesitará alguna biblioteca gráfica, y la lógica de negocio del juego.

Uhm... rokon + jbox2d = jRox2d, a ver que tal.

Problema número 1:
Rokon tiene una herencia desde mi punto de vista no correcta y eso crea problemas en los behaviours de los sprites, solución: todo objeto que hay en la pantalla es un sprite, pero sólo los objetos que no son una isla son objetos dinámicos, la herencia está al revés y ahora no se puede usar el tipo primitivo que es sprite y colarle un DinamicObject cuando sea necesario, no puede haber islas, por que el tipo más básico en la herencia es el objeto más complejo.

Update:
He tenido que tocar todo el sistema de sprites y ya sólo falta por funcionar la gravedad que la he incluido en el dynamicObject, tengo algún problemilla con la temporización de los eventos :S

Update:
Problemas solucionados relativamente, se quedan los Sprites como clase base, pero la he liado un poco invirtiendo las clases, así es que hay que revisar las responsabilidades de BasicSprite, DynamicObject y Sprite, es probable que sustituya esa parte del sistema por jbox2d.
https://code.google.com/p/blasters/source/checkout