Ejemplo de desarrollo de una aplicación Android completa

Después de publicar algunas guías de desarrollo, quizás algunos de vosotros estéis interesados en ver un ejemplo completo de una aplicación real. Pues de esto va este post: os he preparado y destripado la aplicación “Share your dreams”, o “Comparte tus sueños” según aparece nombrada en el Google Play de España.

¿Qué hace la aplicación?

Share your dreams es una aplicación sencilla pero muy resultona. Su propósito es servir de “diario de sueños“, es decir, cuando tenemos un sueño o una pesadilla es una pena que se nos olvide y se eche a perder ese sinsentido tan curioso que nos ha mantenido la mente ocupada toda la noche… pues bien, en Share your dreams podemos dejarlo registrado para recordarlo un tiempo después, y de paso, podemos compartirla de manera anónima con los demás.

Es más… aquellos que a veces nos ponemos místicos podremos llegar a preguntarnos si esa noche que tuve una pesadilla, y mi amigo tambien… ¿habrán tenido pesadillas otras personas cerca de mi? ¿guarda algún tipo de relación la cercania entre nosotros con lo que soñamos? ¿La gente en el mundo tiene más sueños o más pesadillas? ¿a qué le da más importancia? ¡Pues esto también podremos verlo gracias a un mapa y al registro de la ubicación aproximada de la persona que registra el sueño!

Y para terminar un juego: igual que el romantico acto de arrancar pétalos a un margarita no pasa de moda… ¿porque no incluir una bola mágica a la que preguntar si nuestros sueños van a cumplirse?

En este post voy a intentar explicar las características principales de cada una de estas funciones para arrojar un poco de luz sobre el desarrollo en Android.

Por favor, tened en cuenta que es solo un ejemplo, y que puede que existan formas mejores de hacer las cosas que todos estaremos encantados de leer si los compartis en los comentarios, pero que el objetivo de la aplicación es meramente didáctico y como tal se ha diseñado.

1 – Características generales importantes de la implementación

Lo primero que llama la atención de la aplicación es que existe la posibilidad de compartir los elementos de interés, es decir, pesadillas y sueños, con otros usuarios. De hecho, estos se comparten de manera geolocalizada (es decir, sabemos donde están ubicados en el mundo gracias a que incluyen sus coordenadas). Debido a esto ya vemos que tendríamos que pelearnos con la tecnología GPS y no solo eso, sino desarrollar un servicio web y alojarlo en internet, implementando un API segura para poder utilizar estas operaciones de registro, y las consultas desde los dispositivos.

Por suerte esto no va a ser necesario, ya que emplearemos el API de una plataforma llamada topoos que sirve para facilitar este tipo de tareas, y que gracias a su SDK es perfecto para desarrollar estas aplicaciones sin tener que preocuparnos de desarrollar nada en la web. Si no sabeis lo que es os recomiendo echarle un ojo a la página web ya que facilita mucho el desarrollo de aplicaciones móviles dependientes de contexto.

Además, también hemos visto que vamos a mostrar esta información en un mapa, para eso utilizaremos también otro API, en este caso el de Google Maps.

Para monetizar la aplicación y que nuestro esfuerzo se vea tristemente recompensado, vamos a incluir anuncios publicitarios, con el SDK de AdMob.

Debido a estas tres APIs el proyecto no funcionará directamente cuando descarguéis el código, ya que usar un API requiere incluir una serie de códigos secretos (API_keys o tokens) que no es buena idea publicar en un repositorio. Pero no os preocupeis porque precisamente para hacerlo funcionar está este post. :)

Puedes descargar la aplicación para Android desde Google Play aquí

http://bit.ly/shareyourdreams

2 – Descargar el código fuente

Como acabamos de ver, el código no funcionará bien hasta que no hayamos obtenido e incluido nuestras propias claves de las APIs utilizadas, pero es necesario descargarlo y tenerlo cerca para entender las explicaciones siguientes.

Podeis descargar el código de este proyecto desde el repositorio GIT:

http://github.com/findemor/shareyourdreams

3 – Obtener acceso a la plataforma topoos

Ya que topoos nos va a proporcionar todo lo necesario para trabajar con geolocalización y especialmente, en este caso, nos permite disponer de un completo API de servicios en la nube en los que poder almacenar y compartir información entre instancias de nuestra aplicación, se va a convertir en el eje centrar de esta aplicación, permitiéndonos preocuparnos únicamente de lo que nos interesa: registrar sueños y pesadillas.

