msgbartop
Desarrollador web y android, con todo lo que ello implica
msgbarbottom

19 Feb 12 Leer/parsear archivo XML en Android mediante SAX

Con motivo del concurso #BigBangApps convocado por la web Ideas4All en que proponían desarrollar una aplicación utilizando su API, me puse a programar una aplicación para Android de la web. La API de Ideas4All devuelve los datos en XML (hubiese preferido en JSON pero de momento no lo permite) por lo que el “gran secreto” de la app es leer correctamente este tipo de archivos.

Hay varias formas de leer archivos XML, siendo una de ellas mediante SAX (Simple API for XML). En este post voy a explicar los pasos para leer/parsear correctamente un archivo XML disponible en Internet.

El fichero de ejemplo que queremos leer es el listado de categorías:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8"?>
<categories type="array">
  <category>
    <id type="integer">6</id>
    <name>Vida/Salud</name>
  </category>
  <category>
    <id type="integer">3</id>
    <name>Sostenibilidad</name>
  </category>
...
...
</categories>

Lo primero que necesitamos es una clase que utilizaremos para guardar los datos de cada categoría. El objetivo es devolver una lista de objetos del tipo categoría, donde se encontraran todas las categorías leídas del XML.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class ParsedCategoryDataSet {
 
    private String id = null;
    private String name = null;
 
    public String getId() {
      return id;
    }
    public void setId(String extractedString) {
     this.id = extractedString;
    }    
 
    public String getName() {
     return name;
    }
    public void setName(String extractedString) {
     this.name = extractedString;
    }
 
    public String toString(){
         return "name = " + this.name;
    }	
}

Como podemos observar, solamente se trata de una clase con setters y getters para almacenar los datos de cada categoría.

Ahora pasamos a crear la clase con la que parsearemos el archivo XML mediante SAX en Android.
El modelo SAX lee secuencialmente el fichero XML y ejecuta varios métodos (que podemos controlar) por cada elemento leído. Estos métodos son:

- startDocument(): comienza a leer el XML.
- endDocument(): ha terminado de leer XML.
- startElement(): ha encontrado el comienzo de una etiqueta XML.
- endElement(): ha encontrado el cierre de una etiqueta XML.
- characters(): texto que ha encontrado entre el comienzo y el cierre de una etiqueta

Estos métodos se encuentran en la clase org.xml.sax.helpers.DefaultHandler, de la que heredaremos nuestro propio parseador de categorías:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import java.util.Vector;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
 
public class CategoryHandler extends DefaultHandler{
 
    public CategoryHandler() {
	super();
	this.myParsedCategoryDataSet = new Vector<ParsedCategoryDataSet>();
    }	
 
    // Variables de control para saber cuando estamos en el interior de cada etiqueta
    @SuppressWarnings("unused")
    private boolean in_category = false;
    private boolean in_id = false;
    private boolean in_name = false;
 
    // En esta variable guardamos el texto encontrado entre las etiquetas
    StringBuilder builder;
 
    // Aquí guardamos cada objeto categoria
    private ParsedCategoryDataSet DataSet;
 
    // Vector donde se guardaran todas las categorías encontradas
    private Vector<ParsedCategoryDataSet> myParsedCategoryDataSet; 
 
    public Vector<ParsedCategoryDataSet> getParsedCategoryDataSets() {
        return this.myParsedCategoryDataSet;
    }      
 
    public Vector<ParsedCategoryDataSet> getParsedData() {
         return this.myParsedCategoryDataSet;
    }
 
    @Override
    public void startDocument() throws SAXException {
         // Comenzamos a leer el fichero xml, creamos el vector donde se guardarán las categorías
         this.myParsedCategoryDataSet = new Vector<ParsedCategoryDataSet>();
    }
 
    @Override
    public void endDocument() throws SAXException {
         // Ha terminado de leer el fichero, en este paso no hacemos nada
    }     
 
    @Override
    public void startElement(String namespaceURI, String localName,
              String qName, Attributes atts) throws SAXException {
         if (localName.equals("category")) {
             // Ha encontrado la etiqueta principal de cada elemento "category"
             // Creamos un nuevo objeto categoría donde iremos guardando los datos
             this.in_category = true;
             DataSet = new ParsedCategoryDataSet();
         }else if (localName.equals("id")) {
             // Estamos dentro de la etiqueta "id", creamos el StringBuilder que utilizaremos
             // en el método characters para guardar el contenido
             this.in_id = true;
             builder = new StringBuilder();
         }else if (localName.equals("name")) {
             // Estamos dentro de la etiqueta "name", creamos el StringBuilder que utilizaremos
             // en el método characters para guardar el contenido
             this.in_name = true;
             builder = new StringBuilder();
         }
    } 
 
