Monday, December 27, 2010

Finding hardware/software properties at runtime

Right now I am working in an app that needs to detect hardware properties at runtime to change it's behavior.
Some possible examples:
  • We might want to add some arrow keys to our screen if the used doesn't have a way to navigate.
  • We need to know user's locale.
  • We are doing a game and we want to provide some in screen controls if the user doesn't have a keyboard.

For this kind of needs Android provides a class called Configuration.
Let's say we want to detect which kind of navigation the user has in his device.

We will get the device's value doing:


getResources().getConfiguration().navigation

and then we need to compare it against the different constants in the Configuration class.
public static final int NAVIGATION_UNDEFINED = 0;
public static final int NAVIGATION_NONAV = 1;
public static final int NAVIGATION_DPAD = 2;
public static final int NAVIGATION_TRACKBALL = 3;
public static final int NAVIGATION_WHEEL = 4;

Some examples in different devices:

Motorola Droid: navigation=2 (NAVIGATION_DPAD)
Nexus One: navigation=3 (NAVIGATION_TRACKBALL)
Galaxy S: navigation=1 (NAVIGATION_NONAV)

Friday, December 24, 2010

Review Nexus S

Nota: Este blog post lo hizo Pabloks. Compañero de la facu que está arrancando en el mundo Android. Bienvenido :)

Tuve la suerte de estar en NY el 16 de Diciembre y conseguir, felizmente, el último Nexus S del local. Debo admitir que en un momento me sentí en Argentina: El día anterior pasé por un local de Best Buy y pregunté si ya tenían en stock los teléfonos, la respuesta fue un "no, hubo un problema con el envío y los teléfonos llegan el 20 y salen a la venta el 22". Por suerte, como buen argentino, no me dí por vencido y pasé por otro local, y ahí me dijeron que el teléfono estaba y que a las 8.01 am del 16 se empezaban a vender.

Por suerte llegué al local, habían 2 personas (me esperaba una cola en la cuadra como si tocasen los teen angels en corrientes) y pude conseguir el teléfono. Felicidad suprema :)

Aclaración: Actualmente tengo una Blackberry de Nextel por lo tanto voy a describir diferencias entre una Blackberry y el Nexus S. A su vez comentarios sobre el Nexus One, Galaxy S e IPhone 4.


Hardware

El Nexus S (GT-I9020) basicamente es una versión del Galaxy S (GT-I9000). A lo cuál casi trae las mismas características (el menú inferior difiere, el Galaxy S trae slot para micro SD y Radio FM, y otras pequeñeses).

Las características principales son:

  • Procesador 1 GHz Hummingbird
  • 512 MB RAM
  • 16 GB de memoria interna
  • Pantalla de 4'' SUPER AMOLED con soporte mDNIe (mobile Digital Natural Image engine)
  • Camara posterior de 5 MP (graba a 720p)
  • Camara frontal VGA
  • Wi-Fi b/g/n con soporte DLNA
  • Bluetooth
  • NFC (Network Field Communication)
Para más detalles ver la descripción oficial.

Con respecto al Nexus One no tiene características muy distintivas. Las diferencias que se pueden apreciar son:
  • Pantalla de 4 pulgadas con tecnología SUPER AMOLED
  • Mejorado el táctil de la pantalla
  • Cámara frontal
  • NFC
Si están interesados en una buena comparación de ambos vean este artículo realizado por pocket-lint.

NFC

Al principio no tenía idea que era y, honestamente, estaba muy entretenido probando apps del Market para investigarlo :P. Cuestión que estaba el otro día jugando, apoyo el celular en la billetera y sale un cartel "Tag Detected". Vuelvo a probar y lo mismo. Qué es entonces? El NFC es un protocolo basado en una interfaz inalámbrica que brinda la posibilidad de comunicar 2 dispositivos inalambricamente. Resumiendo, el celular lee las tarjetas de proximidad! (en realidad lee frecuencias RFID) La idea es que uno pueda ir pasando por distintos lugares, con objetos, teléfonos, etc. y que el celular te vaya marcando los tags respectivos! Por ejemplo... Supongamos que ambos teléfonos traen NFC, se podría armar que acercando ambos teléfonos automáticamente te brinde los datos de la otra persona.

mDNIe

Mobile Digital Natural Image engine es una tecnología creada por Samsung que está siendo utilizada actualmente sus televisores LCD y LED haciendo que las imágenes sean más nítidas y claras.

Software

Realmente Gingerbread no trae cambios significativos en la UI respecto a FroYo. La mayoría de las mejoras que se realizaron son de las librerías internas del SO logrando mejores velocidades de respuestas. El teclado fue mejorado incorporando, primero, la posibilidad de detección de palabra a medida que se va escribiendo (al estilo de la app SwiftKey) y, segundo, la capacidad de hacer selección de texto por medio del multitouch (se selecciona los rangos del texto) para poder copiar y pegar.