Para usar topoos, lo primero que tenemos que hacer es ir al panel de desarrolladores, registrarnos y crear una nueva aplicación. Cuando hayamos creamos la aplicación nos dará una serie de tokens (son secretos asi que los que publico aquí no son válidos y solo están a modo de ejemplo).

Aplicación registrada en topoos

Aplicación registrada en topoos

Estos tokens nos permiten crear usuarios y obtener nuevos tokens de acceso. Como nuestra aplicación no necesita distinguir e identificar usuarios individuales, y para facilitar las explicaciones, vamos a utilizar únicamente el que se llama APPTOKEN_ADMIN, es decir, una firma que nunca caduca y que proporciona permiso de alto nivel a nuestra aplicación en topoos.

También necesitaremos descargar el SDK de topoos para Android y arrastrarlo a la carpeta libs de nuestro proyecto. (Habrá que crearla si no existe).

4 – Configurar la aplicación con el token de topoos

Podréis observar que el código de la aplicación está organizado en 4 paquetes:

  • .shareyourdreams: Contiene las Actividades (pantallas) de la aplicación)
  • .shareyourdreams.internal: Contiene clases de uso interno de la aplicación, como entidades y el acceso y creación de la base de datos.
  • .shareyourdreams.map: Contiene las clases que nos facilitan tareas comunes para trabajar con el mapa de Google Maps.
  • .shareyourdreams.topoos: Contiene las clases que definen como se va a comunicar nuestra app con topoos.

Pues bien, abrimos el fichero AccessInterface.java de este último paquete y en el atributo TOPOOS_ADMIN_APP_TOKEN escribimos el que hemos obtenido en el Paso anterior en el panel de desarrollador de topoos al crear nuestra app.

public class AccessInterface {

	////Must get your tokens from topoos developer panel https://developers.topoos.com
	private static final String TOPOOS_ADMIN_APP_TOKEN = "70a05a65-097f-429b-8e43-6b9b6078xxa7";

Si vemos la documentación de topoos, podremos ver que un mecanismo perfecto para guardar los sueños y pesadillas es el que topoos denomina Puntos de Interés, pero que estos Puntos de Interés necesitan que existan una serie de categorías con los que organizarlos y consultarlos. Por lo que antes de continuar hay que generar UNA ÚNICA vez estas categorias. Vamos a ver como:

  1. En MainActivity.java descomenta las siguientes líneas del método onCreate:
    public class MainActivity extends CustomActivity {
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            //The first time we must manually create the necessary POIs categories, and get the IDs for use in the whole app
            /*
            try {
    			com.devergence.shareyourdreams.topoos.AccessInterface.PreregisterApplicationNeccessaryItems(this);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
            */
            //Now the application cloud context is ready
    
        }
    
  2. Ejecuta la aplicación en modo DEBUG.
  3. Apunta los valores que aparecen así en el LogCat de Eclipse.

    Resultado del Logcat

    Resultado del Logcat

  4. Vuelve a comentar las líneas del punto 1 en el onCreate de MainActivity.

Lo que estamos haciendo es registrar las Categorias que necesitamos, y un Punto de Interés especial que más adelante explicaremos para que es (un pequeño truco de regalo :) ). Como esto solo hay que hacerlo una vez en la vida y ya no vale para nada más,  lo podríamos haber hecho directamente en topoos a través de llamadas al API Rest, pero así todo queda escrito con código Java.

Ahora abrimos el fichero POICategories.java y damos los valores apropiados según lo que hemos visto en el LogCat del punto 3.

public class POICategories {

	//The INTEGER identifier must be created when we register our POI Categories manually the first time

	public static int DREAM = 30; //Represents a good Dream
	public static int NIGHTMARE = 31; //Represents a Nightmare
	public static int USER = 33; //Category for user registered POIs
	public static int SYSTEM = 32; //Category for app internal POIs
}

Después, tambien a partir del dato que aparece en el LogCat, damos valor al atributo PREREGISTERES_POI_FOR_COUNTERS del fichero AccessInterface.java.

	////We must use the integer id that we got when we registered this POI the first time (manually)
	private static final int PREREGISTERED_POI_FOR_COUNTERS = 6614;