    @Override
    public void endElement(String namespaceURI, String localName, String qName)
              throws SAXException {
        if (localName.equals("category")) {
            // Hemos llegado al final de la etiqueta principal de cada elemento "category"
            // Añadimos al vector el elemento leído
            this.in_category = false;
            myParsedCategoryDataSet.add(DataSet);
        }else if (localName.equals("id")) {
            // Ha encontrado la etiqueta de cierre de "id"
            this.in_id = false;
        }else if (localName.equals("name")) {
            // Ha encontrado la etiqueta de cierre de "name"
            this.in_name = false;
        }
    } 
 
    @Override
    public void characters(char ch[], int start, int length) {
 
       // Si estamos dentro de la etiqueta "id"
       if(this.in_id){
       	   if (builder!=null) {
       	        for (int i=start; i<start+length; i++) {
                    // Añadimos al StringBuilder (definido al encontrar el comienzo de la etiqueta "id")
                    // lo que haya entre las etiquetas de inicio y fin
       	            builder.append(ch[i]);
       	        }
       	   }        	 
           // Lo asignamos al "id" del objeto categoría (DataSet)
       	   DataSet.setId(builder.toString()); 
       }
 
       // Si estamos dentro de la etiqueta "id"
       if(this.in_name){
           if (builder!=null) {
    	       for (int i=start; i<start+length; i++) {
                    // Añadimos al StringBuilder (definido al encontrar el comienzo de la etiqueta "name")
                    // lo que haya entre las etiquetas de inicio y fin
    	            builder.append(ch[i]);
    	        }
     	   }            	 
           // Lo asignamos al "name" del objeto categoría (DataSet)
           DataSet.setName(builder.toString()); 
       }   
 
   } 
}

El código está comentado y creo que se explica bastante bien. Me consta que algunos programadores leen el contenido que se encuentra entre las etiquetas de inicio y cierre, cuando llegan a esta última etiqueta en lugar de en el método characters. Yo me he encontrado con muchos problemas haciéndolo así ya que se corre el riesgo de no conseguir leer todos los caracteres que realmente hay. La propia documentación del método lo explica:

The Parser will call this method to report each chunk of character data. SAX parsers may return all contiguous character data in a single chunk, or they may split it into several chunks; however, all of the characters in any single event must come from the same external entity so that the Locator provides useful information.

Ya tenemos casi todo lo necesario para leer el fichero XML de la API. Solamente nos queda implementar el método que parseará el archivo utilizando nuestra clase.
Esto solo es el extracto del método que lee el XML, encontraréis el código completo de la activity aquí, donde también se hace uso de la combinación de ProgressDialog y Thread para mostrar un mensaje de “cargando” mientras se leen los datos (este tema da para otro post :) ).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
...
...
private Vector<ParsedCategoryDataSet> categories;
private String categories_url = "http://url_de_la_api/categories.xml";
...
...
 
public void loadCategories() {
 
    try {
 
        // Url del archivo XML
        URL url = new URL(categories_url);
 
        SAXParserFactory spf = SAXParserFactory.newInstance();
        SAXParser sp = spf.newSAXParser();
 
        XMLReader xr = sp.getXMLReader();
        // Utilizamos nuestro propio parseador (CategoryHandler)
        CategoryHandler myExampleHandler = new CategoryHandler();
        xr.setContentHandler(myExampleHandler);
 
        InputSource is = new InputSource(url.openStream());
        // Le indicamos la codificación para evitar errores
        is.setEncoding("UTF-8");
        xr.parse(is);
 
        // Asignamos al vector categories los datos parseados
        categories = myExampleHandler.getParsedData();
 
     } catch (Exception e) {
          // Ha ocurrido algún error
          Log.e("Ideas4All", "Error", e);
     }        
 
}

Y eso es todo, no olvidéis indicar en el AndroidManifest.xml solicitar permisos de acceso a Internet.

    <uses-permission android:name="android.permission.INTERNET"></uses-permission>

Podéis encontrar la aplicación completa en github:
Código fuente de la aplicación de Ideas4All para Android

Etiquetas: , , , , , , , ,

13 Feb 12 Paso de datos/variables entre actividades en Android