Contras

Una de las principales contras que le encuentro al teléfono es la falta del slot SD para poder expandir la memoria (a pesar que el Galaxy S trae). Otra desventaja, para nosotros los argentinos, es que actualmente únicamente está la versión para T-Mobile, a lo cuál las bandas de 3g de nuestro país no funcionan con el teléfono. Actualmente estoy probando el teléfono con un chip 3g usando la conexión EDGE y por lo pronto funciona bien para todo lo que es mail, chat, twitter, facebook, etc. Debo admitir que al touch todavía le falta un poquito. Hay veces en que no responde al mando o la transición es lenta (en comparación al IPhone 4 o Ipad).

Pros

Es el Nexus S! Viniendo de una blackberry me gustó prácticamente todo. Es muy intuitiva la usabilidad, el market está lleno de aplicaciones para lo que se te ocurra, la posibilidad de tener skype (la mayoría no lo va a pensar como un pro, pero en blackberry no existe), esta muy bien lograda la integración de todo lo que es social media, y más! El agregado del NFC tiene muy buen potencial y con el uso del giroscópio se pueden lograr apps muy interesantes (Google Sky Map!). Todavía no usé el soporte de VoIP/SIP pero ya de por sí es interesante.

Conclusión

Esta semana estoy sacando la linea para regalar la blackberry :P

¿Es posible comprar una tablet Android en Argentina?



Semanas atrás
Salió un blog post en celularis que mencionaba que la galaxy tab iba a estar disponible en Claro. Más tarde, un blog post por Movistar.

Domingo 12 de Diciembre
Sale en el diario La Nación la publicidad de claro mencionando que el galaxy tab va a estar disponible!


Por más que llamé nadie sabía nada en Claro.

Martes 14 de Diciembre
Estuve paseándome por sucursales de claro averiguando hasta que entré a una que tenía una chica vestida de samsung. Antes de sacar número le pregunto:
- Hola, ¿tienen la galaxy tab acá?
- Sí. Avisame cuando te toque que te la llevo para ver.
- Genial!

Llega mi turno, le hago una seña a la flaca y tengo la siguiente conversación:
- Tomá. Acá lo tenés.
- mmm... Esto es un galaxy S. Yo quiero el tablet de 7'.
- Este es el único galaxy que existe.
- Nop
- ¿Me vas a decir a mí que trabajo para samsung?
- Ok, ya te vas a acordar de mí :)


Seguí llamando a claro y también me pasó algo muy gracioso:
- Hola, ¿ya se puede comprar el galaxy tab?
- ¿Qué?
- Hola, ¿ya se puede comprar el galaxy tab?
- Señor, no lo escucho bien. ¿De dónde me está hablando?
- De mi celular con claro!
- Debe tener algun problema.
- No sé, decimelo vos!

Miércoles 15 de Diciembre
Me entero que ni Claro ni Movistar tiene tarifa plana de 3g. El único que tiene es personal con black desde 200$.

Martes 21 de Diciembre
Movistar me confirma por twitter que todavía no está disponible la galaxy tab.
BTW tienen un servicio muy copado de twitter @MovistarArg. Es mucho mejor que el viaje sin retorno entre derivaciones de claro.

Voy a claro para averiguar un cel para mi novia. Quería el Samsung i5500. La oferta de claro no nos convenció y lo compramos liberado. Nada de permanencias y por valores similares.

Ahí pregunté nuevamente por el tab y me dijeron que podía pasar mañana que ya habían llegado pero que todavía no estaban a la venta.

Por fin!

Miércoles 22 de Diciembre
Voy a claro pido el galaxy tab.

Detalles de la compra:

* $120 por mes
* 2 años de permanencia
* 3GB de transferencia (ASTERISCO GIGANTE: Ver final de la historia)
* $3099

Acepto y espero a que haga todos los papeles.
40 mins más tarde le pido que lo siga que vuelvo en un rato que tenía que volver al trabajo.

Cuando vuelve me dicen:
"Mirá me confundí el plan de datos es de 600MB no de 3GB"

Hice un par de cuentas y le dije:
- Ok. Damelo. Voy a hacer esto:
* Doy de baja mi línea
* Pongo la línea del tab en mi cel
* Compro una sim de internet que es más barata.

- Puede ser, pero tené en cuenta que el galaxy tab viene con micro sim.
- Bueno, dale para adelante!

(Unos minutos más tarde...)
- Mirá no tengo sistema. ¿Podés pasar mañana?
- No, gracias. Cancelá todo.

Conclusiones:
* Comprar una tablet en Argentina es imposible.
* Me quedé sin auto-regalo de navidad
* Lamentablemente la posta es comprar liberado.

Feliz navidad a todos!

Wednesday, December 15, 2010