5 – La aplicación ya funciona, pero el mapa se ve gris.

Al igual que antes, el API de Google Maps que estamos utilizando para visualizar el mapa necesita un Token de Acceso, y si no se configura el mapa se mostrará como un mar gris muy desagradable. Como es bastante largo de explicar y ya hay guías muy completas para obtener un token de google maps, seguro que os sirve con la referencia oficial para configurar este parámetro.

https://developers.google.com/maps/documentation/android/start#obtain_a_google_maps_api_key

Si preferis un tutorial, hay uno que os recomiendo para obtener el API Key del Google maps v2 en Android:

http://www.sgoliver.net/blog/?p=3244

En cualquier caso, una vez que tengais un API key valido, el fichero que teneis que tocar es únicamente el AndroidManifest.xml.

<meta-data android:name="com.google.android.maps.v2.API_KEY"
android:value="XXXXXXXXXXXXXXXXXXXX_PLACE_HERE_YOUR_GOOGLEMAPS_APIKEY"/>

6 – El mapa se ve, pero no aparece la publicidad.

Ocurre exactamente lo mismo que en los puntos anteriores, necesitamos el Token de un API para acceder a este servicio de publicidad. Para esto debemos ir a AdMob, crear una cuenta y configurarla. Damos de alta un perfil y nos darán una pequeña clave que debemos incluir en el layout ads_item.xml de la aplicación, en el atributo ads:adUnitId.

Si este paso no se completa no pasa nada, es opcional, pero no habrá publicidad en la aplicación.

7 – ¡La aplicación funciona!

Hagamos entonces un repaso para entenderla mejor.

7.1 – La pantalla principal.

La actividad MainActivity es la pantalla principal. Carece de funcionalidad salvo como menú principal.

Menu principal

Menu principal

Me gustaría agradecer el estupendo trabajo que ha hecho @neld_ayanami para dejarla así de bonita con su magnífico trabajo de diseño.

7.2 – La pantalla de registro de Sueño/Pesadilla

La actividad UploadActivity contiene ambas funcionalidades. Recibe un parámetro “type” a través de los Extras, y así puede saber si fue invocada para registrar una pesadilla o un sueño. En función de eso mostrará un aspecto u otro y realizara una u otra acción al pulsar el botón de enviar.

Publicar

Publicar

Como vamos a geolocalizar los sueños, necesitamos saber la ubicación GPS del dispositivo. Para eso nos suscribimos al LocationManager del sistema y no permitiremos que el usuario pulse enviar (el botón estará desactivado) hasta que haya escrito algun texto y hasta que el chip GPS se haya calentado y haya obtenido la ubicación aproximada en la que se encuentra.

Cuando tenemos ambos datos, lo unico que haremos será hacer la llamada al SDK de topoos para registrar el Punto de Interés con estos datos. La categoría que le pongamos al Punto de Interés sera la que nos permite distinguir sueños de pesadillas. Ademas siempre lo metemos en una subcategoria (USER) para saber que este elemento lo ha registrado el usuario y no el sistema, por si en el futuro quisiesemos distinguir los manuales de los automaticamente registrados.

Como el tiempo de respuesta de una llamada a un API depende de la conexión que tenga el usuario en ese momento, lo hacemos dentro de un hilo secundario para evitar bloquear la aplicación si la conexión es mala, y mientras tanto mostramos un Progress Dialog.

Detalle: Fijaos que en este punto, además de registrar el POI en topoos, estamos registrandolo en la base de datos local, y tambien estamos dando de alta un elemento Warning en el punto de interés que creamos al configurar la aplicación (que es totalmente opcional pero que más adelante explicaremos el truco).

7.3 – La Base de datos local

La actividad DatabaseActivity contiene una lista de elementos que han sido registrados desde este dispositivo, es decir: los sueños y pesadillas que se han creado desde ahí en el punto 7.2.

Base de datos

Base de datos

Esta actividad es muy sencilla, consulta la base de datos, que contiene toda la información relevante para el usuario de un punto de interés, y los muestra en una lista adornada con icono en función de si es sueño o pesadilla.

Como ya hemos visto esto en las guias no lo detallo mucho, pero es un buen ejemplo real de uso de Bases de datos y listas personalizadas.

7.4 – El Mapa

La actividad MapActivity implementa el mapa de Google Maps.