Una de las cosas más habituales cuando desarrollamos una aplicación para Android, es poder “enviar” datos (variables, objetos, etc.) desde una Activity a otra. En términos generales, una Activity es una “pantalla” de nuestra aplicación.

Para realizar esta tarea, Android pone a nuestra disposición los llamados “Intent“. En general, utilizaremos un Intent cuando queramos movernos de una actividad a otra, permitiéndonos a su vez pasar datos desde la Activity en la que estamos hacia la nueva.

1
2
3
4
5
6
// Pasaremos de la actividad actual a OtraActivity
Intent intent = new Intent(this, OtraActivity.class);
intent.putExtra("variable_integer", objeto.getId());
intent.putExtra("variable_string", objeto.getNombre());
intent.putExtra("objeto_float", objeto.getPrecio());
startActivity(intent);

- En la segunda línea creamos un Intent, al que se le pasa como parámetros la actividad actual (this) y la actividad a la que queremos pasar (en este caso OtraActivity.class).

- En las tres líneas siguientes definimos tres variables de tres tipos diferentes. En el primer caso, estaremos creando una variable llamada “variable_integer” con el contenido de objeto.getId(). Esta variable se “envía” a OtraActivity y podremos recuperar su contenido allí para utilizarlo.

- En la última línea, iniciamos la nueva actividad pasando como parámetro el Intent que hemos creado.

El código que viene a continuación es el que se ejecutará en la actividad OtraActivity. Se muestran dos formas de recuperar las variables, se puede utilizar la que más convenga en cada ocasión.

1
2
3
4
5
6
7
8
9
10
11
12
// Estamos en OtraActivity
int recuperamos_variable_integer = getIntent().getIntExtra("variable_integer");
String recuperamos_variable_string = getIntent().getStringExtra("variable_string");
float recuperamos_variable_float = getIntent().getFloatExtra("objeto_float");
 
// O también de esta otra forma
 
// Estamos en OtraActivity
Bundle datos = this.getIntent().getExtras();
int recuperamos_variable_integer = datos.getInt("variable_integer");
String recuperamos_variable_string = datos.getString("variable_string");
float recuperamos_variable_float = datos.getFloat("objeto_float");

Es importante que sepamos de que tipo son las variables que enviamos en el Intent, ya que deberemos asignar esos valores al tipo de variable correcto.

Etiquetas: , , , , , , ,

10 Jan 12 Aplicación Cercanías Renfe para Android liberada como open source

Como anunciaba en el post anterior (Me han suspendido la aplicación de Cercanías Renfe para Android) he liberado el código fuente de la aplicación Cercanías Renfe para dispositivos Android.

Así mismo, también se puede descargar el fichero .apk de la aplicación e instalarla directamente es vuestros móviles, tablets, etc.

El único requisito para utilizar el código fuente y crear tu propia aplicación, es que sea liberada como código abierto. Nada más.

El código no está excesivamente documentado, quizás haga un tutorial en mi blog explicando paso a paso como funciona la aplicación.

Una vez más, gracias a todos por los ánimos y el apoyo recibido. ¡GRACIAS!

Pd.: Si decides crear tu propia aplicación o reutilizar el código, deja un comentario!

Etiquetas: , , , , , ,

04 Jan 12 Me han suspendido la aplicación de Cercanías Renfe para Android

2 años, 100.730 instalaciones totales y 51.896 instalaciones activas. Eso es lo que ha durado mi aplicación de Cercanías Renfe para Android.

Ayer, día 3 de enero, recibo un email de Google informándome de que “mi aplicación vulnera los derechos de propiedad industrial de RENFE-Operadora” y había sido suspendida. Concretamente por la utilización inconsentida de sus signos distintivos, lo que constituye un acto de competencia desleal.

¿Competencia desleal? Es cierto que utilizo el logotipo de Cercanías como imagen de la aplicación, pero de ahí a ser competencia desleal… Como bien dijo @nacmartin en Twitter: “Serías competencia si tuvieras tu propia red ferroviaria.”

El email que recibo proviene de Google pero, no sé si por error, puedo leer el mensaje que el abogado de Renfe (se le puede encontrar fácilmente en Linkedin) envía a Google y es ahí donde puedo leer lo de competencia desleal (ya que Google ni lo menciona). El mensaje que envía es un copy&paste clarísimo, con tres párrafos donde se repite lo mismo con diferentes palabras.