Concurso NDrive. Tengo cinco licencias de Argentina para regalar!



Concurso NDrive


La gente de NDrive se contacto conmigo hace unos días para ofrecerme la posibilidad de repartir cinco licencias de NDrive para el mapa de Argentina.



Pasos a seguir para ganar la licencia:

  1. Ir al market y descargar NDrive.
  2. Probar la aplicación y encontrar el feature que más les guste.
  3. Darle puntaje y poner un comentario en el Android Market.
  4. Poner un comentario en esta entrada explicando cómo esa feature elegida te va a ayudar en tu vida cotidiana.
Se eligirá al ganador en base a la creatividad, originalidad y humor.

Algunos ejemplos:
  • Voy a usar el modo peatón para no perderme cuando tenga que ir al super chino.
  • Voy a usar el pad de mi nexus one para controlar el mapa 3d como controlo la Matrix (?)

El concurso arranca hoy Jueves 16 y termina el Miércoles 22.
Los ganadores serán anunciados el Jueves 23.

Qué estás esperando? Descargala ya!



Saturday, December 4, 2010

Flof + Layar = Flof-Layar!

Hace un tiempo venía con ganas de probar Layar.

¿Qué es Layar?
Layar es una empresa holandesa con bases en Amsterdam. El producto es un navegador de capas (layers) para encontrar varios temas por medio de tecnología de realidad aumentada.

Para probarlo necesitaba una fuente de puntos de interés. Aprovechando que estaba cursando una materia con Juan F. Codagnone (@juam) le pedí si me podía dumpear la db de Flof.

¿Qué es Flof?

Flof es una colección de lugares catalogados por usuarios en forma libre. Así como es posible guardar páginas favoritas, con flof se puede guardar, compartir y descubrir lugares dentro de una gran comunidad.

Flof es una aplicación colaborativa: la información disponible es el resultado de la interacción de los usuarios con la aplicación y de los datos que éstos aportan al catalogar e ingresar puntos en el mapa (lugares).

El servidor a usar es GAE.
Mientras esperaba que Juan me pase los puntos de Flof tuve la oportunidad de cursar Cloud Computing. Buenísimo! Dos pájaros de un tiro. Termino de aprender GAE y liquido el proyecto Flof-Layar. La materia la dio Miguel Saez (@masaez) empleado de Microsoft.

La idea de hacerlo en GAE se esfumó en un segundo. Hicimos el tp para Windows Azure :(
Es la primera vez que codeo algo en plataforma Windows. Como todo, encontré cosas muy buenas (ej: las búsquedas espaciales en sql azure) pero por otro lado me encontré con cosas muy malas (ej: Launching Azure debug from Visual studio and bind in * instead of 127.0.0.1)

Les dejo un par de screenshots de mi cel con la app corriendo:







Lamentablemente no lo puedo dejar el layer subido porque las cuentas que nos dieron de azure tienen sólo un mes de validez.
Me quedará terminar la versión de GAE y colgarlo :)

Wednesday, December 1, 2010

Creating a Shadow for Robolectric in 6 steps

Some days ago I asked for a pull request in Robolectric's github repo. I finished my ShadowConnectivityManager. The discussion can be read here. I will explain how I did it so someone else can continue creating Shadows :).

Why do I need a ShadowConnectivityManager?
The app we are doing right now requires internet to work so we did a nice SplashScreen that checks if internet is available.
If there is internet go to the main Activity, else show a cute msg saying that you don't have internet.

So we created a class called ConnectionStatus which has a method:

boolean isOnline();


NOTE: We should have created the test first but since we are also giving a try to roboguice we did the code before the test.


public class ConnectionStatus implements IConnectionStatus {

private ConnectivityManager cm;

@Inject
public ConnectionStatus(ConnectivityManager cm) {
this.cm = cm;
}

public boolean isOnline() {
NetworkInfo netInfo = cm.getActiveNetworkInfo();
if (netInfo != null && netInfo.isConnectedOrConnecting()) {
return true;
}

return false;
}
}


Instead of doing:
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
we can inject it :)

Ok, time to test. When I try to inject a ConnectivityManager to a test there was an exception saying that my variable should have a @Nullable annotation.

Conclusion:
Null instance in test scope == "Robolectric needs your help! Create a Shadow object!"

STEP 1: Understand how Android works
Robolectric basically mocks Android's behavior. You need to understand how it works for you to mock it correctly.

In our case:

* You use an Android's context to get the ConnectivityManager which is a SystemService.
* You ask the ConnectivityManager to give you the ActiveNetworkInfo.
* The class NetworkInfo has a method isConnectedOrConnecting() which will determine if your are online or not.

STEP 2: Decide how the Shadow should be used

We want to be able to set if we are connected or not and check if our ConnectionStatus class is returning things accordingly.
To do that we will leave a flag inside the NetworkInfo's Shadow to let the user decide what it should return.