Sueños cercanos

Sueños cercanos

En él se hacen varias cosas:

  • Se obtiene la posición actual del usuario, igual que hicimos en el paso 7.2, para saber donde centrar el mapa y pedir los sueños y pesadillas cercanos.
  • En un hilo secundario, obtenemos los sueños y pesadillas cercanos: fijaos lo sencilla que es esta tarea gracias al SDK de topoos, por eso lo hemos elegido.
  • En el hilo secundario, consultamos los contadores mundiales de sueños y pesadillas registrados. Este es el tip/truco al que me he referido varias veces a lo largo del post, y que explico al final en detalle. :)
  • Mostramos un circulo con transparencia que representa el radio de búsqueda.
7.5 – La pantalla de adivinación

La actividad SpellActivity implementa la función más divertida y simple de todas. Su objetivo es que el usuario se divierta intentando averiguar si su sueño se cumplirá o no.

Generando el hechizo

Generando el hechizo


El código es muy simple y no tiene elementos especiales, pero sí algunas transiciones y animaciones (como el uso de un gif animado en android) que puede ser curioso (si bien la alternativa escogida, usando un webview, es la más simple y por ello veréis que desafortunadamente no funciona en todos los dispositivos).

7.6 – Otras pantallas

Vereis que hay otras actividades que carecen de interés en este post:

  • AboutActivity: es la tipica pantalla donde hay información de desarrollador.
  • SplashscreenActivity: se muestra durante un par de segundos cuando la aplicación se abre, a modo de presentación.
7.7 – Importante! La herencia de Actividades

En el código del proyecto podeis ver que hay clases abstractas para los distintos tipos de actividades: CustomActivity, CustomListActivity y CustomMapActivity.

Estas clases son las que heredaremos en las demás actividades del proyecto, en lugar de las clásicas “Activity” o “ListActivity”.

El objetivo de estas clases es autenticar el usuario de topoos de la manera más sencilla, y permitir meter facilmente analíticas de aplicación si lo deseamos.

Veamos por ejemplo la clase CustomActivity.java.

Si os fijais, lo que hace es definir comportamiento general para todas las actividades de nuestra aplicación, de este modo el código queda más limpio al poder reutilizar esto y no escribirlo en cada una.

  • En el método onCreate, llama al método que crea y almacena el token de topoos en las preferencias, para que no haga falta incluir el token de manera explícita en ninguna otra llamada. Lo podriamos hacer de ese modo, incluyendo el parametro AccessToken, pero así no tenemos que escribirlo.
  • En los métodos onStart y onStop, invocamos la operación del SDK de las analíticas si queremos registrarlas.
  • Añadimos los métodos que crean y manejan los menús de la aplicación, con la opción para ver la pantalla About.
7.8 – El truco para contar sueños y pesadillas

Lo he mencionado varias veces en los puntos anteriores, pero lo he dejado para el final ya que es un mero aunque interesante tip.

Cuando registramos un sueño o una pesadilla, estaría bien dar al usuario un contador de cuantos se han registrado de cada tipo en el mundo.

Para ilustrar un ejemplo de contador personalizado, ya que en topoos (ha nacido hace poco) aún no hay una operación para almacenar contadores, vamos a utilizar un Punto de Interés secreto. Este es el que registramos en el Paso 4 de configuración.

Lo que haremos será registrar warnings en este Punto de Interés. Cuando registremos una pesadilla, registraremos un warning de Duplicado, cuando registremos un sueño, registraremos un Warning de Cerrado.

Este punto de interés no vale para nada más, pero cuando querramos obtener este contador global, bastará con pedir la información del Punto de interés a topoos y leer estos dos contadores de warnings.

Digo que es un truco porque es evidente que los warnings fueron ideados con otro propósito, pero si no los vamos a utilizar del modo “oficial” es un truco muy resultón, ¿no creeis?.

8 – Resultado

Aqui tenéis el enlace al Google Play para descargar la aplicación o ver algunas capturas:

https://play.google.com/store/apps/details?id=com.devergence.shareyourdreams

9 – Conclusión

¡Ya está!

¿Que os ha parecido, fácil o difícil?

¿Se os ocurren otras aplicaciones interesantes basadas en geolocalización?

¿Creeis que hay algún punto que debería ser mejor explicado?

En cualquier caso, un saludo a todos,