No me gusta que Google haya suspendido la aplicación sin yo poder defenderme de ninguna manera. Si es por utilizar el logotipo de Cercanías, podría haber modificado la aplicación y subir otro logo, por ejemplo el de un tren parado en mitad de la vía (sería una buena representación de los trenes de Cercanías de Renfe).

No puedo modificar la aplicación ni tampoco realizar ninguna acción sobre ella: descargar el código, descripciones, etc.

El mensaje del abogado se envió el 29 de diciembre de 2011 y el día 3 ya estaba suspendida. Bastante rápidos para lo que les interesa.

La decisión que he tomado es liberar el código y subir el apk de la aplicación a mi blog para su libre descarga. No tengo intención de seguir beneficiando a Renfe con la aplicación y además de manera gratuita (no he ganado un solo céntimo con la aplicación, era totalmente gratuita y sin publicidad). No dejaré de preocuparme por ella y la iré actualizando (se que existe alguna forma para que las actualizaciones se descarguen desde mi blog, como dice @biriru)

Gracias a todos por los mensajes y las palabras de ánimo que me habéis dejado en Twitter, la verdad que me han desbordado y no puedo contestar a todos. ¡GRACIAS!

Aquí algunos twits que me han parecido interesantes:

Santi Núñez @snunsan
Incapaz de crear app mínimamte seria, @Renfe denuncia la app #Android de @jonseg por “compentencia desleal” y Google la suspende #hazteFan

aurelio hernández @ahdezsanchez
Renfe se supera. No solo tienen la web más vergonzosa que se recuerda, sino que hace que retiren apps independientes, como la de @jonseg

Dani Rubio @vegaquark
@jonseg Suele pasar que las empresas que desconocen el terreno meten la pata… Es como los famosos en twitter…

Rubén Hidalgo @rhidalgo
@jonseg 100veces mas practica tu app,al final estas facilitando el uso a las personas que lo utilizamos,cansado de #renfe #renfelibreAndroid

papakorkel @papakorkel
@jonseg ¿Desleal porque no es puta mierda como su página web?

Josean Bilbao @joseanbilbao
@jonseg otra muestra más de su incompetencia, en lugar de acercarse al talento y colaborar, lo eliminan. #fail #renfe

Albert Mata @almata
@jonseg yo creía que en Android había libertad y no eran como los malísimos de Apple y no pasaban esas cosas…

rnesto G. Aroca @ErneX
@snunsan @Renfe @jonseg Renfe como siempre, cubriéndose de gloria. Son unos incapaces.

Salvador López @salvad0rlopez
@jonseg yo uso tu app , una lastima que te la quiten del market ya que es fantastica, espero que sigas desarrollandola. :-)

Javier Eguiluz @javiereguiluz
@jonseg Ánimo Jon! El único consuelo es que Renfe reconoce que no puede ganarte, así que trata de eliminarte :( #android #renfe

Victor @vdesigner_es
Bravo por los señores de @renfe obligando a Google a eliminar la única app 100% funcional sobre sus propios servicios #BravoRenfe

A todos los RT, menciones y palabras de ánimo, solo puedo decir: ¡GRACIAS!

——-

Actualización 10 enero 2012: Ya está disponible el código fuente en github y puedes descargar el fichero .apk de la aplicación si echas un vistazo a la columna derecha del blog.

Actualización 4 enero 2012: Ahora mismo no tengo acceso a la última versión del código de la aplicación. En cuanto pueda (a partir del día 8 de enero) subiré el código a Github y publicaré el .apk en el blog.

Etiquetas: , , ,

15 Nov 11 Desarrollo Android: Obtener número de teléfono desde la aplicación

Con este simple código, podremos obtener el número de teléfono donde se está ejecutando la aplicación android.

Antes de nada, debemos añadir permisos al archivo manifest.xml:

<uses-permission android:name="android.permission.READ_PHONE_STATE" />

Y, a continuación, la función que nos devolverá el número de teléfono del teléfono donde se está ejecutando nuestra aplicación:

private String getPhoneNumber(){
  TelephonyManager mTelephonyManager;
  mTelephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); 
  return mTelephonyManager.getLine1Number();
}

Etiquetas: , , , , , ,

18 Feb 11 Desarrollo android: Rellenar un spinner con los datos de un array

En este ejemplo, vamos a rellenar un spinner (un combo, select o como queráis llamarlo) con los datos que tenemos en un array.

Añadimos el spinner en la plantilla:

<Spinner android:id="@+id/spinner_animales"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
/>