STEP 3: Code the Shadow
In our case we need to code ShadowConnectivityManager and ShadowNetworkInfo

// With the Implements annotation we tell Robolectric which Android's class this is shadow of.
@Implements(ConnectivityManager.class)
public class ShadowConnectivityManager {

// We will hold here an instance of the ActiveNetworkInfo.
private NetworkInfo networkInfo;


// All methods that exists in the real Android's class and overridden by the shadow
// must have an Implementation annotation. I don't know what for :(
@Implementation
public NetworkInfo getActiveNetworkInfo() {
return networkInfo == null ? networkInfo = newInstanceOf(NetworkInfo.class) : networkInfo;
}
}

Ok, my first big doubt was: "Ok, I need to return a NetworkInfo but I need it to be a shadow, how do I do it?"
That what Robolectric.newInstanceOf() is for :)



@Implements(NetworkInfo.class)
public class ShadowNetworkInfo {

private boolean isConnected = true;

@Implementation
public boolean isConnectedOrConnecting() {
return isConnected;
}

/**
* Non-Android accessor
* Sets up the return value of {@link #isConnectedOrConnecting()}.
*
* @param isConnected the value that {@link #isConnectedOrConnecting()} will return.
*/
public void setConnectionStatus(boolean isConnected) {
this.isConnected = isConnected;
}
}


Pretty easy as well. We have an Non-Android accesor that we will use to set the wanted connectivity status.


STEP 4: Modify Robolectric.java

* Add your Shadow classes to the list in the getDefaultShadowClasses() method.
* Create the shadowOf methods:

public static ShadowNetworkInfo shadowOf(NetworkInfo instance) {
return (ShadowNetworkInfo) shadowOf_(instance);
}

public static ShadowConnectivityManager shadowOf(ConnectivityManager instance) {
return (ShadowConnectivityManager) shadowOf_(instance);
}

* Optional: I needed to modify ShadowApplication as well.

Why?
Application is in charge of the getSystemService's method.
We need to modify it to return our ShadowConnectivityManager just adding this:

if (name.equals(Context.CONNECTIVITY_SERVICE)) {
return connectivityManager == null ? connectivityManager = newInstanceOf(ConnectivityManager.class) : connectivityManager;
}



STEP 5: Test your Shadow
I will just copy and paste the test we did. It's quite simple:

@RunWith(WithTestDefaultsRunner.class)
public class ConnectivityManagerTest {
private ConnectivityManager connectivityManager;
private ShadowNetworkInfo networkInfo;

@Before
public void setUp() throws Exception {
Robolectric.bindDefaultShadowClasses();
Robolectric.application = new Application();
connectivityManager = (ConnectivityManager) Robolectric.application.getSystemService(Context.CONNECTIVITY_SERVICE);
networkInfo = Robolectric.shadowOf(connectivityManager.getActiveNetworkInfo());
}

@Test
public void getConnectivityManagerShouldNotBeNull() {
assertNotNull(connectivityManager);
assertNotNull(connectivityManager.getActiveNetworkInfo());
}

@Test
public void networkInfoShouldReturnTrueCorrectly() {
networkInfo.setConnectionStatus(true);

assertTrue(connectivityManager.getActiveNetworkInfo().isConnectedOrConnecting());
}

@Test
public void networkInfoShouldReturnFalseCorrectly() {
networkInfo.setConnectionStatus(false);

assertFalse(connectivityManager.getActiveNetworkInfo().isConnectedOrConnecting());
}
}


STEP 6: Share it!
Ask for a pull request!


How did our testcase end up being?


@RunWith(XTestRunner.class)
public class ConnectionStatusTest {

@Inject
private ConnectivityManager cm;

@Test
public void connectionStatusShouldBeFalseWhenOffline() {
ConnectionStatus connectStatus = new ConnectionStatus(
getConnectivityManager(false));
assertFalse(connectStatus.isOnline());
}

@Test
public void connectionStatusShouldBeTrueWhenOnline() {

ConnectionStatus connectStatus = new ConnectionStatus(
getConnectivityManager(true));
assertTrue(connectStatus.isOnline());

}

private ConnectivityManager getConnectivityManager(boolean connected) {

ShadowNetworkInfo ni = Robolectric.shadowOf(cm.getActiveNetworkInfo());
ni.setConnectionStatus(connected);

return cm;
}
}



Conclusion:

While I code this simple Shadow for ConnectiviyManager someone else created a Shadow for AsyncTask and SQLite!
Shadows amount is increasing version by version => Android TDD is getting easier and easier thanks to Robolectric.

Robolectric it's a very cool fw. I consider myself a newbie to it but I could place some commits to it ;)
The support in the mailing list is excellent and I guess in the next release we will be able to add mvn support completely.

What are you waiting to give it a try?