y ya que estamos en estas fechas… ¡que tengáis un próspero desarrollo en Android en el 2013!

21 Comments / Add your own comment below

  1. Interesante tutorial.
    Estoy desarrollando el proyecto final de mi módulo y tengo una duda a la hora de utilizar la geolocalización en mi aplicación.
    Estoy desarrollando una webview, y la web que visualiza mi app utiliza un Api de Google que permite geolocalizar al usuario y medir distancias ente puntos de interés.
    He probado a dar todos los permisos de geolocalización a la app, pero no soy capaz de que me funcione la
    api de Google.
    Se que le tengo que dar permisos también en el archivo MainActivity.java, pero no consigo lograr que funcione.
    Me podrías ayudar?
    Muchas gracias!

    1. Hola Miguel,
      disculpa la tardanza, he estado un poco desconectado ultimamente, intentaré corregir eso xD. Espero que esta respuesta no sea necesaria porque ya lo hayas resuelto :).

      Por lo que comentas, estas desarrollando una aplicación que tiene un webview donde se va a visualizar una aplicación web que está implementada en otra parte y alojada en algún servidor web.
      Si esta premisa es correcta, y no estas utilizando algun framework HTML para crear tu aplicación (tipo Phonegap, etc), entonces aparentemente la api de google de la web y la de tu app android no tienen relación, y deberias intentar identificar tu problema unicamente en la parte web.

      Si te refieres a que estas cogiendo la ubicación GPS en el móvil (a traves del API de android) y enviandola como parámetro a la web (en la petición HTTP Rest) y el problema es que no puedes obtener dicha ubicación GPS en el movil para enviarla, entonces sí es un problema de android.

      Por favor, comprueba en que lado está el problema exactamente y, si me das más detalles al respecto, intentaré ayudarte en lo que pueda :).

      Un saludo.

  2. muchas gracias por toda la explicacion y por dejar el codigo abierto resulta de gran utilidad ya q hay informacion limitada acerca de android en español

  3. Muchas gracias por el tutorial, recien estoy iniciando en android y es de utilidad. Mi consulta es que al bajar el codigo en el eclipse se muestra un error en varias paginas. “NO puede resolver la variable R”….

    Entonces no puedo hacer el DEBUG y crear las categorias… que puede ser?…
    quize pegar aqui el error pero no permite…

    Gracias
    Ricardo.

    1. La variable R hace referencia a los recursos, que se generan cuando compilas la aplicación. Por eso, algunos recursos dan error de compilación hasta que intentas hacer el debug, momento en el que desaparece.
      Cuando no desaparece puede deberse a varias cosas:
      – estas haciendo un import de un paquete que no existe en tu proyecto; solución: revisa los imports.
      – realmente el recurso no existe, o no se han podido compilar los recursos; solución: asegurate de que tus ficheros en la carpeta Res de tu proyecto no tienen errores al compilar, porque de ser así impedirían que se genere R.
      – Haz un Proyect / Clean de tu proyecto en eclipse. A menudo Eclipse no se entera de que los recursos han cambiado si modificas el código.

      Un saludo!

  4. Buenos dias Findemor

    Exelente tu blog …
    Te queria pedir un favor no se si me puedes recomendar algun link de te explique la utilizacion de Eclipse por ejemplo me baje tu fuente pero tengor problemas al compilarla

    Muchas gracias

    1. En función del problema que estés teniendo para compilarlo, puede deberse a que falten librerias o que hayas importado el proyecto de manera incorrecta.

      – Comprueba que la versión del API de Android que has configurado en tu proyecto es correcta (v8 deberia servir)
      – Comprueba que dispones de las librerias de google maps y del la librería de topoos, utilizadas en este proyecto.

      ¿Que error te da al compilar?

      PD: No conozco tutoriales de eclipse, pero estoy seguro de que si describes tu problema con precisión google te podrá ayudar :).

      Un saludo y suerte.

  5. Yo creo que es un gran redacción. Saludos.

  6. Me intereso mucho su publicacacion de verdad es bueno para quienes apenas comenzamos y talvez no tenemos la suficiente informacion .

    Apenas comienzo y es bueno ver lo que es posible lograr algo asi .

    Actualmente uso eclipse indigo y ubuntu soy estudiante de ingenieria. seguiere revisando su sitio web. y ver si tiene algunas recomendaciones.

  7. hola que tal me parece interesante y util lo que ha conseguido , actualmente soy estudiante de ingenieria y es bueno ver lo que podria llegar a desarrollar .

    actualmente utilizo eclipse en ubuntu para desarrollar aplicaciones y la verdad seria bueno recibir recomendaciones de alguien que conoce del tema.

    revisare su biografia y tratare de ponerme en contacto .
    la verdad me serviria de mucho algunos de sus consejos como lo ha sido su sitio web.

  8. Hola muy bueno el tutorial amigo, pero, jejeje en eclipse lo importe td correctamente y aal darle al debug me aparecen errores y me dice que solucione los errores primero y no encontre el error..

  9. Hola,

    He seguido todos los pasos y y lo único que no me ha funcionado es que me aparezca el mapa de google, le he añadido el API key del google v3, pero no me aparece. ¿ Que puede ser ?

  10. Muchísimas gracias por el tutorial!

  11. Hola. Si lo importo en eclipse sin hacer nada mas me da muchos errores de compilación. Estos errores los puedo corregir cambiando el “Project build target” del proyecto a “Google APIs”, pero entonces no consigo ni depurar ni ejecutar ni nada. ¿Podrías ayudarme?. Gracias!

    1. Hola!

      He actualizado el código del proyecto en GitHub para que funcione con Google Services (y he migrado el codigo de Google Maps a la v2 del API).

      Ahora, para evitar esos errores, podrías poner En Project Build Target la Android 4.0 (no la Google APIs).
      Y tienes que enlazar la libreria de Google Play Services… (está incluida en la carpeta external_libs, aunque es recomendable que utilices la de la carpeta del SDK que tengas instalado en tu equipo).

      Si aún así no funciona, por favor compártelo con nosotros :)

      1. alexander jaramillo

        en mi caso nunca pude utilizar ECLIPSE. siempre me decia ERROR en los archvos SDK de instalacion, no se trata de la forma en que trabajamos sino, talvez, en un archivo imcompleto a la hora de instalar desde google apps.
        ahora estoy descargando ANDROID STUDIO, a ver que me dice.

  12. Tengo un problema muy raro. Aunque cambie el valor de TOPOOS_ADMIN_APP_TOKEN a la hora de crear las categorías se mandan las XXXXXXXXXXXXXXXX (pues lo puedo ver en el Logcat). Pero las XXXXX no están en ninguna parte del proyecto. ¿Alguien me puede ayudar?. Gracias

    1. Hola Juan Antonio. Creo que ya sé lo que está pasando en tu caso… Probablemente has ejecutado el proyecto alguna vez antes de cambiar el valor del TOKEN. Al hacer eso, se habra guardado el valor XXXXX en las preferencias (de donde lo está leyendo cuando ejecuta las operaciones).

      Para solucionarlo, tan solo tienes que borrar la aplicación y ejecutarla de nuevo (con el TOKEN correcto) o simplemente borrar los datos de la app en el dispositivo.

      Un saludo!

      (PD: Aprovecho para anunciar que he actualizado la aplicación para que los mapas funcionen en la v2 de Google Maps).

  13. Enhorabuena ! Estupendo post y estupenda aplicación , estoy intentadola hacer funcionar para entender el funcionamiento de esta api y he seguido todos los pasos correctamente, pero al pulsar sobre los botones de DREAM o NIGHTMARE se me detiene la aplicación , porque puede ser ? utilizo 4.1.2 Google APIS, puede ser por algo de eso ? Gracias de antemano un saludo !

  14. alexander jaramillo

    he buscado mucha informacion con respecto a ejemplos que me guien claramente hacia mi meta. este aporte es lo mas claro e ilustrativo que he podido ver. esta forma de explicar es una luz en mi camino.
    queria entender la profundidad y esencia de una aplicación, aqui entendi muchas cosas.

    solo tengo una duda: la pregunta sera tonta, pero prefiero parecer tonto a ser un ignorante toda la vida.
    1. este código fuente lo debo copiar directamente de la aplicación, desde un celular y pasarlo al computador; ó ¿ la aplicación de la web tiene las misma funciones y características ?

  15. Pingback: Share your dreams APK 1.3 Download - BEST APK COLLECTION

Leave a Reply

Your email address will not be published. Required fields are marked *