Creamos un archivo llamado arrays.xml en la carpeta /res/values/ de nuestro proyecto e insertamos el siguiente contenido:

<resources>
	<string-array name="animales">
		<item>Elefante</item>
		<item>Tortuga</item>
		<item>Conejo</item>
		<item>Ratón</item>
	</string-array>
</resources>

Por último, en la activity asignamos el array anterior al spinner mediante un ArrayAdapter:

Spinner spinner_animales = (Spinner) findViewById(R.id.spinner_animales);
ArrayAdapter spinner_adapter = ArrayAdapter.createFromResource( this, R.array.animales , android.R.layout.simple_spinner_item);
spinner_adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner_animales.setAdapter(spinner_adapter);

Y eso es todo. Si ejecutamos el proyecto se mostrará el spinner con los elementos del array.

Etiquetas: , , ,

29 Nov 10 Aplicación para Android: Estaciones de esquí

Actualización:
- Planos de las estaciones (mantén el dedo pulsado para hacer zoom)
- Instalar en la tarjeta SD.
- Arreglados problemas con algunas webcams.

Añadidas las estaciones
-Fuentes de Invierno
-Navacerrada

Añadido Pirineo Francés
- La Pierre Saint-Martin
- Luz Ardiden
- Grand Tourmalet
- etc

Si falta alguna estación, ponte en contacto conmigo y la incluiré cuanto antes

——

Con esta aplicación podrás consultar en todo momento la cantidad de nieve y el estado de las pistas de esquí observándolas directamente a través de las webcams.

Disponibles las estaciones de esqui de toda España, contando todas ellas con varias webcams.

Obtendrás información del estado de las pistas, espesor y calidad de la nieve, remontes abiertos, pistas abiertas, kilómetros abiertos, etc.

Toda la información sobre estaciones de esquí y pistas de ski.

- Alto Campoo
- Astún
- Candanchú
- Formigal
- Baqueira Beret
- Valdelinares
- Valdezcaray
- Sierra Nevada
- etc.

Para descargarla, solamente deberemos buscar “estaciones esqui” en el Android Market o a partir del siguiente código QR:
estaciones-esqui-android-qrcode

Etiquetas: , , , , ,

26 Oct 10 Aplicación para Android: Oficinas de la BBK

Con esta aplicación ya puedes buscar las oficinas de la BBK más cercanas a tu posición.

Es una primera versión básica. Las próximas actualizaciones serán:
- Buscar por número de oficina
- Información de la oficina: teléfono, horarios, etc.
- Vuestras sugerencias en los comentarios!

Para descargarla, solamente deberemos buscar “bbk” en el Android Market o a partir del siguiente código QR:
bbk-qrcode

Etiquetas: , , , , ,

20 Oct 10 Emulador Android: Acceder a la web en desarrollo en la propia máquina (localhost)

En mi caso, cuando estoy desarrollando una aplicación web (o móvil) desarrollo en local sincronizando con un servidor svn. Para poder ir comprobando la web, creo un nuevo sitio en Apache y fuerzo la ip en el /etc/hosts a la propia máquina (localhost).

Este podría ser un ejemplo de configuración de una web para Apache. Todos los ejemplos de este post son para Ubuntu. Evidentemente tenemos que tener instalado un servidor Apache en nuestra máquina.

El archivo lo pondríamos en /etc/apache2/sites-available/ejemploweb

<VirtualHost *:80>
   ServerAdmin info@ejemploweb.com
   DocumentRoot /var/www/vhosts/ejemploweb
   ServerName ejemploweb.com
   ServerAlias *.ejemploweb.com
   ErrorLog /var/log/apache2/ejemploweb_error.log
   CustomLog /var/log/apache2/ejemplo_access.log common
   DirectoryIndex index.php
   <Directory "/var/www/vhosts/ejemploweb">
        Options Indexes FollowSymLinks
        Order Allow,Deny
        Allow from all
        AllowOverride all
   </Directory>
   </Directory>
</VirtualHost>

Suponiendo que el contenido de nuestra web se encuentra en el directorio /var/www/vhosts/ejemploweb.

Tenemos que hacer un enlace simbólico a /etc/apache2/sites-enabled

sudo ln -s /etc/apache2/sites-available/ejemploweb /etc/apache2/sites-enabled/ejemploweb

Y reiniciamos apache:

sudo /etc/init.d/apache2 restart

Ya lo tendríamos configurado. Ahora tenemos que forzar que el dominio que hayamos seleccionado lo busque en localhost o en la ip 127.0.0.1. Esto lo podemos hacer en nuestro archivo /etc/hosts

sudo nano /etc/hosts

Y añadimos la siguiente línea al final del archivo:

127.0.0.1 www.ejemploweb.com ejemploweb.com

Ahora, si en nuestro navegador vamos a la dirección http://ejemploweb.com, nos cargará la página que tenemos en local y hemos configurado anteriormente.

El objetivo de este post es poder acceder a esta web en desarrollo desde el emulador de Android. El emulador de Android no tiene en cuenta el archivo /etc/hosts, por lo que al intentar acceder a la web ejemploweb.com desde el emulador, nos mostrará un error indicando que no se ha encontrado la página o veremos la web que tenemos en producción (si está online) y no en desarrollo. El emulador Android no hace caso al archivo /etc/hosts, lo único que hace es extraer las DNS que tenemos configuradas en nuestra máquina y copiarlas al propio emulador.

Si queremos que el emulador nos resuelva la web que tenemos en nuestro ordenador, deberemos configurar el archivo /system/etc/hosts propio del emulador Android.

Para ello, vamos a la carpeta tools platform_tools donde tenemos descargado el sdk de Android:

cd /home/user/android-sdk-linux_86/platform_tools

Lo primero que hacemos es saber el “serial number” del emulador que tenemos abierto (por que tenemos que tener un emulador de Android iniciado, por ejemplo, desde eclipse)

./adb devices

Y obtendremos un salida parecida a esta:

List of devices attached 
emulator-5554	device

El “serial number” del emulador es “emulator-5554″. En todos los comandos que escribamos a continuación, tenemos que indicar a que emulador queremos realizar los cambios:

Llamamos al comando adb con la opción remount para que no nos dé fallos de escritura:

./adb -s emulator-5554 remount

A continuación importamos el archivo /system/etc/hosts original que tenemos en el emulador Android (en el ejemplo, lo importamos a nuestra carpeta personal):

./adb -s emulator-5554 pull /system/etc/hosts /home/user

Ahora hacemos los cambios en el archivo que hemos importado, incluyendo al final del mismo la siguiente linea:

10.0.2.2  www.ejemploweb.com ejemploweb.com

Podemos comprobar que la ip es 10.0.2.2, que es una ip especial del emulador la cual hace referencia a nuestra máquina local. La ip 127.0.0.1, hace referencia al propio emulador Android.

Guardamos el archivo y lo volvemos a copiar al emulador:

./adb -s emulator-5554 push /home/user/hosts /system/etc

Y ya lo tenemos hecho! Si vamos al navegador dentro del emulador Android y escribimos la dirección http://ejemploweb.com, deberemos ir a la web que tenemos en desarrollo en nuestra máquina local.

Actualización:

Si os suelta un error, al intentar copiar de nuevo el archivo hosts al emulador, del tipo:
failed to copy “hosts” to “/system/etc”: No space left on device
failed to copy “hosts” to “/system/etc”: Out of memory

Hay que iniciar el emulador con el parámetro -partition-size 128:

./emulator -avd nombre_de_nuestro_avd -partition-size 128 &

Terminamos la orden poniendo “&” para que se ejecute en segundo plano (entornos linux).
El comando ‘emulator’ está dentro de la carpeta tools donde tenemos instalado el SDK.

También podemos especificar este comando en el propio eclipse. Lo hacemos en “Run/Run configurations”, pestaña “target” y escribimos

-partition-size 128

en el campo “Additional Emulator Command Line Options”.

Etiquetas: , , , ,

23 Mar 10 Aplicación Android: Webcams de tráfico en Vizcaya

Aquí va otra aplicación para Android que nos será de especial utilidad a los conductores de Vizcaya. Se trata de poder consultar las webcams de trafico de vizcaya al instante y así poder conocer el estado de las carreteras antes de realizar un desplazamiento. Podremos evitar las carreteras congestionadas antes de llevarnos una sorpresa.

Se incluyen webcams tan relevantes como las de Bilbao, Txorierri, Barakaldo, autopista A8, Derio, Zamudio, Aeropuerto, Cruces, Zorroza, Max Center, etc.

No vuelvas a meterte en un atasco con tu coche, evita las retenciones.

Utiliza el siguiente código para descargarte la aplicación o busca “trafico vizcaya” en el Android Market.
Tráfico Vizcaya

La aplicación de momento es un poco simple, si teneis alguna sugerencia no dudeis en dejarla en los comentarios. ¡Gracias!