curso apk.pdf

46
Home Blog Síguenos Conócenos Contacto Trasteando un HTC Desire IV. Cambiando HBOOT e instalando ROM Creando una aplicación de Android: primeros pasos 0. Creando una aplicación de Android: la presentación 1. Creando una aplicación de Android: primeros pasos 2. Creando una aplicación de Android: visión de conjunto y diseño del menú 3. Creando una aplicación de Android: el juego y la lógica (parte 1) 4. Creando una aplicación de Android: el juego y la lógica (parte 2) 5. Creando una aplicación de Android: mejoras (parte 1) 6. Creando una aplicación de Android: mejoras (parte 2) 7. Creando una aplicación de Android: empaquetado y publicación Hace tiempo adquirimos un par de HTC Desire con la intención de aprender un poco de desarrollo de aplicaciones para dispositivos con Android. Buscando por la web se encuentran tutoriales y guías muy buenas y snippets también muy buenos. Pero la mayoría son cosas puntuales, inconexas. Bien, el objetivo de la siguiente serie de entradas será el de desarrollar una aplicación completa para dispositivos con Android, empezando desde cero y acabando por la publicación de la aplicación en el Market. No os voy a engañar, a mi lo que me gustan son los juegos. Por esta razón, la aplicación que vamos a desarrollar será el famoso Pong, pasando por todas las fases. Alguna de las fases será menos propia de Android, como la lógica del juego; alguna de las fases será más específica de los juegos que de una aplicación “tradicional”, en este caso gráficos y sonidos. Sin embargo mi meta es, con la excusa de hacer un Pong, la explicación del desarrollo de una aplicación completa tocando muchas de las cosas importantes de Android. Estas entradas supondrán una guía, lo cual significa que los códigos pueden no ser eficientes, que pueden estar programados de una forma más enfocada a la claridad, y que pueden no ser como yo hago mis programas finales. Cosas que vas a aprender: Instalación de las herramientas necesarias en Ubuntu (Linux): Android SDK, Eclipse IDE y el puente entre ellos. Crear proyectos de Android y entender para qué sirve cada fichero creado automáticamente por el IDE. Crear una interfaz de usuario básica, uso de imágenes y despligue de mensajes en pantalla. Crear nuevas Actividades para usar en cada parte de la aplicación. Ejecutar las nuevas Actividades y pasar datos entre ellas. Pintar elementos en pantalla (texto, formas primitivas). Entender y usar el control táctil. Crear hilos que se encarguen de tareas concretas. Usar la vibración del dispositivo. Reproducir sonidos. Usar Fonts propias. Usar el acelerómetro. Impedir el bloqueo de la pantalla. Crear una cuenta de Android Developer. Publicar la aplicación en el Android Market. Crear una actualización de la aplicación y publicarla. Puedes descargar la aplicación del Android Market antes de empezar el curso, para que veas qué Search Creando una aplicación de Android: la presentación Publicado el 21 julio, 2011 por meta Categorías Android Curso introducción Android Programación Seguridad Sistemas Operativos Entradas recientes Colorshapes, el juego de velocidad mental y figuras de colores para Android eyeOS: Trabajando en la nube Integrando Google Analytics en aplicaciones Android Integrando Twitter en aplicaciones Android con SignPost y Twitter4J Entrenando con Metasploitable (IV). Desde postgres a ssh, pasando por openSSL Etiquetas acelerometro activity algoritmo android aplicacion android arbol backtrack bash BD BEeF canvas contraseñas csrf dns dns spoof eclipse expresiones regulares graficos android graphics android htc desire intent java javascript layout menu

Transcript of curso apk.pdf

Home Blog Síguenos Conócenos Contacto

← Trasteando un HTC Desire IV. CambiandoHBOOT e instalando ROM

Creando una aplicación de Android: primerospasos →

0. Creando una aplicación de Android: la presentación1. Creando una aplicación de Android: primeros pasos

2. Creando una aplicación de Android: visión de conjunto y diseño del menú3. Creando una aplicación de Android: el juego y la lógica (parte 1)4. Creando una aplicación de Android: el juego y la lógica (parte 2)

5. Creando una aplicación de Android: mejoras (parte 1)6. Creando una aplicación de Android: mejoras (parte 2)

7. Creando una aplicación de Android: empaquetado y publicación

Hace tiempo adquirimos un par de HTC Desire con la intención de aprender un poco de desarrollode aplicaciones para dispositivos con Android. Buscando por la web se encuentran tutoriales yguías muy buenas y snippets también muy buenos. Pero la mayoría son cosas puntuales,inconexas.

Bien, el objetivo de la siguiente serie de entradas será el de desarrollar una aplicación completapara dispositivos con Android, empezando desde cero y acabando por la publicación de laaplicación en el Market.

No os voy a engañar, a mi lo que me gustan son los juegos. Por esta razón, la aplicación quevamos a desarrollar será el famoso Pong, pasando por todas las fases. Alguna de las fases serámenos propia de Android, como la lógica del juego; alguna de las fases será más específica de losjuegos que de una aplicación “tradicional”, en este caso gráficos y sonidos.

Sin embargo mi meta es, con la excusa de hacer un Pong, la explicación del desarrollo de unaaplicación completa tocando muchas de las cosas importantes de Android. Estas entradassupondrán una guía, lo cual significa que los códigos pueden no ser eficientes, que pueden estarprogramados de una forma más enfocada a la claridad, y que pueden no ser como yo hago misprogramas finales.

Cosas que vas a aprender:

Instalación de las herramientas necesarias en Ubuntu (Linux): Android SDK, Eclipse IDE y elpuente entre ellos.Crear proyectos de Android y entender para qué sirve cada fichero creado automáticamentepor el IDE.Crear una interfaz de usuario básica, uso de imágenes y despligue de mensajes en pantalla.Crear nuevas Actividades para usar en cada parte de la aplicación.Ejecutar las nuevas Actividades y pasar datos entre ellas.Pintar elementos en pantalla (texto, formas primitivas).Entender y usar el control táctil.Crear hilos que se encarguen de tareas concretas.Usar la vibración del dispositivo.Reproducir sonidos.Usar Fonts propias.Usar el acelerómetro.Impedir el bloqueo de la pantalla.Crear una cuenta de Android Developer.Publicar la aplicación en el Android Market.Crear una actualización de la aplicación y publicarla.

Puedes descargar la aplicación del Android Market antes de empezar el curso, para que veas qué

 Search

Creando una aplicación de Android: lapresentación

Publicado el 21 julio, 2011 por meta

Categorías

AndroidCurso introducciónAndroidProgramaciónSeguridadSistemas Operativos

Entradas recientes

Colorshapes, el juego develocidad mental y figurasde colores para AndroideyeOS: Trabajando en lanubeIntegrando GoogleAnalytics en aplicacionesAndroidIntegrando Twitter enaplicaciones Android conSignPost y Twitter4JEntrenando conMetasploitable (IV). Desdepostgres a ssh, pasandopor openSSL

Etiquetas

acelerometro activityalgoritmo androidaplicacion androidarbol backtrack bash BD

BEeF canvas contraseñas csrf

dns dns spoof eclipseexpresiones regularesgraficos androidgraphics android htc

desire intent javajavascript layout menu

Twittear 19 2

← Trasteando un HTC Desire IV. CambiandoHBOOT e instalando ROM

Creando una aplicación de Android: primerospasos →

vas a crear. El resultado será como éste:

¡Espero que sean de ayuda para todos los lectores!

 

EDITADO:

El equipo de Android Market ha decidido a fecha 20-09-2011 retirar dicha aplicación por violaciónde las políticas de contenido, a pesar de que nunca cobramos por dicha aplicación ni obtuvimosganancias por publicidad ni negamos que Atari fuera la depositaria de los derechos de autor.

Por este motivo hemos decidido alojar la aplicación en nuestro propio servidor para que puedaseguir descargándose pulsando aquí (MD5: 039bf32bfaa8c64a6112bc364d456aa0).

Gracias a todos por vuestra comprensión y apoyo.

Esta entrada fue publicada en Android, Curso introducción Android, Programación y etiquetadacomo aplicacion android.

4 Respuestas a Creando una aplicación de Android: lapresentación

1. LuiS! dijo:22 julio, 2011 at 0:07

Hmmm me gusta lo del pong !! Yo tenia uno por algun lado programado en Visual basic y laverdad esque me enganche a programar con el pong hasta el punto de ir de empalmada aclase xD. Tengo un par de ideas para juegos / programas de utilidad para android xD yahablaremos. Kisses!LuiS!

Responder

2. Pingback: Poesía binaria » C.I. XII: La evolución de la web, 20 aniversario de Linux, DateTimepara php, instalar Arch Linux, Creando una aplicación en Android y un pedal con Arduino

3. Pingback: Aprendiendo Android | Blog Interno de Tecnología

4. Diseño de Pagina Web dijo:29 agosto, 2012 at 23:04

Muy buenooo!!!

Responder

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *

Nombre *

Share

metasploitmetasploitable mitmmysql oauth owasp

pentesting php seguridadpor defecto shodan

smartphones SQL SQLi

trasteando twitter twitter4jVirtualBox wireshark xml xss

persistente

Sitios de interés

Android DevelopersAndroid.esBacktrackCommand Line Kung FuDragonJAREl Androide LibreExploits DatabaseFlu ProjectGran AngularHispasecMicrosiervosOpenLibraPentester.esPoesía BinariaSecurity By DefaultUn informático en el ladodel malWorld Wide WebConsistorium

Home Blog Síguenos Conócenos Contacto Escribe aquí para buscar...

← Creando una aplicación de Android: lapresentación

Inyecciones SQL. Qué son y como combatirlas→

0. Creando una aplicación de Android: la presentación1. Creando una aplicación de Android: primeros pasos

2. Creando una aplicación de Android: visión de conjunto y diseño del menú3. Creando una aplicación de Android: el juego y la lógica (parte 1)4. Creando una aplicación de Android: el juego y la lógica (parte 2)

5. Creando una aplicación de Android: mejoras (parte 1)6. Creando una aplicación de Android: mejoras (parte 2)

7. Creando una aplicación de Android: empaquetado y publicación

Bienvenidos a la primera parte de la serie de entradas en el ciclo Creando una aplicación deAndroid. Si aún no lo has hecho, comienza desde la primera entrada mostrada en el menúinmediatamente superior.

En esta entrada vamos a dar los primeros pasos en el desarrollo de nuestra aplicación: instalar lasherramientas necesarias y crear nuestro Hello, world.En este caso vamos a poner a punto el Android SDK sobre Eclipse (nuestro entorno de desarrollo),y todo ello sobre Ubuntu 11.04. Sin embargo, esta entrada no tiene que ver con la instalación deUbuntu, sólo con la del SDK y el IDE.Téngase en cuenta que las versiones de estas tres plataformas son las últimas en el momento dela publicación de esta entrada

He de avisar de que lo que vamos a hacer en esta entrada será descargar muchas cosas, lo cual vaa tardar bastante (sobre todo el Android SDK).

¡Comencemos!

Vamos a dar por hecho que tenemos nuestro Ubuntu 11.04 recién instalado. Lo primero quedebemos hacer será actualizar el sistema (y lógicamente ponerlo a nuestro gusto con losprogramas que queramos). Es en este momento cuando comenzamos la instalación de lasherramientas.

Paso 0: preparación

Ubuntu no trae instalado por defecto el Java SDK, por lo que lo primero que debemos hacer esinstalarlo. Para ello, abrimos una Terminal y escribimos:

sudo apt‐get install sun‐java6‐bin

Introducimos la contraseña del usuario y esperamos a que descargue los ~106MB de los paquetesnecesarios.

Nota: si el Ubuntu sobre el que estáis trabajando es de 64 bits, necesitáis ejecutar el siguientecomando en una terminal:

sudo apt‐get install ia32‐libs

Esto es necesario porque el SDK usa las librerías de 32 bits.

Recomendamos crearnos nuestro directorio de desarrollo, para tenerlo todo organizado. Porejemplo en /home/[user_name]/AndroidDev o /media/[data_disk]/AndroidDev.Una vez completado esto, vamos al siguiente paso.

Paso 1: descargar Eclipse

Hemos elegido Eclipse como IDE solamente porque el Android SDK tiene un plugin para Eclipseque hace la vida muy fácil y que lo integra perfectamente.Lo primero que tenemos que hacer es ir a la página de descargas de Eclipse. Vamos a elegir la

Creando una aplicación de Android: primerospasos

Publicado el 21 julio, 2011 por meta

Categorías

AndroidCurso introducciónAndroidProgramaciónSeguridadSistemas Operativos

Entradas recientes

Automatizando lacreación de entornos dedesarrollo con VagrantColorshapes, el juego develocidad mental y figurasde colores para AndroideyeOS: Trabajando en lanubeIntegrando GoogleAnalytics en aplicacionesAndroidIntegrando Twitter enaplicaciones Android conSignPost y Twitter4J

Etiquetas

acelerometro activityalgoritmo androidaplicacion androidarbol backtrack bash BD

BEeF canvas contraseñas csrf

dns dns spoof eclipseexpresiones regularesgraficos androidgraphics android htc

desire intent javajavascript layout menu

metasploitmetasploitable mitmmysql oauth owasp

pentesting php seguridadpor defecto shodan

primera opción (o al menos la que era primera opción cuando se creó esta entrada), la cual esEclipse IDE for Java EE Developers, 210 MB. La web debería detectar que estamos en un Linux, ysin haber hecho click en el link tendremos a la derecha las opciones Linux 32 bit y Linux 64 bit. Enmi caso, 32 bit. Elegimos el mirror y comenzamos la descarga. Eclipse no se instala, es portable,por lo que el lugar donde lo descomprimimos es el lugar de la instalación. Lo dejamosdescargando en la ubicación que queramos y avanzamos al siguiente paso.

Paso 2: descargar Android SDK

Nos dirigimos a la página de descargas del Android SDK en Android Developers. Aquí elegiremos,en nuestro caso, Linux (i386). Lo descargamos a nuestro disco en la ubicación que queramos y lodescomprimimos. Abrimos una terminal, y ejecutamos:

[path_development]/android‐sdk‐linux_x86/tools/android

Donde [path_development] será la ubicación donde hayamos descomprimido el SDK (en el cualtendremos el directorio android-sdk-linux_x86). Este comando nos mostrará el Android SDK andAVD Manager, como en la siguiente imagen:

Lo siguiente que vamos a hacer es instalar las API del SDK que vamos a querer. En nuestro casovan a ser todas, por si quisiéramos desarrollar para una versión más o menos antigua. Para ello nosvamos a Available Packages, y seleccionamos los dos grupos por completo.

Después de esto hacemos click en Install Selected, en la parte inferior derecha.Nos pedirá que aceptemos las licencias de las API del SDK y veremos la siguiente pantalla:

Elegimos Accept All en la parte derecha y hacemos click en Install.Tardará lo suyo en descargar todo, así que tranquilamente podemos navegar porvidasConcurrentes durante un rato.

Eventualmente Eclipse se habrá descargado, así que podemos ir descomprimiéndolo en laubicación que hayamos elegido.

Una vez se hayan instalado las API volveremos a nuestra ventana del Android SDK and AVDManager, donde podemos pinchar en Installed Packages y comprobar que hemos instalado todocorrectamente:

Durante estos pasos deberás reiniciar el adb al menos una vez, aunque sólo hay que dar a “Sí,reiniciarlo” cuando nos lo pida.

smartphones SQL SQLi

trasteando twitter twitter4jVirtualBox wireshark xml xss

persistente

Sitios de interés

Android DevelopersAndroid.esBacktrackCommand Line Kung FuDragonJAREl Androide LibreExploits DatabaseFlu ProjectGran AngularHispasecMicrosiervosOpenLibraPentester.esPoesía BinariaSecurity By DefaultUn informático en el ladodel malWorld Wide WebConsistorium

¡Enhorabuena, has instalado el Android SDK!

Paso 3: configurar Eclipse con el Android SDK

Llegados a este punto, si hemos seguido todos los pasos, tendremos un directorio con lo siguiente:

Directorio con Eclipse (llamado eclipse).Directorio con el Android SDK (llamado android-sdk-linux_x86).Fichero comprimido con Eclipse.Fichero comprimido con el Android SDK.

Podemos borrar ya los comprimidos. Ahora vamos a configurar Eclipse para funcionar con elAndroid SDK. Para ello lo primero que tenemos que hacer es navegar hasta el directorio dondedescomprimimos Eclipse y ejecutar el fichero eclipse. Para mayor comodidad podemos añadireste path a los paths del sistema, pero eso ya es cosa de cada uno.

Ejecutamos Eclipse y nos pedirá la ruta del Workspace. Este workspace (espacio de trabajo) va aser el directorio donde se guarden todos nuestros proyectos. Podemos tener varios workspaces, opodemos tener uno solo y usar siempre el mismo. En mi caso voy a usar esta instalación deEclipse sólo para Android, por lo que voy a crear mi workspace en[path_development]/workspace, y voy a pulsar en la opción de usar esta ruta y no volver apreguntarme.

Cerramos la pestañita del inicio que nos ha salido la primera vez que hemos ejecutado Eclipse, ynos encontramos el IDE listo para ser configurado.Lo que vamos a hacer ahora es instalar el plugin de Eclipse para trabajar con el Android SDK. Paraello vamos a Help > Install new software. En la parte superior nos encontramos con un campo detexto y el botón Add a la derecha. Pulsamos sobre él para obtener lo siguiente:

Escribimos lo siguiente:

Name: Android Plugin (en realidad, el nombre que queramos darle).Location: https://dl-ssl.google.com/android/eclipse

Y pulsamos en OK. En la siguiente pantalla debemos elegir todo y pulsar en Next:

Aceptamos la licencia e instalamos. Tendremos que reiniciar Eclipse para completar dichainstalación.

El último paso de la configuración es decirle a Eclipse dónde está el Android SDK. Para ello vamosa Window > Preferences > Android, y donde pone SDK Location escribimos la ruta absoluta. Existeun bug en el momento de la creación de esta entrada, por el cual no podemos pulsar en Proceeden el pop-up que veremos hasta que no escribamos la ruta y demos a Enter. Recomiendo escribirla ruta en lugar de buscarlo con el botón Browse, para evitar quedarnos bloqueados.

Ahora sí, hemos acabado de configurar las herramientas. ¡Ahora es momento de comprobar quefunciona!

Paso 4: crear el Hello, world

Llegado este punto tendremos todas las herramientas necesarias para desarrollar aplicacionespara Android. Sin embargo lo que no tenemos es el dónde. Disponemos de dos alternativas, asaber: un dispositivo físico (preferentemente) o un dispositivo virtual.

Dispositivo físico: tenemos que conectar el dispositivo por USB y habilitar la DepuraciónUSB. Para esto, y dependiendo de la versión de Android que tengamos (o en mi caso laROM instalada), tenemos que ir a Ajustes > Aplicaciones > Desarrollo y activar DepuraciónUSB. Con esto, al ejecutar nuestro Hello, world se instalará y ejecutará en el dispositivo físicodirectamente.Nota: podemos asegurarnos de que nuestro dispositivo está reconocido cuando, después deconectar ejecutamos:

[path_development]/android‐sdk‐linux_x86/platform‐tools/adb devices

Si hemos visto algún dispositivo, es que está reconocido perfectamente. Siempre podemosreiniciar el servicio con los siguientes dos comandos:

cd [path_development]

android‐sdk‐linux_x86/platform‐tools/adb kill‐serverandroid‐sdk‐linux_x86/platform‐tools/adb start‐server

Dispositivo virtual: si no disponemos de un dispositivo físico podemos usar el emulador quenos ofrece el Android SDK. Si bien es una opción muy buena, no dispone de aceleraciónhardware ni soporte para muchas de las funcionalidades, así que un dispositivo físico essiempre la mejor opción.Para poder crear un dispositivo virtual vamos a Window > Android SDK and AVD Manager ypulsamos en New. Damos un nombre a nuestro dispositivo virtual, por ejemploVirtualAndroid7. ¿Y por qué 7? Pues porque en Target vamos a elegir Android 2.1-update1 –API Level 7. Finalmente pulsamos en Create AVD.

Como paso final, nos queda crear un nuevo proyecto que sea nuestro Hello, world. Para ellovamos a File > New > Project… y buscamos Android > Android Project.

Damos nombre a nuestro proyecto, por ejemplo Hello world. Elegimos la API de nivel 7 para laque hemos configurado el emulador (Android 2.1 es razonablemente viejo por ahora para obtenerbuena compatibilidad en las aplicaciones).Application Name lo dejamos como está. Package Name DEBE ser un nombre de paquete único,pues no podemos tener dos paquetes del mismo nombre en el mismo dispositivo. Lo más normales poner nuestro namespace en el formato típico en estos casos, por ejemplo para mí:com.vidasconcurrentes.helloworld.

Sin mirar ni siquiera al código, hacemos click derecho en el proyecto y elegimos Run As… >Android Application.

Si todo ha ido bien, la aplicación ejecutará. Si tenemos el dispositivo virtual creado, pero no hayningún dispositivo físico conectado, esperamos a que cargue el emulador (puede tardar bastante)y la aplicación estará ejecutando:

Si por el contrario hemos conectado nuestro dispositivo físico, tendremos algo parecido a losiguiente:

Hasta aquí la primera entrada del ciclo de entradas llamado Creando una aplicación de Android.En sucesivas entradas veremos cómo continuar, creando nuestra aplicación y dando los primerospasos en las decisiones de diseño.

¡Hasta pronto!

Más información:

Android Developers

0. Creando una aplicación de Android: la presentación1. Creando una aplicación de Android: primeros pasos

2. Creando una aplicación de Android: visión de conjunto y diseño del menú3. Creando una aplicación de Android: el juego y la lógica (parte 1)4. Creando una aplicación de Android: el juego y la lógica (parte 2)

5. Creando una aplicación de Android: mejoras (parte 1)6. Creando una aplicación de Android: mejoras (parte 2)

7. Creando una aplicación de Android: empaquetado y publicación

Home Blog Síguenos Conócenos Contacto Escribe aquí para buscar...

← Inyecciones SQL. Qué son y comocombatirlas

Cross Site Scripting (XSS) →

0. Creando una aplicación de Android: la presentación1. Creando una aplicación de Android: primeros pasos

2. Creando una aplicación de Android: visión de conjunto y diseño del menú3. Creando una aplicación de Android: el juego y la lógica (parte 1)4. Creando una aplicación de Android: el juego y la lógica (parte 2)

5. Creando una aplicación de Android: mejoras (parte 1)6. Creando una aplicación de Android: mejoras (parte 2)

7. Creando una aplicación de Android: empaquetado y publicación

Bienvenidos a la segunda parte de la serie de entradas en el ciclo Creando una aplicación deAndroid. Si aún no lo has hecho, comienza desde la primera entrada mostrada en el menúinmediatamente superior.

Como vimos en la primera parte de este ciclo de entradas, tenemos instalado y configuradonuestro entorno de desarrollo Eclipse para trabajar con el Android SDK. En esta entrada vamos acentrarnos en nuestro proyecto. Vamos a crearlo, vamos a comentar para qué sirve cada uno delos ficheros que nos crea Eclipse al hacer el proyecto, vamos a explicar brevemente las partes delas que va a consistir nuestra aplicación y vamos a crear el menú principal del juego.

El primer paso de esta entrada va a ser abrir nuestro Eclipse para poder comenzar a trabajar (duh).Una vez haya cargado y hayamos elegido nuestro workspace, entraremos a Eclipse. Ahora vamosa crear nuestro proyecto. Para ello vamos a File > New > Android Project (o si es nuestra primeravez, File > New > Project… y elegimos Android > Android Project en la ventana emergente).

En la ventana de creación de proyecto que aparecerá vamos a escribir y elegir lo siguiente:

Project Name: Pong-vCBuild Target: Android 2.1-update1 (API level 7)Application Name: Pong-vCPackage Name: com.vidasconcurrentes.pongvcCreate Activity: PongvCActivityMin SDK Version: 7

El resto de cosas que no he dicho las dejamos por defecto. Pero… ¿por qué hemos elegido estasopciones?

El Build Target es la versión de Android mínima en la que vamos a querer que se ejecute nuestraaplicación. Esto significa que el SDK nos ofrecerá las funciones que estén disponibles para esaversión, y si elegimos una muy baja no tendremos ciertas funcionalidades. Por contra, si elegimosuna muy nueva, puede ser que los dispositivos más antiguos no puedan ejecutar nuestraaplicación. En este compromiso vamos a elegir Android 2.1 porque nuestra aplicación no va anecesitar las funcionalidades del Android 2.3 y la 2.1 es una versión que es relativamente joven yextendida.

El Application Name va a ser el texto que aparezca en nuestro dispositivo debajo del icono cuandoqueramos ejecutarlo.

El Package Name es el nombre del paquete de esta aplicación. Es importante recordar que en elmismo dispositivo sólo puede haber instalada una aplicación con el mismo package name, por loque necesitamos que sea único. Se recomienda que se usen las convenciones de nombrado depaquetes de software, por las cuales debemos usar minúsculas y usaremos el dominio de lacompañía empezando desde la derecha, y al final el nombre de nuestra aplicación.

El campo Create Activity sirve para crear la actividad por defecto. Tiene restricciones a la hora deponer símbolos en el nombre, así que elegiremos nuestra actividad de dicha forma.

El campo Min SDK Version contiene la versión del SDK que aparezca en el Build Target quehayamos elegido. Normalmente se pone por defecto, pero debemos ponerla en caso contrario.

Ahora tenemos nuestro proyecto creado, con todos los ficheros por defecto. Veremos algo así:

Por lo que podemos ver, tenemos varios directorios, dos ficheros .java y tres ficheros .xml.Veamos para qué sirve cada uno:

PongvCActivity.java: este es el fichero de la actividad por defecto que nos ha creado Eclipse.Vamos a entender esto como el mainde una aplicación Java tradicional, el punto de entradaal ejecutar la aplicación. Su código es:

package com.vidasconcurrentes.pongvc;

import android.app.Activity;import android.os.Bundle;

public class PongvCActivity extends Activity {    /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);    }}

Esta clase hereda de Activity y redefine la función onCreate(). Esta función toma un Bundle,

Creando una aplicación de Android: visión deconjunto y diseño del menú

Publicado el 27 julio, 2011 por meta

Categorías

AndroidCurso introducciónAndroidProgramaciónSeguridadSistemas Operativos

Entradas recientes

Automatizando lacreación de entornos dedesarrollo con VagrantColorshapes, el juego develocidad mental y figurasde colores para AndroideyeOS: Trabajando en lanubeIntegrando GoogleAnalytics en aplicacionesAndroidIntegrando Twitter enaplicaciones Android conSignPost y Twitter4J

Etiquetas

acelerometro activityalgoritmo androidaplicacion androidarbol backtrack bash BD

BEeF canvas contraseñas csrf

dns dns spoof eclipseexpresiones regularesgraficos androidgraphics android htc

desire intent javajavascript layout menu

metasploitmetasploitable mitmmysql oauth owasp

pentesting php seguridadpor defecto shodan

smartphones SQL SQLi

trasteando twitter twitter4jVirtualBox wireshark xml xss

persistente

Sitios de interés

Android DevelopersAndroid.esBacktrackCommand Line Kung FuDragonJAREl Androide LibreExploits DatabaseFlu ProjectGran AngularHispasecMicrosiervosOpenLibraPentester.esPoesía BinariaSecurity By DefaultUn informático en el ladodel malWorld Wide WebConsistorium

que es la forma que tiene Android de pasar elementos primitivos entre actividades. Por asídecirlo (y muy cogido con pinzas) es como pasarle a la actividad el estado del sistema. Luegousa la función setContentView(), que dice qué debe mostrarse en la pantalla. Ahora veremosqué es R.layout.main.

R.java: este es un fichero generado automáticamente por el propio Eclipse y que nodeberíamos tocar bajo ningún concepto. Contiene información sobre los recursos quepueden usarse (bajo el directorio res), de modo que podamos acceder a ello como unaconstante escribiendo R.<directorio>.<recurso>.main.xml: en este fichero se define la Interfaz de Usuario (UIen adelante). El plugin deAndroid para Eclipse nos permite ver este fichero como texto o como un editor gráfico, locual simplifica mucho las cosas. Inicialmente contiene el siguiente código:

<?xml version="1.0" encoding="utf‐8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    ><TextView    android:layout_width="fill_parent"    android:layout_height="wrap_content"    android:text="@string/hello"    /></LinearLayout>

Aquí vemos por primera vez LinearLayout. Define la forma de la que se van a distribuir loselementos que vayan dentro de ella. En este caso, define que los elementos debencolocarse uno detrás de otro. Existe una explicación en detalle de todas las vistas y layoutsdisponibles en Android Developers. Vemos que hay también un TextView, que es un widgetque permite mostrar un texto. Este texto puede ser hardcoded (es decir, escrito a mano ahí)o que venga del fichero strings.xml. Se recomienda usar la opción de strings.xml siempreque podamos, entre otras cosas porque nos ayudará a las traducciones de nuestros textos (siqueremos aceptar varios idiomas).

strings.xml: este fichero define cadenas de texto. Es muy útil en situaciones de querercambiar un texto que aparece en muchos sitios, que en lugar de tener que buscarlo en todaspartes y cambiarlo, sólo lo cambiamos aquí y ya aparece en todos.AndroidManifest.xml: toda aplicación debe tener este fichero en su directorio raiz, y entreotras cosas define el nombre del paquete de la aplicación, los componentes (actividades ysus configuraciones, servicios…), los permisos que necesita la aplicación, el nivel de la APImínimo que necesita, las librerías que el proyecto necesita… Se puede editar (y de hechotendremos que editarlo antes o después), y cuenta con una vista gráfica muy buena paraesta edición.

Hemos visto que en el directorio res encontramos todos los recursos (gráficos también) que va ausar el proyecto. layouts guarda las distribuciones, values guarda los strings, drawable guarda lasimagenes…

Hasta aquí la explicación de los componentes de nuestro proyecto creado por defecto.

Ahora sí, vamos a empezar nuestro proyecto. Como hemos dicho, vamos a crear un Pong. Seráuna aplicación sencilla, muy sencilla. La aplicación ejecutará y mostrará un menú desde el cualpodremos seleccionar tres opciones: Jugar, Opciones y Salir. Jugar ejecutará el juego, Opciones nosllevará a elegir la configuración del juego, y Salir cerrará la aplicación. En esta entrada vamos acrear este primer menú.

Si ejecutamos el proyecto ahora (click derecho en el proyecto, Run as > Android Application),veremos lo siguiente:

Como vemos, nos muestra la barra de notificaciones, el nombre de la aplicación y lo que contieneR.layout.main. Sin embargo nosotros no queremos que aparezca nada más que nuestroR.layout.main. Para hacer esto, vamos a añadir las siguientes líneas de código en PongvCActivity:

requestWindowFeature(Window.FEATURE_NO_TITLE);getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,                    WindowManager.LayoutParams.FLAG_FULLSCREEN);

Con esto estamos pidiendo al sistema de ventanas de Android que nos quite el nombre de laaplicación y que además oculte la barra de notificaciones. Veremos lo siguiente:

Existe otra manera de hacer esto, y es modificando el AndroidManifest.xml. Sin embargo vamos ahacerlo de forma programática aquí (con código) y haremos otra cosa de forma estructural (con losxml) al final de la entrada. Ahora vamos a crear nuestro menú. Esta aplicación va a ser muy simple,por lo que no vamos a fijarnos en que sea artístico, sino funcional. Para comenzar, vamos a crearun nuevo directorio en res/ y vamos a llamarlo drawable. Dentro vamos a guardar estas tresimágenes:

En mi caso, van a llamarse pong.png, button_bg.png y vc.png, respectivamente. Una vezguardado, el fichero R.java se recreará y podremos acceder a estos recursos. Además, queremosque nuestro menú tenga tres botones. Recordemos que hemos dicho que es importante usar elfichero strings.xml todo lo posible. Por tanto, vamos a modificarlo para que sea de esta forma:

<?xml version="1.0" encoding="utf‐8"?><resources>    <string name="hello">Hello World, PongvCActivity!</string>    <string name="app_name">Pong‐vC</string>    <string name="menu_play">Jugar</string>    <string name="menu_options">Opciones</string>    <string name="menu_exit">Salir</string></resources>

Ahora vamos a modificar main.xml. El código es el siguiente:

<?xml version="1.0" encoding="utf‐8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:weightSum="1">    <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/pong" android:layout_gravity="center" android:layout_marginBottom="50dip" android:id="@+id/pong_logo" android:layout_marginTop="40dip"></ImageView>    <TextView android:layout_height="wrap_content" android:text="@string/menu_play" android:textAppearance="?android:attr/textAppearanceLarge" android:layout_width="wrap_content" android:background="@drawable/button_bg" android:layout_gravity="center" android:gravity="center_vertical|center_horizontal" android:layout_marginBottom="30dip" android:id="@+id/play_button"></TextView>    <TextView android:layout_height="wrap_content" android:text="@string/menu_options" android:textAppearance="?android:attr/textAppearanceLarge" android:layout_width="wrap_content" android:background="@drawable/button_bg" android:layout_gravity="center" android:gravity="center_vertical|center_horizontal" android:layout_marginBottom="30dip" android:id="@+id/options_button"></TextView>    <TextView android:layout_height="wrap_content" android:text="@string/menu_exit" android:textAppearance="?android:attr/textAppearanceLarge" android:layout_width="wrap_content" android:background="@drawable/button_bg" android:layout_gravity="center" android:gravity="center_vertical|center_horizontal" android:id="@+id/exit_button">    <ImageView android:id="@+id/imageView1" android:layout_width="314dp" android:layout_height="wrap_content" android:src="@drawable/vc" android:layout_gravity="center|bottom"></ImageView></LinearLayout>

Si hemos hecho todo como he explicado, no habrá errores. Es tan largo porque está aplicado yaun poco de maquetado para que quede colocado. Podemos ejecutar nuestra aplicación ahora yveremos lo siguiente:

Ahora solamente tenemos que darle funcionalidad a los elementos que hemos colocado. Esto lohacemos en el fichero PongvCActivity.java. Primero vamos a añadir funcionalidad al botón deJugar. Para ello, al final del código que tenemos, escribimos:

TextView play = (TextView)findViewById(R.id.play_button);play.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) {  Toast.makeText(getApplicationContext(), R.string.menu_play,                               Toast.LENGTH_SHORT).show(); }});

En este código obtenemos el TextView cuyo identificador es play_button y le ponemos unOnClickListener que detectará que hemos tocado con el dedo encima (evento de la acción click).Además vamos a crear anónimamente este OnClickListener de modo que redefinimos sucomportamiento para la función onClick(). Ésta lo que hace es mostrar un mensaje en pantalla conel texto del botón pulsado. Así hemos visto cómo referirnos a un string desde los XML y desde elcódigo Java.

El código para los demás botones será el mismo, sólo cambiando el texto mostrado en el Toast.Aquí está el código completo para el fichero PongvCActivity.java:

package com.vidasconcurrentes.pongvc;

import android.app.Activity;import android.content.Intent;import android.net.Uri;import android.os.Bundle;import android.view.View;import android.view.Window;import android.view.WindowManager;import android.view.View.OnClickListener;import android.widget.ImageView;import android.widget.TextView;import android.widget.Toast;

public class PongvCActivity extends Activity {  /** Called when the activity is first created. */  @Override  public void onCreate(Bundle savedInstanceState) {      super.onCreate(savedInstanceState);      requestWindowFeature(Window.FEATURE_NO_TITLE);      getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,                          WindowManager.LayoutParams.FLAG_FULLSCREEN);      setContentView(R.layout.main);

  TextView play = (TextView)findViewById(R.id.play_button);  play.setOnClickListener(new OnClickListener() {   @Override   public void onClick(View v) {    Toast.makeText(getApplicationContext(),             R.string.menu_play, Toast.LENGTH_SHORT).show();   }  });

  TextView options = (TextView)findViewById(R.id.options_button);  options.setOnClickListener(new OnClickListener() {   @Override   public void onClick(View v) {    Toast.makeText(getApplicationContext(),             R.string.menu_options, Toast.LENGTH_SHORT).show();   }  });

  TextView exit = (TextView)findViewById(R.id.exit_button);  exit.setOnClickListener(new OnClickListener() {   @Override   public void onClick(View v) {    Toast.makeText(getApplicationContext(),             R.string.menu_exit, Toast.LENGTH_SHORT).show();   }  });

  ImageView logo = (ImageView)findViewById(R.id.imageView1);  logo.setOnClickListener(new OnClickListener() {   @Override   public void onClick(View v) {    Intent viewIntent = new Intent("android.intent.action.VIEW",             Uri.parse("http://www.vidasconcurrentes.com"));    startActivity(viewIntent);   }  });    }}

Vamos a hacer un acto de fe en la última parte del código y vamos a quedarnos con que el códigodel ultimo bloque hace que se abra el navegador web del dispositivo y lleve a este blog. En lasiguiente entrada explicaremos esto en detalle, pero para no hacer más larga esta entrada vamos atomarlo así.

Ahora podemos ejecutar la aplicación y por ejemplo tocar en Opciones, y veremos lo siguiente:

Twittear 2 1 Follow

← Inyecciones SQL. Qué son y comocombatirlas

Cross Site Scripting (XSS) →

Sólo nos queda un último truco, y es irnos al AndroidManifest.xml y poner android:screenOrientation=”portrait” en <activity android:name=”.PongvCActivity”android:label=”@string/app_name”>. De esta manera obligamos a que no se cambie deorientación al mover el dispositivo, o si no encontraríamos problemas como este al girarlo:

Hasta aquí la entrada de esta semana. En ella hemos visto cómo crear el proyecto de nuestraaplicación, de qué partes se compone este proyecto, para qué sirve cada una de estas partes,hemos diseñado nuestro menú principal del juego y le hemos dado funcionalidad.

Puedes descargar el proyecto completo en un fichero comprimido, listo para importar en tuEclipse, pulsando aquí (MD5: 354b8fb840d9aeb6e91cb2ef35f3203f).

En la siguiente entrada crearemos el juego en sí, todas las clases necesarias para representar unPong y la lógica de movimientos, además de mostrar todo esto en pantalla al dar al botón Jugardel menú.

¡Un saludo a todos los lectores!

0. Creando una aplicación de Android: la presentación1. Creando una aplicación de Android: primeros pasos

2. Creando una aplicación de Android: visión de conjunto y diseño del menú3. Creando una aplicación de Android: el juego y la lógica (parte 1)4. Creando una aplicación de Android: el juego y la lógica (parte 2)

5. Creando una aplicación de Android: mejoras (parte 1)6. Creando una aplicación de Android: mejoras (parte 2)

7. Creando una aplicación de Android: empaquetado y publicación

Esta entrada fue publicada en Android, Curso introducción Android, Programación y etiquetadacomo activity, aplicacion android, eclipse, java, layout, menu.

5 Respuestas a Creando una aplicación de Android: visión deconjunto y diseño del menú

1. Gonzalo dijo:9 febrero, 2014 at 14:48

Hola, en primer lugar gracias por tu aporte.Quería comentarte que tengo algún problema a la hora de seguir los pasos.En primer lugar el codigo que se me genera en “PongvCActivity.java” no es igual al quemuestras (esto puede ser por que estoy usando Ubuntu 13.10.En segundo luegar a la hora de añadir el codigo:

requestWindowFeature(Window.FEATURE_NO_TITLE);getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);

me da error donde quiera que lo ponga.

¿Alguna sugerencia?

muchas gracias por todo

2. Josue dijo:5 septiembre, 2011 at 0:30

Fijate q yo quiero hacer q el pong funcione en 2 celulares por medjio de un servidor. Mepregunto si me podrias explicar como hacerlo. Solo la explicacion sin la necesidad de ponerel codigo

meta dijo:5 septiembre, 2011 at 0:43

Así como primera idea, en frío… se me ocurre únicamente lo siguiente:

Podrías hacer que el servidor manejase, entre otras cosas, la coordenada en la que seencuentra cada raqueta y la bola en cada momento. Continuamente (quizá en unnúmero fijo de veces por segundo), cada dispositivo se comunicaría con el servidormandando paquetes de información (dependiendo de si es por Internet, Bluetooth…será de forma distinta), y el servidor estaría enviando a cada uno de los dispositivosinformación sobre la posición de ambas raquetas y de la bola.Cada dispositivo recibiría dicha información y la usaría para actualizar su interfaz(incluso podría detectar errores en la precisión del servidor o de sí mismo, al incluirredundancia en los datos contínuamente).

Cuando se marca un punto, el servidor sería notificado (él sabría qué tiene que hacer,puesto que sabe la posición de la bola siempre) y enviaría también la información a losdispositivos (o no, porque ellos también pueden llevar la cuenta de sus puntos enlocal. Lo importante es que el volumen de información que se transfiera sea el mínimoposible, para poder hacerlo rápido.

Es sólo una idea, no tienes por qué seguirla ^^

Share7Like

Home Blog Síguenos Conócenos Contacto Escribe aquí para buscar...

← Cross Site Scripting (XSS) Creando una aplicación de Android: el juego y lalógica (parte 2) →

0. Creando una aplicación de Android: la presentación1. Creando una aplicación de Android: primeros pasos

2. Creando una aplicación de Android: visión de conjunto y diseño del menú3. Creando una aplicación de Android: el juego y la lógica (parte 1)4. Creando una aplicación de Android: el juego y la lógica (parte 2)

5. Creando una aplicación de Android: mejoras (parte 1)6. Creando una aplicación de Android: mejoras (parte 2)

7. Creando una aplicación de Android: empaquetado y publicación

Bienvenidos a la tercera parte de la serie de entradas en el ciclo Creando una aplicación deAndroid. Si aún no lo has hecho, comienza desde la primera entrada mostrada en el menúinmediatamente superior.

Partiremos del resultado de la entrada anterior en la cual teníamos el menú creado como en lasiguiente imagen:

En esta entrada vamos a crear el juego, incluyendo todas las clases necesarias para que funcione yen la siguiente entrada crearemos la lógica de movimientos.

¡Comencemos!

Importante: esta entrada va a basarse en los códigos creados en las anteriores entradas del ciclo alque pertenece. Tienes disponible pinchando aquí (MD5: 354b8fb840d9aeb6e91cb2ef35f3203f)el proyecto de Eclipse con todo lo hecho hasta ahora, el cual puedes importar a tu Eclipse ycomenzar a trabajar.

Lo primero que vamos a hacer es crear una nueva Activity que será el juego, y que se ejecutará enel momento en que pinchemos en el botón Jugar del menú mostrado arriba.

Vamos a comenzar añadiendo una nueva clase a nuestro proyecto, que será nuestra nuevaactividad. Sin embargo esta es la primera vez que vamos a crear una actividad sin que sea elpropio asistente de Eclipse el que cree el código por defecto, y es interesante darse cuenta de queno se sobrescribe la función onCreate() automáticamente.

Hacemos click derecho sobre el paquete com.vidasconcurrentes.pongvc y seleccionamos New >Class. En la ventana emergente que aparece vamos a donde pone Superclass y a la derechapulsamos en Browse. Escribimos android.app.Activity y aceptamos. Escribimos el nombre paranuestra clase, por ejemplo PongJuego, y creamos la clase. Ahora pinchamos en Source >Override/Implement methods, y buscamos onCreate(Bundle). Ahora nuestra clase debería serparecida a esta:

Creando una aplicación de Android: el juego y lalógica (parte 1)

Publicado el 5 agosto, 2011 por meta

Categorías

AndroidCurso introducciónAndroidProgramaciónSeguridadSistemas Operativos

Entradas recientes

Automatizando lacreación de entornos dedesarrollo con VagrantColorshapes, el juego develocidad mental y figurasde colores para AndroideyeOS: Trabajando en lanubeIntegrando GoogleAnalytics en aplicacionesAndroidIntegrando Twitter enaplicaciones Android conSignPost y Twitter4J

Etiquetas

acelerometro activityalgoritmo androidaplicacion androidarbol backtrack bash BD

BEeF canvas contraseñas csrf

dns dns spoof eclipseexpresiones regularesgraficos androidgraphics android htc

desire intent javajavascript layout menu

metasploitmetasploitable mitmmysql oauth owasp

pentesting php seguridadpor defecto shodan

package com.vidasconcurrentes.pongvc;

import android.app.Activity;import android.os.Bundle;

public class Test extends Activity {

 @Override protected void onCreate(Bundle savedInstanceState) {  // TODO Auto‐generated method stub  super.onCreate(savedInstanceState); }

}

Como vemos, no tiene un View que pintar, así que lo que vamos a hacer ahora es crearlo. Parahacerlo, vamos a seguir el siguiente tutorial que hice hace unas semanas. Pincha en el enlace, siguelos pasos y tendrás algo como esto:

PongJuego.java:

package com.vidasconcurrentes.pongvc;

import com.vidasconcurrentes.pongvc.pintado.PongGameView;

import android.app.Activity;import android.os.Bundle;import android.view.Window;import android.view.WindowManager;

public class PongJuego extends Activity {

 @Override protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  requestWindowFeature(Window.FEATURE_NO_TITLE);  getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,                     WindowManager.LayoutParams.FLAG_FULLSCREEN);  setContentView(new PongGameView(this)); }}

PongGameView.java:

package com.vidasconcurrentes.pongvc.pintado;

import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.view.SurfaceHolder;import android.view.SurfaceView;

public class PongGameView extends SurfaceView                          implements SurfaceHolder.Callback {

 private PongGameThread paintThread;

 public PongGameView(Context context) {  super(context);  getHolder().addCallback(this); } @Override public void surfaceChanged(SurfaceHolder holder, int format,                    int width, int height) { }

 @Override public void surfaceCreated(SurfaceHolder holder) {  paintThread = new PongGameThread(getHolder(), this);  paintThread.setRunning(true);  paintThread.start(); }

 @Override public void surfaceDestroyed(SurfaceHolder arg0) {  boolean retry = true;  paintThread.setRunning(false);  while (retry) {   try {    paintThread.join();    retry = false;   } catch (InterruptedException e) { }  } }

 @Override public void onDraw(Canvas canvas) {  canvas.drawColor(Color.WHITE); }}

PongGameThread.java:

package com.vidasconcurrentes.pongvc.pintado;

import android.graphics.Canvas;import android.view.SurfaceHolder;

public class PongGameThread extends Thread {

 private SurfaceHolder sh; private PongGameView view; private boolean run;

smartphones SQL SQLi

trasteando twitter twitter4jVirtualBox wireshark xml xss

persistente

Sitios de interés

Android DevelopersAndroid.esBacktrackCommand Line Kung FuDragonJAREl Androide LibreExploits DatabaseFlu ProjectGran AngularHispasecMicrosiervosOpenLibraPentester.esPoesía BinariaSecurity By DefaultUn informático en el ladodel malWorld Wide WebConsistorium

 public PongGameThread(SurfaceHolder sh, PongGameView view) {  this.sh = sh;  this.view = view;  run = false; }

 public void setRunning(boolean run) {  this.run = run; }

 public void run() {  Canvas canvas;  while(run) {   canvas = null;   try {    canvas = sh.lockCanvas(null);    synchronized(sh) {     view.onDraw(canvas);    }   } finally {    if(canvas != null)     sh.unlockCanvasAndPost(canvas);   }  } }}

Nota: es importante darse cuenta de que estas dos clases están dentro de un nuevo paquetellamado com.vidasconcurrentes.pongvc.pintado. Es interesante mantener los códigos de nuestrosproyectos ordenados, y los paquetes nos ayudan a agrupar aquellas clases que sirven para elmismo fin.

Ya tenemos todo lo necesario para pintar nuestra nueva Activity. Ahora sólo nos falta ejecutarla.Para ello vamos a usar un Intent. El Intent es una abstracción para definir operaciones asíncronascomo ejecutar nuevas actividades y pasar información entre éstas, entre otras.

Una Activity creada de esta forma puede considerarse una sub-actividad si está previsto quedevuelva algún dato a la actividad que la creó. Contamos con dos funciones para crear actividades:

startActivity(): esta función crea una nueva Activity que no devolverá información al acabar.Una actividad creada de esta forma se considera una actividad aparte.startActivityForResult(): esta función crea una sub-actividad que devolverá ciertos valores alfinalizar. Cuando lo haga, la actividad que la creó entrara en su función onActivityResult(),para procesar los datos necesarios.

Después de esta breve teoría, vamos a lo que nosotros necesitamos. Hemos de recordar que lasactividades forman una pila, de modo que si ejecutamos el juego desde el menú y luegoacabamos esa actividad (por ejemplo con la tecla apropiada en nuestro terminal), vamos a volveral menú. Por ahora no vamos a necesitar guardar el progreso del juego, por lo que no vamos adevolverle al menú información alguna. Ejecutemos entonces nuestra nueva Activity. Recordemosque nuestro menú tenía una parte del código así:

[...]TextView play = (TextView)findViewById(R.id.play_button);play.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) {  Toast.makeText(getApplicationContext(), R.string.menu_play,                Toast.LENGTH_SHORT).show(); }});[...]

Pues ahora la modificamos para que sea así:

[...]TextView play = (TextView)findViewById(R.id.play_button);play.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) {  Toast.makeText(getApplicationContext(), R.string.menu_play,                Toast.LENGTH_SHORT).show();  empiezaJuego(); }});[...]

Donde la función empiezaJuego() es:

private void empiezaJuego() { Intent juego = new Intent(this, PongJuego.class); this.startActivity(juego);}

El constructor de Intent recibe qué clase crea la Activity y de qué clase es esta Activity nueva. Sólonos resta añadir código a la función onCreate() de nuestra nueva Activity. Escribimos lo siguienteen ella:

@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,                      WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(new PongGameView(this));}

Aún nos falta una cosa, y es añadir nuestra nueva actividad al AndroidManifest.xml. Si no loañadimos no podremos ejecutar la actividad. Añadimos lo siguiente antes de </application>.

<activity android:name=".PongJuego" android:label="@string/app_name" android:screenOrientation="landscape"></activity>

Ahora sí, podemos ejecutar nuestro proyecto. Click derecho sobre el proyecto, Run as > AndroidApplication. Si todo está bien hecho, veremos el menú, y al pulsar sobre Jugar nos abrirá unanueva ventana con el fondo blanco. ¡Ya hemos creado nuestra actividad para pintar el juego!

Lo siguiente que vamos a hacer son los elementos que van a hacer falta en el juego. Haciendo unpequeño análisis previo (con poca vista al futuro), vamos a necesitar una bola y dos raquetas.Tanto las raquetas como la pelota tienen que moverse por la pantalla (y sin salirse), pero nonecesitan más funcionalidad.

Es ahora el momento en el que diseñamos nuestro juego. Debemos recordar que los ordenadores(y en este caso nuestros dispositivos) son estúpidos, no saben nada. Un computador no sabe quées una Raqueta, no sabe qué es una Bola, no sabe qué es una pantalla ni siquiera sabe qué es unaactividad. Sin embargo sí que sabe qué es un número, qué es un carácter y qué es un booleano(sabe qué es cada tipo de dato primitivo).Así que podemos pensar que una Raqueta es un rectángulo. ¿Qué es un rectángulo? Unrectángulo no es más que un punto origen, un ancho y un alto. ¿Y qué es un punto? Un punto va aser un par de coordenadas en un plano (la pantalla).

Por tanto tenemos que una Raqueta es dos números que representan las coordenadas del origen,un número que representa el ancho y un número que representa el alto. ¿Y una Bola?Recordemos que en el Pong original, la bola era un cuadrado. Por tanto, y teniendo en cuenta queun Cuadrado es un Rectángulo con el ancho y alto iguales, podemos llegar a la conclusión de queambas tienen en común su representación. Esto nos permite pensar en una superclaseElementoPong que tenga la funcionalidad necesaria para representar tanto Raquetas como Bolas.

Creamos un nuevo paquete llamado com.vidasconcurrentes.pongvc.juego. En él, creamos unanueva clase llamada Coordenada, y escribimos el siguiente código:

package com.vidasconcurrentes.pongvc.juego;

public class Coordenada {

 private int x; private int y;

 public Coordenada(int x, int y) {  this.x = x;  this.y = y; }

 public int getX() {  return x; }

 public void setX(int x) {  this.x = x; }

 public int getY() {  return y; }

 public void setY(int y) {  this.y = y; }}

Añadimos los getters y setters para ambos atributos porque queremos poder consultar sus valoresy cuando movamos los elementos, querremos modificarlos.

Ahora creamos una nueva clase llamada ElementoPong, y escribimos el siguiente código:

package com.vidasconcurrentes.pongvc.juego;

import android.graphics.Rect;

public abstract class ElementoPong {

 protected Coordenada origen; protected int ancho; protected int alto;

 public ElementoPong(Coordenada origen, int ancho, int alto) {  this.origen = origen;  this.ancho = ancho;  this.alto = alto; }

 public int getOrigenX() {  return origen.getX(); }

 public int getOrigenY() {  return origen.getY(); }

 public int getAncho() {  return ancho;

 }

 public int getAlto() {  return alto; }

 public Rect getRectElemento() {  return new Rect(getOrigenX(), getOrigenY(),                getOrigenX()+ancho, getOrigenY()+alto); }}

Con esto estamos creando un elemento del juego. Con el modificador abstract en la declaraciónde la clase estamos diciendo que no se pueden instanciar objetos de esta clase, con lo queobligamos a crear clases que hereden de ésta (y por tanto hereden todos los atributos yfuncionalidad ya descrita). La función getRectElemento() nos será útil a la hora de pintar loselementos, entre otras.

Además querremos que nuestros elementos se muevan, pero cada uno se moverá de formadistinta. En este caso vamos a crear una interfaz que obligue a las clases que la implementen aincluir una función para moverse. El código es el siguiente:

package com.vidasconcurrentes.pongvc.juego;

public interface ElementoPongMovil { public void move();}

Ahora sólo resta crear nuestra clase Raqueta y nuestra clase Bola. El código para la clase Raquetaserá:

package com.vidasconcurrentes.pongvc.juego;

public class Raqueta extends ElementoPong                     implements ElementoPongMovil {

 public Raqueta(Coordenada origen, int ancho, int alto) {  super(origen, ancho, alto); }

 @Override public void move() {

 }}

Y el código para la clase Bola será:

package com.vidasconcurrentes.pongvc.juego;

public class Bola extends ElementoPong                  implements ElementoPongMovil {

 public Bola(Coordenada origen, int ancho, int alto) {  super(origen, ancho, alto); }

 @Override public void move() {

 }}

Son iguales por ahora, ya que no hemos dado funcionalidad al método move() aún.

Para acabar con esta primera parte en la creación de la Activity del juego, vamos a mostrar todo enla pantalla. El primer paso va a ser añadir dos raquetas y una bola a nuestra aplicación. Para ello,vamos a la clase PongGameView y le añadimos los tres nuevos atributos, de modo que sean:

private PongGameThread paintThread;private ElementoPong raquetaIzda;private ElementoPong raquetaDcha;private ElementoPong bola;

Ahora instanciamos dichos atributos. Dependiendo de si nuestras instanciaciones van a necesitarde las dimensiones de nuestra superficie, crearemos nuestros objetos en el constructor dePongGameView si no lo necesitamos, o dentro del método surfaceCreated() si vamos anecesitarlo. En este caso vamos a necesitarlo, así que nuestro surfaceCreated() será así:

@Overridepublic void surfaceCreated(SurfaceHolder holder) { raquetaIzda = new Raqueta(new Coordenada(50,getHeight()/2‐50),                    20,100); raquetaDcha = new Raqueta(new Coordenada(getWidth()‐70,                    getHeight()/2‐50),20,100); bola = new Bola(new Coordenada(getWidth()/2‐5,getHeight()/2‐5),                 10,10);

 paintThread = new PongGameThread(getHolder(), this); paintThread.setRunning(true); paintThread.start();}

Esto hace que tengamos las raquetas en los laterales a la misma distancia de su pared, y la bolacentrada en pantalla. Las raquetas serán de 20×100 píxeles mientras que la bola será de 10×10píxeles.

Twittear 2 0 Follow

← Cross Site Scripting (XSS) Creando una aplicación de Android: el juego y lalógica (parte 2) →

Sólo nos resta añadir código al pintado para que muestre dichos elementos. Para ellomodificamos el método onDraw() de la siguiente forma:

@Overridepublic void onDraw(Canvas canvas) { Paint paint = new Paint(); paint.setColor(Color.WHITE);

 canvas.drawColor(Color.BLACK); canvas.drawRect(raquetaIzda.getRectElemento(), paint); canvas.drawRect(raquetaDcha.getRectElemento(), paint); canvas.drawRect(bola.getRectElemento(), paint);}

Et voilà! Podemos ejecutar nuestra aplicación y probar que lo que hemos hecho está bien. Si hasseguido el tutorial paso a paso, tendrás lo siguiente al pulsar Jugar en el menú:

En esta entrada hemos continuado el código de la entrada anterior en la que teníamos un menú, yhemos añadido la funcionalidad para que al pulsar en un determinado elemento del menú se creenuestro juego. Además hemos creado las clases necesarias para representar nuestro juego yhemos pintado estos elementos en pantalla.

Puedes descargar el proyecto de Eclipse con todo lo hecho hasta ahora pulsando aquí (MD5:e50037a2c1219ea0b5e8e464c72390aa). Además puedes importarlo a tu workbenchdirectamente y trabajar con ello.

En la siguiente entrada vamos a crear la lógica del juego: movimientos de las raquetas,movimiento de la pelota, restricciones de dichos movimientos (que no se salga de la pantalla, querebote la pelota…) y la creación del bucle de juego.

¡Un saludo a todos los lectores, y gracias por dedicarle tiempo!

0. Creando una aplicación de Android: la presentación1. Creando una aplicación de Android: primeros pasos

2. Creando una aplicación de Android: visión de conjunto y diseño del menú3. Creando una aplicación de Android: el juego y la lógica (parte 1)4. Creando una aplicación de Android: el juego y la lógica (parte 2)

5. Creando una aplicación de Android: mejoras (parte 1)6. Creando una aplicación de Android: mejoras (parte 2)

7. Creando una aplicación de Android: empaquetado y publicación

Esta entrada fue publicada en Android, Curso introducción Android, Programación y etiquetadacomo activity, aplicacion android, eclipse, graficos android, intent, java.

4 Respuestas a Creando una aplicación de Android: el juego y lalógica (parte 1)

1. william ayala dijo:20 noviembre, 2013 at 6:39

Hola muy buen sitio, a la vez necesitando de su ayuda, soy nuevo en programación yestamos trabajando en hacer un gps en android el problema es que no me genera error, ypues no se ejecuta me gustaría si me dan la oportunidad de enviarles una copia de miproyecto y los detalles específicos por email, saludos desde el salvador y gracias

2. Rohe dijo:30 octubre, 2013 at 18:50

Si no quisiera pintar un rectangulo sino un Bitmap, la clase elementopong, solo cambiaría enel método “public Rect getRectElemento()”? … o qué debería hacer?

Share7Like

Home Blog Síguenos Conócenos Contacto Escribe aquí para buscar...

← Creando una aplicación de Android: el juego yla lógica (parte 1)

Fingerprinting con wireshark y FOCA →

0. Creando una aplicación de Android: la presentación1. Creando una aplicación de Android: primeros pasos

2. Creando una aplicación de Android: visión de conjunto y diseño del menú3. Creando una aplicación de Android: el juego y la lógica (parte 1)4. Creando una aplicación de Android: el juego y la lógica (parte 2)

5. Creando una aplicación de Android: mejoras (parte 1)6. Creando una aplicación de Android: mejoras (parte 2)

7. Creando una aplicación de Android: empaquetado y publicación

Bienvenidos a la cuarta parte de la serie de entradas en el ciclo Creando una aplicación de Android.Si aún no lo has hecho, comienza desde la primera entrada mostrada en el menú inmediatamentesuperior.

Esta entrada se basa en el resultado de completar la anterior parte, en la que construíamos unanueva Activity para ejecutar nuestro juego. Además creábamos las clases necesarias para elpintado del juego y las necesarias para representar los elementos del juego. El resultado al quehabíamos llegado era mostrar lo siguiente:

En esta entrada vamos a completar la lógica del juego, haciendo que las raquetas y la bola semuevan y, en definitiva, se pueda jugar.

¡Comenzamos!

Importante: esta entrada va a basarse en los códigos creados en las anteriores entradas del ciclo alque pertenece. Tienes disponible pinchando aquí (MD5: e50037a2c1219ea0b5e8e464c72390aa)el proyecto de Eclipse con todo lo hecho hasta ahora, el cual puedes importar a tu Eclipse ycomenzar a trabajar.

Nota: esta entrada es bastante larga, pero incluye mucho código. ¡Quedáis avisados!

Recordemos que en la anterior entrada creamos una serie de clases que nos iban a servir pararepresentar nuestros elementos del juego. Disponíamos de una superclase ElementoPong quedescribía la representación de un elemento del juego (un rectángulo definido por una coordenadaorigen, un ancho y un alto), una interfaz ElementoPongMovil que obliga a implementar el métodomove() y dos clases que heredaban de la primera e implementaban la segunda (Raqueta y Bola).

Vamos a comenzar con el movimiento de las palas. Queremos que se muevan al tocar con eldedo sobre ellas, y se muevan donde vaya nuestro dedo.Para hacer esto, vamos a sobrescribir el método onTouchEvent() en nuestro PongGameView:

@Overridepublic boolean onTouchEvent(MotionEvent event) { int x = (int) event.getX(); int y = (int) event.getY();

 return true;}

Creando una aplicación de Android: el juego y lalógica (parte 2)

Publicado el 8 agosto, 2011 por meta

Categorías

AndroidCurso introducciónAndroidProgramaciónSeguridadSistemas Operativos

Entradas recientes

Automatizando lacreación de entornos dedesarrollo con VagrantColorshapes, el juego develocidad mental y figurasde colores para AndroideyeOS: Trabajando en lanubeIntegrando GoogleAnalytics en aplicacionesAndroidIntegrando Twitter enaplicaciones Android conSignPost y Twitter4J

Etiquetas

acelerometro activityalgoritmo androidaplicacion androidarbol backtrack bash BD

BEeF canvas contraseñas csrf

dns dns spoof eclipseexpresiones regularesgraficos androidgraphics android htc

desire intent javajavascript layout menu

metasploitmetasploitable mitmmysql oauth owasp

pentesting php seguridadpor defecto shodan

De esta forma estamos detectando las coordenadas X e Y en las que se ha detectado el evento,aunque de momento no hacemos nada con ellas. El siguiente paso es detectar qué tipo de acciónse ha hecho. ¿Hemos pulsado, hemos arrastrado o hemos levantado el dedo? Son los tres eventosque vamos a detectar. Para ello añadimos lo siguiente:

@Overridepublic boolean onTouchEvent(MotionEvent event) { int x = (int) event.getX(); int y = (int) event.getY();

 switch(event.getAction()) { case MotionEvent.ACTION_DOWN:  // hemos pulsado  break; case MotionEvent.ACTION_MOVE:  // hemos arrastrado  break; case MotionEvent.ACTION_UP:  // hemos levantado  break; }

 return true;}

El evento ACTION_DOWN se produce en el momento en que tocamos con el dedo en pantalla.El evento ACTION_MOVE se produce cuando, después de un ACTION_DOWN, movemos eldedo sin levantarlo. Finalmente, el evento ACTION_UP se produce al levantar el dedo de lapantalla.

En nuestro Pong vamos a querer poder mover la raqueta izquierda y la raqueta derecha, pero labola deberá moverse sola. Por tanto, en nuestro ACTION_DOWN vamos a ver si hemos tocadoen la raqueta izquierda, la derecha o en ninguna de ellas (siendo el estado inicial ninguna). Sihemos tocado en una de las dos, tenemos que quedarnos con cual es la que hemos tocado parapoder aplicarle los movimientos del ACTION_MOVE. Una vez que hagamos ACTION_UP lo queharemos será decir ya no estoy tocando ninguna de las raquetas.

Formas de hacer esto hay muchas y muy buenas, como por ejemplo usar un identificador paracada elemento, tener una colección de elementos móviles y pulsables y luego iterar sobre ellapara encontrar el elemento sobre el que se pulsó y quedarse con su identificador… Sin embargonosotros vamos a hacerlo simple, puesto que sólo vamos a permitir tocar en dos figuras (y esosólo cuando jueguen dos personas). Además, para calcular un desplazamiento, necesitamos laposición que vamos a llamar origen y la actual.

Lo primero, entonces, será añadir un nuevo parámetro al PongGameView, que será el elementoactivo, y el origen del movimiento, que será la posición del eje Y donde hemos puesto el dedo:

private ElementoPong elementoActivo = null;private int origenY;

Se inicializa a null porque inicialmente no hay ningún elemento activo.Ahora vamos a modificar el caso del ACTION_DOWN de la siguiente forma:

case MotionEvent.ACTION_DOWN: // hemos pulsado if(raquetaIzda.getRectElemento().contains(x, y)) {  elementoActivo = raquetaIzda;  origenY = y;  break; } if(raquetaDcha.getRectElemento().contains(x, y)) {  elementoActivo = raquetaDcha;  origenY = y;  break; } break;

Lo que hacemos es asignar al elemento activo el elemento sobre el que hemos tocado (si es quehemos tocado en alguno), y además asignamos el la posición Y en la que hemos pulsado a nuestravariable origenY. Repetimos el código de la asignación en lugar de hacerlo siempre para evitarasignaciones innecesarias (los dispositivos son suficientemente rápidos como para procesar unasmiles de asignaciones extra… pero es interesante valorar el lugar donde vamos a poner nuestrasinstrucciones con respecto del número de veces que se ejecutarán). El método contains(int,int) dela clase Rect nos viene de perlas para no tener que hacer una línea con 4 and. Aunque nunca ennuestro juego puede darse que estemos tocando la raqueta izquierda y además la raquetaderecha, hacemos un break después de asignar el elemento para curarnos en salud, y de pasoejecutar un par de operaciones menos.

Lo siguiente que vamos a hacer es el caso del ACTION_UP, que es tan simple como volver a nullel elemento activo. La variable origenY no la vamos a devolver a ningún estado nulo porque nonos hace falta (no hacemos comprobaciones con ella). Podríamos hacer una comprobación paraponer null si el elemento activo no lo es ya, pero como en nuestro caso queremos que no hayanada activo al soltar, lo hacemos de la siguiente forma:

case MotionEvent.ACTION_UP: // hemos levantado elementoActivo = null; break;

Finalmente, el caso de arrastrar. El concepto es: si hemos pulsado en un elemento durante elACTION_DOWN, entonces queremos moverle. Sin embargo, no queremos que nuestras raquetasse muevan horizontalmente, sino sólo verticalmente. Por tanto la modificación de la coordenada

smartphones SQL SQLi

trasteando twitter twitter4jVirtualBox wireshark xml xss

persistente

Sitios de interés

Android DevelopersAndroid.esBacktrackCommand Line Kung FuDragonJAREl Androide LibreExploits DatabaseFlu ProjectGran AngularHispasecMicrosiervosOpenLibraPentester.esPoesía BinariaSecurity By DefaultUn informático en el ladodel malWorld Wide WebConsistorium

será sólo en la Y. Recordemos que en los gráficos de Android (y en Java en general), se considera elorigen de coordenadas la esquina superior izquierda, y no la inferior izquierda como en un sistemade coordenadas cartesianas. Por tanto, si vamos hacia abajo sumamos y si vamos hacia arribarestamos.

Es, por tanto, el momento de implementar el método move() para las raquetas. Por ahora, vamosa tomar la decisión de diseño de cambiar el método move() de la interfaz ElementoPongMovil,para hacerla de la siguiente forma:

package com.vidasconcurrentes.pongvc.juego;

public interface ElementoPongMovil { public void move(int x, int y);}

Ahora al método move() le pasamos dos números enteros, que son el número de píxeles quedebe moverse en el eje X y el Y.

El método move() de la Raqueta y la Bola va a necesitar modificar su origen de coordenadas, porlo que hemos de añadir los siguientes métodos a ElementoPong:

public void setOrigenX(int newX) { origen.setX(newX);}

public void setOrigenY(int newY) { origen.setY(newY);}

La clase Coordenada ya tenía la funcionalidad para modificar sus valores.Ahora sí, el método move() para las Raquetas:

@Overridepublic void move(int x, int y) { origen.setY(origen.getY() + y);}

Simple. Recordemos que no nos interesa ningún desplazamiento en el eje X, así que nos da igualel valor de X que venga.

Volviendo al ACTION_MOVE, éste es su código:

case MotionEvent.ACTION_MOVE: // hemos arrastrado if(elementoActivo != null) {  Raqueta r = (Raqueta) elementoActivo;  r.move(0, y ‐ origenY); } origenY = y; break;

Sólo calculamos la diferencia de posiciones para mandárselo al método move(). Necesitamoshacer el casting explícito a Raqueta porque si no, no disponemos de move(). A move() le pasamoscomo primer parámetro un 0 que, aunque nos da igual su valor, nos ayuda a ver que no nosmoveremos en el eje X sin tener que saber el código de move().

Bien, ahora podemos mover las raquetas por pantalla y sólo verticalmente pero… echemos un ojoa la siguiente imagen:

Esto ocurre porque no hemos puesto restricciones por los lados (en este caso arriba y abajo). Esmomento de añadírselas.

Una buena práctica de Programación Orientada a Objetos consiste en tener claro que cada objetoes un conjunto de atributos y funciones relativas a una entidad. Es decir, cada objeto conoce susatributos y sabe operar con ellos, pero no tiene que saber cómo lo hacen los demás.

Pongamos un ejemplo muy simple. Digamos que tenemos una clase Persona que tiene atributospara definir nombre, apellidos, DNI… y operaciones para cambiar y consultar estos datos.Digamos que queremos escribir un objeto de esta clase Persona por pantalla. Lo primero quepodemos pensar es hacer una función dentro de Persona que sea mostrarPorPantalla() y queescriba en la salida estándar los datos. Sin embargo esto viola nuestra idea de POO, y veamos porqué. Imaginemos que ahora queremos escribirlo en un fichero. Y en una base de datos. Y en unSocket. Al final acabamos con una clase Persona que tiene mil y una funciones sólo encargadas deescribir esta clase Persona en diferentes lugares. También podríamos hablar de leer de fichero, debase de datos, de Socket, de entrada estándar…Lo correcto es que nuestra clase Persona tenga funciones para servir sus datos de las formas quese necesiten, y sean otras clases las encargadas de realizar la entrada y salida. Incluso, una clase sepuede encargar de la entrada y salida de Personas en un fichero, otra en una base de datos, otraen un Socket… En proyectos complejos es interesante crear clases más simples y especializadas

que operen con un conjunto relativamente pequeño de datos, para facilitar la modularidad.

Después de este tostón de buenas prácticas, volvamos a lo nuestro y analicemos las restricciones.No queremos que nuestra Raqueta se salga por arriba ni por abajo (no nos podemos mover enhorizontal, así que izquierda y derecha ni nos interesan). Y, siguiendo nuestra encapsulaciónexplicada arriba, es la Raqueta quien sabe sus atributos, por tanto es ella quien sabe si puedemoverse a un sitio o no, y no las demás clases. Una de las cosas que podemos hacer es crear unanueva función para las raquetas que nos diga si podemos hacer un movimiento antes de hacerlo,que también vamos a usar en la Bola (y además va a ser igual). Para ello añadimos una nuevadeclaración a nuestra superclase ElementoPong:

public boolean puedoMover(int x, int y, Rect screen) { return screen.contains(origen.getX() + x, origen.getY() + y,   origen.getX() + ancho + x, origen.getY() + alto + y);}

De esta forma podemos consultar si nuestro elemento (sea Raqueta o Bola) podrá realizar elmovimiento o no. Con esta función estamos pasándole el rectángulo que forma la pantalla paraque la propia Raqueta  Modificamos nuestro ACTION_MOVE para que quede así:

case MotionEvent.ACTION_MOVE: // hemos arrastrado if(elementoActivo != null) {  Raqueta r = (Raqueta) elementoActivo;  if(r.puedoMover(0, y ‐ origenY, new Rect(0, 0, getWidth(), getHeight())))    r.move(0, y ‐ origenY); } origenY = y; break;

Ahora podemos ejecutar de nuevo el proyecto e intentar sacar las palas de la pantalla, el resultadoserá similar a este:

Hasta aquí el movimiento de las Raquetas.

El siguiente paso es crear el movimiento de la Bola, la cual va a moverse automáticamente yrebotará contra los laterales y las Raquetas. Para hacerlo simple, ya que esto no es un tutorialsobre Cómo hacer un clon del Pong, vamos a simplificar mucho las posibilidades de movimiento yrebote.En nuestro caso, vamos a permitir solamente movimientos en las diagonales principales delsistema cartesiano (es decir, ángulos de 45º, 135º, 225º y 315º). De esta forma, añadimos lossiguientes atributos a nuestra clase Bola:

public static final int DCHA_ARRIBA = 1;public static final int IZDA_ARRIBA = 2;public static final int IZDA_ABAJO = 3;public static final int DCHA_ABAJO = 4;

private int direccion;

Parece ser que Android y los tipos enumerados de datos no se llevan especialmente bien y que serecomienda usar static final int en lugar de enums, así que esta es la razón que influye para estediseño. El constructor de la Bola sería el siguiente:

public Bola(Coordenada origen, int ancho, int alto) {  super(origen, ancho, alto);  direccion = 1;}

La variable dirección queda inicializada a 1 por ahora, pero más adelante la cambiaremos (en otraentrada). El método move() queda de la siguiente forma:

@Overridepublic void move(int x, int y) { switch(direccion) { case DCHA_ARRIBA:  origen.setX(origen.getX() + x);  origen.setY(origen.getY() ‐ y);  break; case IZDA_ARRIBA:  origen.setX(origen.getX() ‐ x);  origen.setY(origen.getY() ‐ y);  break; case IZDA_ABAJO:  origen.setX(origen.getX() ‐ x);  origen.setY(origen.getY() + y);  break; case DCHA_ABAJO:  origen.setX(origen.getX() + x);  origen.setY(origen.getY() + y);  break; }

}

Básicamente nos quitamos de trigonometría para hacer la explicación más simple ya que eso notiene nada que ver con Android. Ahora es el momento de hacer que automáticamente la bola semueva. Para ello vamos a crear una nueva clase llamada BolaMoveThread con el siguiente código:

package com.vidasconcurrentes.pongvc.juego;

public class BolaMoveThread extends Thread {

 private Bola bola; private boolean run; private int speed;

 public BolaMoveThread(Bola bola) {  this.bola = bola;  this.run = false;  this.speed = 1; }

 public void setRunning(boolean run) {  this.run = run; }

 @Override public void run() {  while(run) {   try {    Thread.sleep(10);   } catch (InterruptedException e) {    e.printStackTrace();   }   bola.move(speed, speed);  } }}

Es muy similar al Thread que se encarga del pintado. Ahora tenemos que ejecutar el Thread. Paraello, en la clase PongGameView, añadimos como nuevo atributo este Thread, de modo que ahoratenemos todos estos atributos:

private PongGameThread paintThread;private BolaMoveThread bolaThread; 

private ElementoPong raquetaIzda;private ElementoPong raquetaDcha;private ElementoPong bola;

private ElementoPong elementoActivo = null;private int origenY;

Ahora, creamos el Thread y lo arrancamos en surfaceCreated(), de modo que el código queda:

@Overridepublic void surfaceCreated(SurfaceHolder holder) { raquetaIzda = new Raqueta(new Coordenada(50,getHeight()/2‐50),20,100); raquetaDcha = new Raqueta(new Coordenada(getWidth()‐70,getHeight()/2‐50),20,100); bola = new Bola(new Coordenada(getWidth()/2‐5,getHeight()/2‐5),10,10);

 paintThread = new PongGameThread(getHolder(), this); paintThread.setRunning(true); paintThread.start();

 bolaThread = new BolaMoveThread((Bola)bola); bolaThread.setRunning(true); bolaThread.start();}

Y por último, en surfaceDestroyed() paramos el hilo, para que deje de mover la bola y muera:

@Overridepublic void surfaceDestroyed(SurfaceHolder arg0) { boolean retry = true; paintThread.setRunning(false); bolaThread.setRunning(false); while (retry) {  try {   paintThread.join();   bolaThread.join();   retry = false;  } catch (InterruptedException e) { } }}

Ahora podemos ejecutar el proyecto y veremos que la bola se mueve en la diagonal del primercuadrante. Aquí tenemos un par de fotos de la ejecución:

Como vemos, no estamos aplicando restricciones de movimiento, de modo que la pelota se va dela pantalla y sigue moviéndose, pero lógicamente no se pinta porque no está en pantalla. Elsiguiente paso, y último de esta entrada, consiste en hacer que la pelota rebote.

Para ello, vamos a añadirle a la Bola dos nuevos métodos. Uno se llamará puedoMover() comohicimos en la Raqueta y el otro se llamará rebota().

Comenzamos creando el método puedoMover(). Vamos a sobrecargar dicha función que vieneheredada de ElementoPong para agregar funcionalidad de la siguiente forma:

public boolean puedoMover(int x, int y, Rect screen,              Rect raquetaIzda, Rect raquetaDcha) { if(!puedoMover(x,y,screen))  return false; if(chocaraCon(x,y,raquetaIzda))  return false; if(chocaraCon(x,y,raquetaDcha))  return false;

 return true;}

Siendo la función chocaraCon() la siguiente:

private boolean chocaraCon(int x, int y, Rect raqueta) { if(raqueta.contains(origen.getX()+x, origen.getY()+y))  return true; if(raqueta.contains(origen.getX()+ancho+x, origen.getY()+y))  return true; if(raqueta.contains(origen.getX()+x, origen.getY()+alto+y))  return true; if(raqueta.contains(origen.getX()+ancho+x, origen.getY()+alto+y))  return true;

 return false;}

De esta forma hacemos como cortocircuito las comprobaciones, apoyándonos en elpuedoMostrar() primitivo. Básicamente comprobamos que al hacer el movimiento no nosmetemos en ninguna raqueta ni nos salimos de la pantalla (de ahí el sumar x e y en cada paso).

Ahora vamos a modificar el método run() del BolaMoveThread, de la siguiente forma:

@Overridepublic void run() { while(run) {  try {   Thread.sleep(10);  } catch (InterruptedException e) {   e.printStackTrace();  }  if(bola.puedoMover(speed, speed, screen,        raquetaIzda.getRectElemento(), raquetaDcha.getRectElemento()))   bola.move(speed, speed); }}

Si ejecutamos esto, llegaremos a la siguiente imagen:

Ahora tenemos que crear los rebotes, primero con las paredes y luego con las raquetas. Por ahoravamos a hacer que rebote con todos los lados de la pantalla. Para ello, creamos el siguientemétodo en la clase Bola:

public void rebota(int x, int y, Rect screen,                   Rect raquetaIzda, Rect raquetaDcha) { if(!puedoMover(x,y,screen)) {  switch(direccion) {  case DCHA_ARRIBA:   direccion = (origen.getY() ‐ y <= screen.top) ?     DCHA_ABAJO : IZDA_ARRIBA;   break;  case IZDA_ARRIBA:   direccion = (origen.getY() ‐ y <= screen.top) ?

     IZDA_ABAJO : DCHA_ARRIBA;   break;  case IZDA_ABAJO:   direccion = (origen.getY() + alto + y >= screen.bottom) ?     IZDA_ARRIBA : DCHA_ABAJO;   break;  case DCHA_ABAJO:   direccion = (origen.getY() + alto + y >= screen.bottom) ?     DCHA_ARRIBA : IZDA_ABAJO;   break;  } }}

Con esto estamos haciendo una pequeña lógica de rebotes con la pantalla. Para hacernos unaidea, pongamos el ejemplo de que la bola vaya hacia arriba a la derecha (DCHA_ARRIBA). En estecaso sólo podemos estar chocando con la parte de la derecha o la parte de arriba. Por ahora (ya locambiaremos en la siguiente entrada), si choca en la derecha va a rebotar en lugar de marcar unpunto. Por tanto, si estamos yendo hacia la derecha y arriba (ángulo de 45º), rebotaremos haciaabajo y a la derecha (ángulo de 315º, 45+315=360, con lo que comprobamos que está bien). Paracomprobar esto miramos que la parte mas alta de nuestra Bola, después de moverse, hayaatravesado la pantalla por arriba. Si no es así, es que estamos chocando con la otra opción: laderecha.La misma idea se usa para el resto de las situaciones.

Sólo resta modificar el código del run() en el BolaMoveThread:

@Overridepublic void run() { while(run) {  try {   Thread.sleep(10);  } catch (InterruptedException e) {   e.printStackTrace();  }  if(!bola.puedoMover(speed, speed, screen,        raquetaIzda.getRectElemento(), raquetaDcha.getRectElemento()))   bola.rebota(speed, speed, screen,        raquetaIzda.getRectElemento(), raquetaDcha.getRectElemento());  bola.move(speed, speed); }}

Falta cambiar la creación del Thread en PongGameView por:

bolaThread = new BolaMoveThread((Bola)bola, (Raqueta)raquetaIzda,          (Raqueta)raquetaDcha, new Rect(0,0,getWidth(),getHeight()));bolaThread.setRunning(true);bolaThread.start();

De modo que el constructor y los atributos de BolaMoveThread ahora son:

private Bola bola;private Raqueta raquetaIzda;private Raqueta raquetaDcha;private Rect screen;

private boolean run;private int speed;

public BolaMoveThread(Bola bola, Raqueta izda, Raqueta dcha, Rect screen, Context context) {  this.bola = bola;  this.raquetaIzda = izda;  this.raquetaDcha = dcha;  this.screen = screen;  this.run = false;  this.speed = 1;}

Si ejecutamos ahora, la bola rebotará indefinidamente por la pantalla atravesando las Raquetas.Ahora vamos a crear los rebotes con éstas. Para esta entrada vamos a comprobar los rebotes portodos los lados de cada raqueta, aunque en el juego final hay colisiones que no tenemos quecomprobar (como el caso del lado izquierdo de la raqueta izquierda, o el del lado derecho de laraqueta derecha). Modificamos el código del método rebota() añadiendo el siguiente código:

Rect raqueta = null;if(chocaraCon(x, y, raquetaIzda))  raqueta = raquetaIzda;if(chocaraCon(x, y, raquetaDcha))  raqueta = raquetaDcha;if(raqueta != null) {  switch(direccion) {  case DCHA_ARRIBA:    direccion = (origen.getX()+ancho < raqueta.left) ?         IZDA_ARRIBA : DCHA_ABAJO;    break;  case IZDA_ARRIBA:    direccion = (origen.getX() > raqueta.right) ?        DCHA_ARRIBA : IZDA_ABAJO;    break;  case IZDA_ABAJO:    direccion = (origen.getX() > raqueta.right) ?        IZDA_ARRIBA : DCHA_ABAJO;    break;  case DCHA_ABAJO:    direccion = (origen.getX()+ancho < raqueta.left) ?        IZDA_ABAJO : DCHA_ARRIBA;    break;  }

vidasConcurrentesSitio creado por meta y sshMan

Twittear 1 1 Follow

← Creando una aplicación de Android: el juego yla lógica (parte 1)

Fingerprinting con wireshark y FOCA →

}

Básicamente es comprobar por dónde estamos chocando, y rebotar en la dirección correcta.

Si ejecutamos el código ahora tendremos un Pong en el cual la bola rebota en todas las paredes yambas raquetas, que era nuestro objetivo.

Aquí acaba esta segunda parte de la lógica del juego. Ha sido una entrada muy larga, pero he dedecir en mi defensa que contiene mucho código para que sea fácil de seguir y comprender. Vaya,lo que es un paso a paso.

En esta entrada hemos ampliado la funcionalidad del proyecto que teníamos hasta ahora, paraañadir la lógica de movimientos de las raquetas y la bola, incluyendo los rebotes de ésta con cadaelemento y la creación de un Thread que se encarga de actualizar la posición de la misma.

En la siguiente entrada del ciclo Cómo crear una aplicación en Android vamos a añadir los últimosretoques: el marcador del juego y su representación en pantalla, la posibilidad de aumentar ladificultad cambiando la velocidad de la bola y posiblemente una Inteligencia Artificial muy simple.

Como siempre, podéis descargar el proyecto completo hasta el momento desde aquí (MD5:31b264db2de4125fa01c52d4d169bc99), e importarlo a vuestro Eclipse.

¡Muchas gracias por la lectura!

0. Creando una aplicación de Android: la presentación1. Creando una aplicación de Android: primeros pasos

2. Creando una aplicación de Android: visión de conjunto y diseño del menú3. Creando una aplicación de Android: el juego y la lógica (parte 1)4. Creando una aplicación de Android: el juego y la lógica (parte 2)

5. Creando una aplicación de Android: mejoras (parte 1)6. Creando una aplicación de Android: mejoras (parte 2)

7. Creando una aplicación de Android: empaquetado y publicación

Esta entrada fue publicada en Android, Curso introducción Android, Programación y etiquetadacomo aplicacion android, eclipse, graficos android, java, thread.

2 Respuestas a Creando una aplicación de Android: el juego y lalógica (parte 2)

1. Darker dijo:27 julio, 2012 at 3:22

Muy buen tutorial!!!! Pero necesito ayuda, he seguido todos los pasos hasta el final de estaparte, y se muestran las figuras pero no hay manera de moverlas. Me descargué tu versión yesta todo igual. No se a que puede deberse… y me estoy volviendo loco.Gracias por adelantado y encantado de haber encontrado un tutorial así!

2. ohcan dijo:9 agosto, 2011 at 0:30

Buen trabajo META,prefiero que hagas el paso a paso,asi comprendo el codigo y sufuncion.UNsaludo

Share3Like

Home Blog Síguenos Conócenos Contacto Escribe aquí para buscar...

← Fingerprinting con wireshark y FOCA Nessus en Backtrack 5: Instalación e integracióncon Metasploit →

0. Creando una aplicación de Android: la presentación1. Creando una aplicación de Android: primeros pasos

2. Creando una aplicación de Android: visión de conjunto y diseño del menú3. Creando una aplicación de Android: el juego y la lógica (parte 1)4. Creando una aplicación de Android: el juego y la lógica (parte 2)

5. Creando una aplicación de Android: mejoras (parte 1)6. Creando una aplicación de Android: mejoras (parte 2)

7. Creando una aplicación de Android: empaquetado y publicación

Bienvenidos a la quinta parte de la serie de entradas en el ciclo Creando una aplicación deAndroid. Si aún no lo has hecho, comienza desde la primera entrada mostrada en el menúinmediatamente superior.

En esta entrada vamos a continuar con el resultado de la entrada anterior, en la que habíamosacabado la lógica de movimientos y las colisiones. Añadiremos funcionalidades durante estaentrada y la siguiente para acabar la aplicación.Para esta entrada añadiremos vibración del dispositivo, reproducción de sonidos y uso delacelerómetro para los movimientos de las raquetas.

¡Comenzamos!

Importante: esta entrada va a basarse en los códigos creados en lasanteriores entradas del ciclo al que pertenece. Tienes disponible pinchando aquí (MD5:31b264db2de4125fa01c52d4d169bc99) el proyecto de Eclipse con todo lo hecho hasta ahora, elcual puedes importar a tu Eclipse y comenzar a trabajar.

El Android SDK incluye una gran cantidad de clases que hace muy sencillo el uso de los sensoresdel dispositivo, la vibración, la reproducción de audio… Para mostrar cómo de sencillo es,comenzamos añadiéndole vibración a nuestra aplicación. Comenzamos abriendo nuestro Eclipse.

Vibración

Para que una aplicación pueda vibrar, ya que necesita acceder a un elemento del sistema, necesitaque el usuario acepte el uso de este elemento. Para ello tenemos que añadir alAndroidManifest.xml que queremos usar vibración. Tenemos dos formas, la primera es añadiendo<uses-sdk android:minSdkVersion=”7″ /> justo detrás de la etiqueta <manifest … >.La segunda forma consiste en ir a la pestaña Permissions del manifest, pulsar en Add, elegir UsesPermission y aceptar, y luego escribir android.permission.VIBRATE en el cuadro de la derecha. Losiguiente es programar el uso del vibrador.

El uso de la vibración está definido por un Context, por lo que vamos a necesitar usar el contextode nuestra aplicación para poder obtener el vibrador y posteriormente hacerlo vibrar. La vibraciónla vamos a realizar solamente cuando la Bola rebote en una de las dos Raquetas. Si recordamoslas entradas anteriores, nuestra Bola y nuestra Raqueta tenían una función llamada puedoMover(),heredada de su superclase ElementoPong, que decía si se podía mover este elemento sin salirsede la pantalla. Sabemos que cuando una bola rebota es porque se ha chocado con algo. Si se hachocado con algo pero aún se puede mover por la pantalla significa que, por eliminación, se hachocado con una raqueta. Ya tenemos planteado lo que vamos a hacer, así que hagámoslo.

Primero vamos a añadir un nuevo atributo a la clase BolaMoveThread de la siguiente forma:

private Vibrator v = null;

Este será nuestro vibrador. Ahora necesitamos inicializarle, puesto que está a null y si lo usáramosahora la aplicación se moriría debido a un NullPointerException (de ahí que se inicialice a null, paradebuggearlo más fácil). Para inicializarle necesitamos el Context de la aplicación, de modo que alconstructor de BolaMoveThread le vamos a pasar el Context, quedando así:

public BolaMoveThread(Bola bola, Raqueta izda, Raqueta dcha,        Rect screen, Context context) {  this.bola = bola;  this.raquetaIzda = izda;  this.raquetaDcha = dcha;  this.screen = screen;  this.run = false;  this.speed = 1;  this.v = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);}

Faltaría cambiar la forma en que se crea este Thread de la siguiente forma (en el métodosurfaceCreated() del PongGameView:

bolaThread = new BolaMoveThread((Bola)bola, (Raqueta)raquetaIzda,        (Raqueta)raquetaDcha, new Rect(0,0,getWidth(),getHeight()),        this.getContext());

Por último sólo queda hacer que vibre, para ello vamos a modificar el código del run() delBolaMoveThread de la siguiente forma:

@Overridepublic void run() {  while(run) {    try {      Thread.sleep(10);    } catch (InterruptedException e) {      e.printStackTrace();    }    if(!bola.puedoMover(speed, speed, screen, raquetaIzda.getRectElemento(), raquetaDcha.getRectElemento())) {      bola.rebota(speed, speed, screen, raquetaIzda.getRectElemento(), raquetaDcha.getRectElemento());      if(bola.puedoMover(speed, speed, screen))          v.vibrate(50);    }    bola.move(speed, speed);  }}

Con esto estamos haciendo una vibración breve (50 milisegundos) cada vez que rebotamoscontra una raqueta. Fácil, ¿verdad?

Como información extra tenemos que saber que un objeto de la clase Vibrator también puedevibrar dado un patrón, utilizando la función vibrate(pattern, repeat), siendo pattern un long[] yrepeat un int que dice cuántas veces se repite (-1 si no queremos repetir).

Sonido

Creando una aplicación de Android: mejoras(parte 1)

Publicado el 21 agosto, 2011 por meta

Categorías

AndroidCurso introducciónAndroidProgramaciónSeguridadSistemas Operativos

Entradas recientes

Automatizando lacreación de entornos dedesarrollo con VagrantColorshapes, el juego develocidad mental y figurasde colores para AndroideyeOS: Trabajando en lanubeIntegrando GoogleAnalytics en aplicacionesAndroidIntegrando Twitter enaplicaciones Android conSignPost y Twitter4J

Etiquetas

acelerometro activityalgoritmo androidaplicacion androidarbol backtrack bash BD

BEeF canvas contraseñas csrf

dns dns spoof eclipseexpresiones regularesgraficos androidgraphics android htc

desire intent javajavascript layout menu

metasploitmetasploitable mitmmysql oauth owasp

pentesting php seguridadpor defecto shodan

smartphones SQL SQLi

trasteando twitter twitter4jVirtualBox wireshark xml xss

persistente

Sitios de interés

Android DevelopersAndroid.esBacktrackCommand Line Kung FuDragonJAREl Androide LibreExploits DatabaseFlu ProjectGran AngularHispasecMicrosiervosOpenLibraPentester.esPoesía BinariaSecurity By DefaultUn informático en el ladodel malWorld Wide WebConsistorium

El siguiente paso consistirá en añadir sonido a los rebotes, el típico sonido metálico. Existendiversas formas de usar sonidos en Android, pero vamos a usar la más simple de todas: elMediaPlayer. Lo primero que tenemos que hacer es buscar un sonido que nos valga. Por lo generalse recomienda usar ficheros codificados en formato .ogg (Ogg Vorbis) por ser el más compatible ytener una gran compresión. Yo he elegido el siguiente sonido. Si quieres usar el mismo, haz clickderecho sobre el enlace y selecciona Guardar enlace como (y guárdalo con un nombre distinto, enminúsculas, sin espacios y sin tildes).

Ahora crearemos una nueva carpeta dentro de la carpeta res de nuestro proyecto, y la llamaremosraw. Dentro de ella meteremos nuestro fichero de audio (en mi caso pong.ogg). A partir de ahorapodremos acceder a ello referenciando a R.raw.pong. Añadimos un nuevo atributo aBolaMoveThread:

private MediaPlayer mp = null;

Y el constructor queda así:

public BolaMoveThread(Bola bola, Raqueta izda,        Raqueta dcha, Rect screen, Context context) {  this.bola = bola;  this.raquetaIzda = izda;  this.raquetaDcha = dcha;  this.screen = screen;  this.run = false;  this.speed = 1;  this.v = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);  this.mp = MediaPlayer.create(context, R.raw.pong);}

La llamada a MediaPlayer.create() crea y prepara el audio local para ser reproducido. Existe unafunción de los objetos MediaPlayer llamada prepare() que hace lo mismo (pero sólo hay quellamarla en ciertos momentos, ahora explicamos más). Falta hacer que reproduzca el sonido, demodo que vamos a la función run(), que queda:

@Overridepublic void run() {  while(run) {    try {      Thread.sleep(10);    } catch (InterruptedException e) {      e.printStackTrace();    }    if(!bola.puedoMover(speed, speed, screen, raquetaIzda.getRectElemento(), raquetaDcha.getRectElemento())) {      mp.start();      bola.rebota(speed, speed, screen, raquetaIzda.getRectElemento(), raquetaDcha.getRectElemento());      if(bola.puedoMover(speed, speed, screen))          v.vibrate(50);    }    bola.move(speed, speed);  }}

Podríamos hacer un stop() y prepare() después y antes (respectivamente) de cada start(). Sinembargo eso sería un consumo muy grande de los recursos, y start() ya mantiene preparado elaudio para hacer un replay. Sería interesante, sin embargo, hacer una llamada a stop() y prepare()dentro del setRunning() dependiendo de si paramos o iniciamos el thread. Agregar sonidossimples ha resultado ser también muy fácil, ¿no?

Activar y desactivar

Ahora mismo tenemos que la aplicación hace que el dispositivo vibre al rebotar con una pala, yhace que reproduzca un sonido de choque metálico cada vez que rebote con algo (sea pared oraqueta). Recordemos que tenemos un menú en el cual teníamos una parte de Opciones, peroque no tenía nada dentro. Es ahora el momento de crear las opciones del juego, permitiendoactivar y desactivar estas dos funcionalidades.

Comenzamos creando un nuevo layout que tendrá el siguiente código:

<?xml version="1.0" encoding="utf‐8"?><TableLayout xmlns:android="http://schemas.android.com/apk/res/android"  android:orientation="vertical" android:layout_width="fill_parent"  android:layout_height="fill_parent">  <TableRow android:id="@+id/tableRow1" android:layout_width="wrap_content"    android:layout_height="wrap_content">    <TextView android:textAppearance="?android:attr/textAppearanceLarge"      android:layout_width="wrap_content" android:layout_height="wrap_content"      android:width="250dip" android:paddingLeft="30dip" android:id="@+id/labelSonido"      android:text="@string/sonidoMenu"></TextView>    <CheckBox android:layout_width="wrap_content" android:id="@+id/checkBoxSonido"      android:layout_height="wrap_content" android:checked="true"></CheckBox>  </TableRow>  <TableRow android:id="@+id/tableRow2" android:layout_width="wrap_content"    android:layout_height="wrap_content">    <TextView android:textAppearance="?android:attr/textAppearanceLarge"      android:layout_width="wrap_content" android:layout_height="wrap_content"      android:paddingLeft="30dip" android:id="@+id/labelVibracion"      android:text="@string/vibracionMenu"></TextView>    <CheckBox android:layout_width="wrap_content" android:id="@+id/checkBoxVibracion"      android:layout_height="wrap_content" android:checked="true"></CheckBox>  </TableRow></TableLayout>

Teniendo en cuenta que tenemos que añadir los Strings a strings.xml:

<?xml version="1.0" encoding="utf‐8"?><resources>  <string name="app_name">Pong</string>  <string name="menu_play">Jugar</string>  <string name="menu_options">Opciones</string>  <string name="menu_exit">Salir</string>  <string name="sonidoMenu">Sonido</string>  <string name="vibracionMenu">Vibración</string></resources>

Tenemos que añadir la Activity al AndroidManifest.xml igual que hicimos en otra de las entradas.Para ello abrimos el AndroidManifest.xml y añadimos lo siguiente antes de </application>:

<activity android:name=".PongOpcionesActivity" android:screenOrientation="portrait"></activity>

Lo siguiente que necesitamos hacer es añadir el código necesario para crear una actividad nuevaque muestre este nuevo layout. Creamos una nueva clase llamada PongOpcionesActivity, cuyocódigo es el siguiente:

package com.vidasconcurrentes.pongvc;

import android.app.Activity;import android.os.Bundle;import android.view.Window;import android.view.WindowManager;

public class PongOpcionesActivity extends Activity {

  @Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    requestWindowFeature(Window.FEATURE_NO_TITLE);        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,                            WindowManager.LayoutParams.FLAG_FULLSCREEN);    setContentView(R.layout.options);  }}

Ahora sólo falta hacer el código en la actividad principal para que se ejecute esta. Para ello vamos ala clase PongvCActivity (la principal), y añadimos la función:

private void muestraOpciones() {  Intent opciones = new Intent(this, PongOpcionesActivity.class);  this.startActivity(opciones);}

Ahora en el onCreate() de esta clase, vamos al lugar donde registramos el listener para el botón deOpciones y cambiamos el contenido por lo siguiente:

TextView options = (TextView)findViewById(R.id.options_button);options.setOnClickListener(new OnClickListener() {  @Override  public void onClick(View v) {    muestraOpciones();  }});

Ahora sí, si hacemos una ejecución, obtendremos esto tras pulsar en el botón Opciones del menúprincipal:

Ahora tenemos que programar qué pasa cuando activamos y desactivamos estos checkboxes. Heelegido hacer lo siguiente con un patrón Singleton. A grandes rasgos, un patrón Singleton ofrece lagarantía de que existe como máximo una instancia de una clase y que es accesible globalmente.Nosotros queremos poder acceder al estado de estas opciones desde el juego, pero modificarlasdesde esta actividad. De modo que comenzamos creando nuestra clase PongOpciones dentro deun nuevo paquete llamado com.vidasconcurrentes.pongvc.opciones:

package com.vidasconcurrentes.pongvc.opciones;

public class PongOpciones {

  private static PongOpciones opciones = null;  private boolean sonido;  private boolean vibracion;

  private PongOpciones() {    sonido = true;    vibracion = true;  }

  public static synchronized PongOpciones getInstance() {    if(opciones == null)      opciones = new PongOpciones();    return opciones;  }

  public void toggleSound() {    sonido = !sonido;  }

  public void toggleVibration() {    vibracion = !vibracion;  }

  public boolean soundEnabled() {    return sonido;  }

  public boolean vibrationEnabled() {    return vibracion;  }}

Las ponemos inicializadas a true porque, por defecto, nuestra aplicación va a tener ambasactivadas. Ahora añadimos el comportamiento al pulsar sobre los checkboxes. Para ello vamos alonCreate() de la clase PongOpcionesActivity y añadimos lo siguiente al final:

CheckBox sonido = (CheckBox) findViewById(R.id.checkBoxSonido);sonido.setOnClickListener(new OnClickListener() {  @Override  public void onClick(View v) {    PongOpciones.getInstance().toggleSound();  }});

CheckBox vibracion = (CheckBox) findViewById(R.id.checkBoxVibracion);vibracion.setOnClickListener(new OnClickListener() {  @Override  public void onClick(View v) {    PongOpciones.getInstance().toggleVibration();  }});

sonido.setChecked(PongOpciones.getInstance().soundEnabled());vibracion.setChecked(PongOpciones.getInstance().vibrationEnabled());

Como vemos, lo último que hacemos es poner el estado de cada CheckBox acorde con el estadode la instancia del patrón Singleton. Cuando pulsamos en un CheckBox, cambiamos el valor de lavariable a la que se refiere de true a false y viceversa.

Efectivamente, si ejecutásemos ahora, comprobaríamos que podemos tener ambas activas,desactivadas o una activa y otra no.

Acelerómetro

El acelerómetro del dispositivo va a permitirnos registrar movimientos de éste para saber si se hacambiado la inclinación con respecto de la posición inicial con la que se comenzó el juego. Existenvarias formas de usar el acelerómetro, y por supuesto existen muchísimas e infinitas formas deprogramar dónde debe ir cada cosa en nuestro proyecto.Mis decisiones han sido las siguientes:

Queremos que se ejecute un Thread que controle la raqueta izquierda con el acelerómetro.Queremos quitar el registro del acelerómetro cuando no lo necesitemos.Queremos reanudar el uso del acelerómetro al volver al juego.

Al igual que hicimos al crear los hilos anteriores (pintado y movimiento de la bola), vamos a crearun hilo nuevo para las raquetas:

package com.vidasconcurrentes.pongvc.juego;

import android.graphics.Rect;

public class RaquetaMoveThread extends Thread {

  private Raqueta raqueta;  private Rect screen;

  private boolean run;

  public RaquetaMoveThread(Raqueta r, Rect s) {    raqueta = r;    screen = s;  }

  public void setRunning(boolean run) {    this.run = run;  }

  public void run() {    while(run) {      try {        Thread.sleep(10);      } catch (InterruptedException e) {        e.printStackTrace();

      }      // nuestro codigo va aqui    }  }}

En PongGameView creamos el hilo en surfaceCreated() y lo matamos en surfaceDestroyed():

// esto dentro de surfaceCreated()raquetaThread = new RaquetaMoveThread((Raqueta)raquetaIzda,                new Rect(0,0,getWidth(),getHeight()));raquetaThread.setRunning(true);raquetaThread.start();

// esto seria el surfaceDestroyed():@Overridepublic void surfaceDestroyed(SurfaceHolder arg0) {  boolean retry = true;  paintThread.setRunning(false);  bolaThread.setRunning(false);  raquetaThread.setRunning(false);  while (retry) {    try {      paintThread.join();      bolaThread.join();      raquetaThread.join();      retry = false;    } catch (InterruptedException e) { }  }}

Ahora es el momento de crear nuestro acelerómetro. Para ello vamos a crear una clase envolventepara la funcionalidad que queremos que nos ofrezca. Un dispositivo emulado no puede usaracelerómetro, así que será necesario el uso de un dispositivo físico.Nosotros vamos a querer que se mueva la raqueta. Esta raqueta pertenece a una actividad queestá en modo landscape (apaisado) continuamente. Un dispositivo físico tiene su eje X a lo alto, esdecir, es una línea imaginaria que va desde los botones del dispositivo hasta el auricular. Si lopreferís: de abajo a arriba. Su eje Y es el perpendicular a éste que cruza de lado a lado. Como hastaahora hemos visto a la hora de pintar, con el dispositivo en modo apaisado, el eje X será el ancho yel eje Y será el alto. De modo que si nosotros rotamos el dispositivo hacia delante en modoapaisado, queremos que nuestra pala suba. Si rotamos el dispositivo hacia nosotros en modoapaisado, queremos que nuestra pala baje.Dicho en otras palabras: si la rotación del eje X es negativa, queremos que vaya arriba; si espositiva, queremos que vaya abajo. Para más información sobre los ejes de coordenadastridimensionales pulsa aquí.

Por tanto sólo nos interesa la rotación del eje X para nuestra pala, pero podemos acceder a losvalores de Y y Z consultando event.values[1] y event.values[2] respectivamente. Creamos unanueva clase AcelerometroPong en el paquete com.vidasconcurrentes.pongvc.juego:

package com.vidasconcurrentes.pongvc.juego;

import android.content.Context;import android.hardware.Sensor;import android.hardware.SensorEvent;import android.hardware.SensorEventListener;import android.hardware.SensorManager;

public class AcelerometroPong implements SensorEventListener {

  private SensorManager sm = null;  private int x;

  public AcelerometroPong(Context context) {    sm = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);  }

  public void register() {    sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),                SensorManager.SENSOR_DELAY_GAME);  }

  public void unregister() {    sm.unregisterListener(this);  }

  @Override  public void onAccuracyChanged(Sensor sensor, int accuracy) { }

  @Override  public void onSensorChanged(SensorEvent event) {    if(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {      x = Math.round(event.values[0] * 100);    }  }

  public int getXInclination() {    return x;  }}

Desde la Activity PongJuego vamos a usar esta clase como atributo, y añadiremos dos nuevosmétodos de modo que quedará así:

package com.vidasconcurrentes.pongvc;

import android.app.Activity;import android.os.Bundle;import android.view.Window;import android.view.WindowManager;

import com.vidasconcurrentes.pongvc.juego.AcelerometroPong;import com.vidasconcurrentes.pongvc.pintado.PongGameView;

public class PongJuego extends Activity {

  private AcelerometroPong acelerometro;

  @Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    requestWindowFeature(Window.FEATURE_NO_TITLE);        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,                            WindowManager.LayoutParams.FLAG_FULLSCREEN);        acelerometro = new AcelerometroPong(this.getApplicationContext());    setContentView(new PongGameView(this, acelerometro));  }

  @Override  protected void onResume() {    super.onResume();    acelerometro.register();  }

  @Override  protected void onStop() {    super.onStop();    acelerometro.unregister();  }}

Es importante no usar el sensor si no es necesario, de ahí onResume() y onStop().Nuestro PongGameView ahora recibe también el acelerómetro, así que tendremos que modificarel constructor para que así lo reciba y añadir un atributo nuevo.

private Integer xInit = null;private AcelerometroPong acelerometro;

public PongGameView(Context context, AcelerometroPong acelerometro) {  super(context);  getHolder().addCallback(this);

  this.acelerometro = acelerometro;}

Ahora, queremos que sea el Thread que controla el movimiento de la raqueta el encargado deconsultar el acelerómetro, así que igualmente cambiamos el constructor de éste y lo añadimos

como atributo a RaquetaMoveThread:

private AcelerometroPong acelerometro;

public RaquetaMoveThread(Raqueta r, Rect s, AcelerometroPong a) {  raqueta = r;  screen = s;  this.acelerometro = a;}

Además, añadimos esta nueva variable xInit de tipo Integer (para poder inicializarla a null). ¿Y porqué queremos inicializarla a null? Es tan sólo una pequeña treta que se me ha ocurrido para poderrealizar una calibración en cada ejecución. Si es null es que aún no hemos calibrado la posición enla que está el dispositivo al arrancar el Thread, si no es null es que ya está calibrado.

Ahora modificaremos el run() de este Thread, de la siguiente forma:

public void run() {  if(xInit == null)    xInit = acelerometro.getXInclination();

  while(run) {    try {      if(Math.abs(xInit ‐ acelerometro.getXInclination()) < 200)        Thread.sleep(5);      else        Thread.sleep(2);    } catch (InterruptedException e) {      e.printStackTrace();    }    if(xInit < acelerometro.getXInclination() ‐ UMBRAL ||       xInit < acelerometro.getXInclination() + UMBRAL)      if(raqueta.puedoMover(0, 1, screen))          raqueta.move(0, 1);    if(xInit > acelerometro.getXInclination() ‐ UMBRAL ||       xInit > acelerometro.getXInclination() + UMBRAL)      if(raqueta.puedoMover(0, ‐1, screen))        raqueta.move(0, ‐1);  }}

Lo primero que hacemos es inicializar la posición de calibrado, si es null. Lo siguiente que hacemoses hacer que el movimiento de la raqueta sea más o menos rápido dependiendo de si hemosinclinado mucho el dispositivo o no. En nuestro caso, si hay una diferencia absoluta (positiva onegativa) de menos de 200 unidades, entonces nos vamos a mover a una velocidad normal. Siesto es mayor significa que hemos inclinado el dispositivo mucho más, por lo que deseamos quese mueva más rápido. La variable UMBRAL no es más que una variable final de la clase que en estecaso tiene el valor de 20. Este UMBRAL nos sirve para no mover la raqueta si el movimiento esdemasiado pequeño (quizá por errores de medida o de redondeo). Además añadimos lacomprobación de si puedoMover() para evitar salirse de la pantalla.

Con esto ya tenemos la raqueta izquierda funcionando para moverse con el acelerómetro, pero ala vez funciona con el dedo y esto no es lo deseable.

Activar / desactivar acelerómetro

Igual que hicimos con el sonido y la vibración, ahora queremos poder cambiar acelerómetro portáctil y viceversa. Para ello vamos a nuestra clase PongOpciones y añadimos un nuevo atributo, demodo que queda:

private static PongOpciones opciones = null;private boolean sonido;private boolean vibracion;private boolean acelerometro;

private PongOpciones() {  sonido = true;  vibracion = true;  acelerometro = false;}

Añadimos también los siguientes dos métodos, para cambiar el valor y consultarlo:

public void toggleAcelerometro() {  acelerometro = !acelerometro;}

public boolean accelerometerEnabled() {  return acelerometro;}

Ahora tenemos que llamar a estos métodos desde la actividad de las opciones, la cual necesita sercambiada para añadir una nueva fila. Por tanto, antes del </TableLayout> de options.xml,añadimos:

<TableRow android:id="@+id/tableRow3" android:layout_width="wrap_content" android:layout_height="wrap_content">  <TextView android:textAppearance="?android:attr/textAppearanceLarge" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/labelAccel" android:text="@string/accel" android:layout_marginLeft="30dip"></TextView>  <CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/checkBoxAccel"></CheckBox></TableRow>

Hay que añadir también el String al fichero strings.xml. De esta forma veríamos la siguienteimagen al ejecutar:

En el onCreate() de PongOpcionesActivity, añadimos:

CheckBox acelerometro = (CheckBox) findViewById(R.id.checkBoxAccel);acelerometro.setOnClickListener(new OnClickListener() {  @Override  public void onClick(View v) {    PongOpciones.getInstance().toggleAcelerometro();  }});

acelerometro.setChecked(PongOpciones.getInstance().accelerometerEnabled());

De esta forma cambiamos la variable de activado a desactivado y viceversa.

Es el momento ahora de hacer que la aplicación use una u otra. Todo el código se va a poner portanto en PongGameView. El Thread de la raqueta sólo se ejecuta cuando está activado elacelerómetro, por tanto modificamos el código de surfaceCreated() y cambiamos:

if(PongOpciones.getInstance().accelerometerEnabled()) {  raquetaThread = new RaquetaMoveThread((Raqueta)raquetaIzda,       new Rect(0,0,getWidth(),getHeight()), acelerometro);  raquetaThread.setRunning(true);  raquetaThread.start();}

Además, si este Thread no se ha iniciado, no se puede matar. Así que en surfaceDestroyed():

@Overridepublic void surfaceDestroyed(SurfaceHolder arg0) {  boolean retry = true;

vidasConcurrentesSitio creado por meta y sshMan

Twittear 1 0 Follow

← Fingerprinting con wireshark y FOCA Nessus en Backtrack 5: Instalación e integracióncon Metasploit →

  paintThread.setRunning(false);  bolaThread.setRunning(false);  if(PongOpciones.getInstance().accelerometerEnabled())    raquetaThread.setRunning(false);  while (retry) {    try {      paintThread.join();      bolaThread.join();      if(PongOpciones.getInstance().accelerometerEnabled())        raquetaThread.join();      retry = false;    } catch (InterruptedException e) { }  }}

Además, si activamos el acelerómetro no queremos poder mover la raqueta con el dedo. Demodo que en el onTouchEvent() vamos a envolverlo todo con un:

if(!PongOpciones.getInstance().accelerometerEnabled() {  // aqui todo el codigo anterior, incluyendo el switch}return true;

Hecho esto podemos ejecutar la aplicación y trastear con ella activando y desactivando cosas,reiniciando el juego… La idea es iniciar el juego, pulsar la tecla de “actividad anterior” que nos llevaal menú, elegir Opciones y cambiarlas, dar a “actividad anterior” y luego a Jugar.

Aquí llega el final de la entrada de hoy. En ella hemos visto cómo usar distintos sensores delsistema como la vibración o el acelerómetro, además de las herramientas que nos ofrece parareproducir sonidos locales. En la siguiente entrada acabaremos la aplicación añadiendo las últimasmejoras como un pequeño umbral para el juego táctil, el marcador de juego y la posibilidad de quese cuele la bola y por último una pequeña Inteligencia Artificial para la raqueta derecha.

Como siempre, podéis descargar el proyecto de Eclipse desde aquí (MD5:1e3eeda28b041716b8526aa59f1aa312) e importarlo a vuestro Eclipse.

Muchas gracias por la lectura y ¡hasta la próxima semana!

0. Creando una aplicación de Android: la presentación1. Creando una aplicación de Android: primeros pasos

2. Creando una aplicación de Android: visión de conjunto y diseño del menú3. Creando una aplicación de Android: el juego y la lógica (parte 1)4. Creando una aplicación de Android: el juego y la lógica (parte 2)

5. Creando una aplicación de Android: mejoras (parte 1)6. Creando una aplicación de Android: mejoras (parte 2)

7. Creando una aplicación de Android: empaquetado y publicación

Esta entrada fue publicada en Android, Curso introducción Android, Programación y etiquetadacomo acelerometro, activity, aplicacion android, mejoras, sonido, vibracion.

Una respuesta a Creando una aplicación de Android: mejoras(parte 1)

1. ohcan dijo:22 agosto, 2011 at 0:02

Gracias como siempre,en cuanto tenga tiempo me pongo a picar codigo,desarrollas cosasmuy interesantes en este simple juego

Share1Like

Home Blog Síguenos Conócenos Contacto Escribe aquí para buscar...

← Nessus en Backtrack 5: Instalación eintegración con Metasploit

Post-exploitation con WCE y Flu →

0. Creando una aplicación de Android: la presentación1. Creando una aplicación de Android: primeros pasos

2. Creando una aplicación de Android: visión de conjunto y diseño del menú3. Creando una aplicación de Android: el juego y la lógica (parte 1)4. Creando una aplicación de Android: el juego y la lógica (parte 2)

5. Creando una aplicación de Android: mejoras (parte 1)6. Creando una aplicación de Android: mejoras (parte 2)

7. Creando una aplicación de Android: empaquetado y publicación

Bienvenidos a la sexta parte de la serie de entradas en el ciclo Creando una aplicación de Android.Si aún no lo has hecho, comienza desde la primera entrada mostrada en el menú inmediatamentesuperior.

En esta entrada acabaremos el desarrollo de la aplicación, mejoraremos el control táctil parahacerlo más tolerante e incluiremos todo lo necesario para el uso del marcador (y que se guarde sivolvemos al menú). En la próxima y última entrada de la serie, publicaremos la aplicación.

¡Comencemos!

Importante: esta entrada va a basarse en los códigos creados en lasanteriores entradas del ciclo al que pertenece. Tienes disponible pinchando aquí(MD5: 1e3eeda28b041716b8526aa59f1aa312) el proyecto de Eclipse con todo lo hecho hastaahora, el cual puedes importar a tu Eclipse y comenzar a trabajar.

Mejora del control táctil

El primer paso para esta entrada va a ser el añadir un pequeño umbral al control táctil de lasraquetas. Ahora mismo el control exige que toquemos exactamente dentro de la raqueta,  demodo que si tocas un píxel por fuera no te va a detectar nada. El feedback de la gente que haprobado la aplicación en mi dispositivo es que necesita ser más tolerante, así que allá vamos.

Con nuestro Eclipse abierto, localizamos la clase PongGameView, que es la clase encargada deprocesar el control táctil. Vamos a añadir el siguiente atributo a la clase, que a fin de cuentas esuna constante:

El número que pongamos a esta variable será el número de píxeles de más que queremos queacepte por la izquierda y la derecha.Ahora vamos a añadir este umbral al procesado del control táctil. Para ello vamos a la funciónonTouchEvent() que, si recordamos, consta principalmente de un switch con tres casos. El primercaso se activa al pulsar, el segundo se activa al arrastrar después de haber pulsado y el tercero seactiva al soltar. Nosotros estamos interesados en el primer caso, así que lo modificaremos de lasiguiente forma:

Creando una aplicación de Android: mejoras(parte 2)

Publicado el 30 agosto, 2011 por meta

1 public static final int UMBRAL_TACTIL = 70;

1 case MotionEvent.ACTION_DOWN:2     // hemos pulsado3     Rect aux;4  5     aux = new Rect(raquetaIzda.getRectElemento());6     aux.set(aux.left ‐ UMBRAL_TACTIL, aux.top,7             aux.right + UMBRAL_TACTIL, aux.bottom);

8     if(aux.contains(x, y)) {9         elementoActivo = raquetaIzda;10         origenY = y;11         break;12     }

Categorías

AndroidCurso introducciónAndroidProgramaciónSeguridadSistemas Operativos

Entradas recientes

Automatizando lacreación de entornos dedesarrollo con VagrantColorshapes, el juego develocidad mental y figurasde colores para AndroideyeOS: Trabajando en lanubeIntegrando GoogleAnalytics en aplicacionesAndroidIntegrando Twitter enaplicaciones Android conSignPost y Twitter4J

Etiquetas

acelerometro activityalgoritmo androidaplicacion androidarbol backtrack bash BD

BEeF canvas contraseñas csrf

dns dns spoof eclipseexpresiones regularesgraficos androidgraphics android htc

desire intent javajavascript layout menu

metasploitmetasploitable mitmmysql oauth owasp

pentesting php seguridadpor defecto shodan

Así, usamos un rectángulo a partir de los rectángulos definidos por las raquetas, con la salvedad deque los expandimos por los lados tantas unidades como UMBRAL_TACTIL diga. Hasta aquí lamejora del control táctil.

Marcador

Lo siguiente que vamos a hacer es crear el marcador de juego y todo lo necesario para quefuncione. Es decir, cuando completemos esta sección tendremos algo jugable de principio a fin.

Comenzamos creando una clase Marcador:

De esta forma estamos definiendo que el juego acabará cuando uno de los dos jugadores haga 9puntos. Además estamos definiendo los comportamientos necesarios para inicializar el marcador,consultar el valor y añadir un punto a los jugadores.

Una cosa está clara cuando programamos, y es que queremos ver que las cosas que hacemosfuncionan, y queremos verlo lo antes posible. Por esta razón lo siguiente que vamos a hacer es lonecesario para mostrar en pantalla el marcador para que veamos que lo que vayamos haciendorealmente funciona.

Vamos a la clase PongGameView y añadimos un nuevo atributo de clase Marcador:

Además, añadimos el constructor de este objeto al constructor de la clase, de modo que elconstructor quedará:

Ahora ya contamos con un marcador. Lo siguiente será crear en PongGameView las funcionesnecesarias para pintar los números en pantalla. Queremos crear una linea divisoria a la mitad de lapantalla, al estilo Pong original. Comenzamos creando este método:

13  14     aux = new Rect(raquetaDcha.getRectElemento());15     aux.set(aux.left ‐ UMBRAL_TACTIL, aux.top,16             aux.right + UMBRAL_TACTIL, aux.bottom);17     if(aux.contains(x, y)) {18         elementoActivo = raquetaDcha;19         origenY = y;20         break;21     }22     break;

1 package com.vidasconcurrentes.pongvc.juego;2  3 public class Marcador {4  5     public static final int MAX_PUNT = 9;6  7     private int puntosIzda;8     private int puntosDcha;9  10     public void initMarcador() {11         puntosIzda = 0;12         puntosDcha = 0;13     }14  15     public Marcador() {16         initMarcador();17     }18  19     public int getPuntosIzda() {20         return puntosIzda;21     }22  23     public int getPuntosDcha() {24         return puntosDcha;25     }26  27     public void addPuntoIzda() {28         puntosIzda++;29     }30  31     public void addPuntoDcha() {32         puntosDcha++;33     }34  35     public boolean acabado() {36         return puntosDcha == MAX_PUNT || puntosIzda == MAX_PUNT;37     }38 }

1 private Marcador marcador;

1 public PongGameView(Context context, AcelerometroPong acelerometro){

2     super(context);3     getHolder().addCallback(this);4  5     this.acelerometro = acelerometro;6     this.marcador = new Marcador();7 }

smartphones SQL SQLi

trasteando twitter twitter4jVirtualBox wireshark xml xss

persistente

Sitios de interés

Android DevelopersAndroid.esBacktrackCommand Line Kung FuDragonJAREl Androide LibreExploits DatabaseFlu ProjectGran AngularHispasecMicrosiervosOpenLibraPentester.esPoesía BinariaSecurity By DefaultUn informático en el ladodel malWorld Wide WebConsistorium

En este código tenemos unas variables iniciales, que muy bien podían ser parte de los atributos dela clase puesto que no vamos a modificarlos en ningún momento, pero quería mantener laexplicación en códigos breves. La variable w será el ancho de cada una de las lineas divisorias. Serecomienda que sea par. La variable h es la altura de cada linea divisoria y gap es el espacio entreuna y otra linea. La variable ini define dónde comenzaremos a pintar. He elegido gap / 2 para suinicialización para que esté igual de separada por arriba que por abajo de los límites, pero es unaelección empírica. En el bucle vamos pintando cada uno de los tramos de la linea discontínuahasta llegar abajo. Sólo faltaría añadir la llamada a este método dentro del onDraw():

Aquí tenemos una captura de pantalla de la ejecución actual de la aplicación:

Lo siguiente que vamos a añadir es el pintado de los números de las puntuaciones de cadajugador. Además, vamos a usar una font propia, que no viene en el SDK de Android. Lo primeroserá buscar una, yo elegí la font Kelly Slab de Google Web Fonts. Ahora la incluimos en nuestraaplicación, para lo cual vamos a añadir un directorio llamado fonts en nuestro directorio assets, yahí incluimos nuestra recién descargada font:

Atención: ¡continuar leyendo antes de crear ningún código!

Lo siguiente será crear el método donde cargamos el tipo de letra, de la siguiente forma:

Con esto añadimos opciones al objeto Paint y pintamos los números del marcador. Si ahoramodificamos el método onDraw():

1 private void drawCenterLine(Canvas canvas, Paint paint) {2     int w = 6;3     int h = 20;4     int gap = 10;5     int ini = gap / 2; // por estetica, si no seria 06  7     for(int i = 0; i < this.getHeight() / (h+gap); i++) {8         canvas.drawRect(this.getWidth()/2 ‐ w/2, ini,9                 this.getWidth()/2 + w/2, ini + h, paint);10         ini += h + gap;11     }12 }

1 @Override2 public void onDraw(Canvas canvas) {3     Paint paint = new Paint();4     paint.setColor(Color.WHITE);5  6     canvas.drawColor(Color.BLACK);7     drawCenterLine(canvas, paint);8     canvas.drawRect(raquetaIzda.getRectElemento(), paint);9     canvas.drawRect(raquetaDcha.getRectElemento(), paint);10     canvas.drawRect(bola.getRectElemento(), paint);11 }

1 private void drawMarcador(Canvas canvas, Paint paint) {2     paint.setTextAlign(Align.CENTER);3     paint.setTypeface(Typeface.createFromAsset(this.getContext().getAssets(),4             "fonts/KellySlab‐Regular.ttf"));5     paint.setTextSize(80);6     paint.setAntiAlias(true);7     canvas.drawText(Integer.toString(marcador.getPuntosIzda()),8             getWidth() / 2 ‐ 80, 80, paint);9     canvas.drawText(Integer.toString(marcador.getPuntosDcha()),10             getWidth() / 2 + 80, 80, paint);11 }

1 @Override2 public void onDraw(Canvas canvas) {3     Paint paint = new Paint();4     paint.setColor(Color.WHITE);

Podemos ejecutar la aplicación y obtendremos una captura como la siguiente:

Si continuamos con el código actual, con lo de arriba explicado, hagamos una reflexión. Pongamosque la carga de esa font gastara 1KB de memoria por cada ejecución. Nuestos dispositivos tienen512MB de media, ¡así que eso no es un problema! Falso.Nuestra aplicación no ejecuta un número de frames por segundo fijo, sino que ejecuta todo lorápido que puede. Por ejemplo, la aplicación podría estar refrescando la pantalla a una velocidadde 60FPS, lo que conlleva una carga de la font en cada refresco con el consecuente tiempo decarga y el consecuente gasto de memoria. Si esto lo prolongamos con el tiempo… entonces nosvamos a quedar sin memoria (been there, done that).Por lo tanto, dado que esto no es un PC de mesa que suelen tener varios GB de memoria RAM…es de especial importancia no realizar la carga de ficheros sin necesidad (y otras operacionescostosas y que comen RAM). Si podemos hacerlas una sola vez, mejor.

Ahora sí, vamos a crear el código necesario y relativamente optimizado. Lo primero va a seragregar el siguiente atributo a la clase PongGameView:

Ahora el constructor de la clase será de la siguiente forma (puesto que el objeto Paint no semodifica en los demás métodos):

El método de pintado completo será el conjunto de lo siguiente:

5  6     canvas.drawColor(Color.BLACK);7     drawCenterLine(canvas, paint);8     drawMarcador(canvas, paint);9     canvas.drawRect(raquetaIzda.getRectElemento(), paint);10     canvas.drawRect(raquetaDcha.getRectElemento(), paint);11     canvas.drawRect(bola.getRectElemento(), paint);12 }

1 private Paint paint;

1 public PongGameView(Context context, AcelerometroPong acelerometro){

2     super(context);3     getHolder().addCallback(this);4  5     this.acelerometro = acelerometro;6     this.marcador = new Marcador();7  8     paint = new Paint();9     paint.setColor(Color.WHITE);10     paint.setTextAlign(Align.CENTER);11     paint.setTypeface(Typeface.createFromAsset(this.getContext().getAssets(),12             "fonts/KellySlab‐Regular.ttf"));13     paint.setTextSize(80);14     paint.setAntiAlias(true);15 }

1 @Override2 public void onDraw(Canvas canvas) {3     canvas.drawColor(Color.BLACK);4     drawCenterLine(canvas);5     drawMarcador(canvas);6     canvas.drawRect(raquetaIzda.getRectElemento(), paint);7     canvas.drawRect(raquetaDcha.getRectElemento(), paint);8     canvas.drawRect(bola.getRectElemento(), paint);9 }10  11 private void drawCenterLine(Canvas canvas) {12     int w = 6;13     int h = 20;14     int gap = 10;15     int ini = gap / 2; // por estetica, si no seria 016  17     for(int i = 0; i < this.getHeight() / (h+gap); i++) {18         canvas.drawRect(this.getWidth()/2 ‐ w/2, ini,19                 this.getWidth()/2 + w/2, ini + h, paint);20         ini += h + gap;21     }22 }23  24 private void drawMarcador(Canvas canvas) {25     canvas.drawText(Integer.toString(marcador.getPuntosIzda()),26             getWidth() / 2 ‐ 80, 80, paint);27     canvas.drawText(Integer.toString(marcador.getPuntosDcha()),

Ahora sí, tenemos un pintado inteligente intentando optimizar el uso de Paint.

El siguiente paso será hacer que, al tocar en uno de los laterales de la pantalla (izquierdo oderecho), se sume un punto al jugador en cuestión.

Comenzamos modificando el método rebota() de la Bola, de modo que ahora va a devolver unvalor. Devolverá -1 si la bola entró por la izquierda, 1 si entró por la derecha y 0 si sigue en lapantalla. Por tanto, este método ahora es:

De esta forma hemos modificado la primera parte del código del método, si ahora mismoejecutásemos la aplicación podríamos ver que la bola se cuela por los lados, pero no ocurre nada.Ahora es cuando haremos que ocurra ese algo al colarse.

Comenzamos añadiendo el Marcador a la clase BolaMoveThread, pues va a ser éste el que seencargue de modificarlo. El constructor con el nuevo atributo quedaría:

28             getWidth() / 2 + 80, 80, paint);29 }

1 public int rebota(int x, int y, Rect screen, Rect raquetaIzda,2         Rect raquetaDcha) {3     if(!puedoMover(x,y,screen)) {4         switch(direccion) {5         case DCHA_ARRIBA:6             if(origen.getY() ‐ y <= screen.top)7                 direccion = DCHA_ABAJO;8             else9                 return 1;10             break;11         case IZDA_ARRIBA:12             if(origen.getY() ‐ y <= screen.top)13                 direccion = IZDA_ABAJO;14             else15                 return ‐1;16             break;17         case IZDA_ABAJO:18             if(origen.getY() + alto + y >= screen.bottom)19                 direccion = IZDA_ARRIBA;20             else21                 return ‐1;22             break;23         case DCHA_ABAJO:24             if(origen.getY() + alto + y >= screen.bottom)25                 direccion = DCHA_ARRIBA;26             else27                 return 1;28             break;29         }30     }31  32     Rect raqueta = null;33     if(chocaraCon(x, y, raquetaIzda))34         raqueta = raquetaIzda;35     if(chocaraCon(x, y, raquetaDcha))36         raqueta = raquetaDcha;37     if(raqueta != null) {38         switch(direccion) {39         case DCHA_ARRIBA:40             direccion = (origen.getX()+ancho < raqueta.left) ?41                      IZDA_ARRIBA : DCHA_ABAJO;42             break;43         case IZDA_ARRIBA:44             direccion = (origen.getX() > raqueta.right) ?45                     DCHA_ARRIBA : IZDA_ABAJO;46             break;47         case IZDA_ABAJO:48             direccion = (origen.getX() > raqueta.right) ?

49                     IZDA_ARRIBA : DCHA_ABAJO;50             break;51         case DCHA_ABAJO:52             direccion = (origen.getX()+ancho < raqueta.left) ?53                     IZDA_ABAJO : DCHA_ARRIBA;54             break;55         }56     }57  58     return 0;59 }

1 private Marcador marcador;2  3 public BolaMoveThread(Bola bola, Raqueta izda, Raqueta dcha,4         Rect screen, Context context, Marcador marcador) {5     this.bola = bola;6     this.raquetaIzda = izda;7     this.raquetaDcha = dcha;8     this.screen = screen;9     this.run = false;10     this.speed = 1;11     this.v = (Vibrator)

Ahora vamos a modificar el método run() de esta clase. Queremos que, si el método bola.rebota()devuelve 0, haga lo que hace hasta ahora. Si devuelve -1 queremos que sume un punto a laraqueta derecha y si devuelve 1 que sume a la raqueta izquierda (recordamos que el signo indicapor qué lado entró). De esta forma, modificamos así:

Aquí hemos hecho varias cosas, expliquémoslas por partes.Lo primero que hemos hecho es añadir una variable private boolean punto; a los atributos de laclase, la cual se inicializa a false. Lo siguiente es añadir el primer bloque. Si punto == true, entoncesestamos diciendo que se ha marcado un punto ahora mismo. En este caso queremos que la bolano se mueva y que se quede dos segundos parada. En caso de haber acabado no volverá amoverse hasta que no volvamos al menú y juguemos de nuevo. En caso de no haber acabado,devolvemos la variable punto a false, lo que significa que quedan puntos. En cualquier casocontinuamos con la siguiente iteración sin pasar por el resto del código.

El resto del código modificado es un switch con el valor de salida del método bola.rebota(). Sidevuelve 0 ejecutamos el código que ya teníamos. Si devuelve otra cosa, añadimos un punto aljugador correspondiente, reiniciamos la posición de la bola y ponemos punto a true. El código dereinitBola() necesita que hayamos agregado dos nuevos atributos y los hayamos inicializado. Todolo necesario para reinitBola() se indica a continuación:

context.getSystemService(Context.VIBRATOR_SERVICE);12     this.mp = MediaPlayer.create(context, R.raw.pong);13     this.marcador = marcador;14 }

1 @Override2 public void run() {3     while(run) {4         try {5             Thread.sleep(5);6         } catch (InterruptedException e) {7             e.printStackTrace();8         }9         if(punto) {10             try {11                 Thread.sleep(2000);12             } catch (InterruptedException e) {13                 e.printStackTrace();14             }15             if(!marcador.acabado()) {16                 punto = false;17             }18             continue;19         }20  21         if(!bola.puedoMover(speed, speed, screen,22                 raquetaIzda.getRectElemento(),

raquetaDcha.getRectElemento())) {23             switch(bola.rebota(speed, speed, screen,24                     raquetaIzda.getRectElemento(),

raquetaDcha.getRectElemento())) {25             case 0:26                 if(PongOpciones.getInstance().soundEnabled())27                     mp.start();28                 if(bola.puedoMover(speed, speed, screen) &&29                         PongOpciones.getInstance().vibrationEnabled())30                         v.vibrate(50);31                 break;32             case ‐1:33                 marcador.addPuntoDcha();34                 reinitBola();35                 punto = true;36                 break;37             case 1:38                 marcador.addPuntoIzda();39                 reinitBola();40                 punto = true;41                 break;42             }

43         }44         bola.move(speed, speed);45     }46 }

1 private int bolaInitX;2 private int bolaInitY;3 private boolean punto;4  5 public BolaMoveThread(Bola bola, Raqueta izda, Raqueta dcha,6         Rect screen, Context context, Marcador marcador) {7     this.bola = bola;8     this.bolaInitX = bola.getOrigenX();9     this.bolaInitY = bola.getOrigenY();10     this.raquetaIzda = izda;11     this.raquetaDcha = dcha;12     this.screen = screen;13     this.run = false;14     this.speed = 1;15     this.v = (Vibrator)

Además hemos cambiado el primer Thread.sleep() a 5 para que vaya más rápido la bola conrespecto de cómo iba hasta ahora. Una pequeña y rápida partida jugando a propósito nos podríadar la siguiente imagen:

Ya tenemos el marcador completo, funcional y en pantalla. Sin embargo, si ahora mismo jugamosy volvemos al menú en mitad de una partida, no mantendremos nuestra puntuación guardada.Para ilustrar el paso de datos entre actividades vamos a hacer que se mantenga la puntuación.

Lo primero que tenemos que hacer es modificar el código en la clase PongvCActivity. Localizamosel método empiezaJuego(), que contiene este código:

Ahora lo modificamos para que sea:

De esta forma, en lugar de iniciar una Activity nueva, decimos que queremos que nos mande algode vuelta. Ahora tenemos que crear el lugar donde procesar ese algo. Para ello sobrecargamos elmétodo onActivityResult():

Lo siguiente que vamos a hacer es crear el código que devuelve las puntuaciones del marcador.Vamos a la clase PongJuego, y añadimos el siguiente atributo con la necesaria modificación delconstructor:

context.getSystemService(Context.VIBRATOR_SERVICE);16     this.mp = MediaPlayer.create(context, R.raw.pong);17     this.marcador = marcador;18     this.punto = false;19 }20  21 private void reinitBola() {22     bola.setOrigenX(bolaInitX);23     bola.setOrigenY(bolaInitY);24 }

1 private void empiezaJuego() {2     Intent juego = new Intent(this, PongJuego.class);3     this.startActivity(juego);4 }

1 private void empiezaJuego() {2     Intent juego = new Intent(this, PongJuego.class);3     this.startActivityForResult(juego, Activity.RESULT_OK);4 }

1 @Override2 public void onActivityResult(int requestCode, int resultCode,

Intent data) {3     super.onActivityResult(requestCode, resultCode, data);4     switch(requestCode) {5     case 1:6         if (resultCode == Activity.RESULT_OK) {7             // solo si el codigo devuelto es RESULT_OK, procesamos8         }9         break;10     }11 }

1 private AcelerometroPong acelerometro;2 private PongGameView view;3  4 @Override5 protected void onCreate(Bundle savedInstanceState) {6     super.onCreate(savedInstanceState);7     requestWindowFeature(Window.FEATURE_NO_TITLE);8     getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,9                         WindowManager.LayoutParams.FLAG_FULLSCREEN);10     acelerometro = new

AcelerometroPong(this.getApplicationContext());11     view = new PongGameView(this, acelerometro);12     setContentView(view);

Además, en PongGameView vamos a poner un nuevo método:

Así podremos consultar el marcador desde la actividad y poder devolver el valor. Para ello, enPongJuego crearemos el siguiente método:

Ahora sólo falta procesar estos datos devueltos. Lo primero será añadir dos nuevos atributos enPongvCActivity, con su inicialización:

Ahora volvemos al método onActivityResult() de la clase PongvCActivity, y añadimos el códigointerno a este if:

Solo falta hacer que se usen estos valores al arrancar la actividad de PongJuego. Para ello vamos amodificar la forma de llamarla en empiezaJuego(), incluyendo estos dos valores. Usamos la mismaidea de añadir extras, obteniendo este código:

Ahora falta usar estos valores en PongJuego, de modo que modificamos el constructor para quequede así:

Y modificar el constructor de PongGameView así:

13 }

1 public Marcador getMarcador() {2     return marcador;3 }

1 @Override2 public void onBackPressed() {3     Bundle bundle = new Bundle();4     bundle.putInt("PuntosIzda",

view.getMarcador().getPuntosIzda());5     bundle.putInt("PuntosDcha",

view.getMarcador().getPuntosDcha());6  7     Intent mIntent = new Intent();8     mIntent.putExtras(bundle);9     setResult(Activity.RESULT_OK, mIntent);10     super.onBackPressed();11 }

1 private int puntosIzdaIniciales = 0;2 private int puntosDchaIniciales = 0;

1 if (resultCode == Activity.RESULT_OK && data.getExtras() != null) {2     // solo si el codigo devuelto es RESULT_OK, procesamos3     puntosIzdaIniciales = data.getExtras().getInt("PuntosIzda");4     puntosDchaIniciales = data.getExtras().getInt("PuntosDcha");5 }

1 private void empiezaJuego() {2     Intent juego = new Intent(this, PongJuego.class);3     juego.putExtra("PuntosIzda", puntosIzdaIniciales);4     juego.putExtra("PuntosDcha", puntosDchaIniciales);5     this.startActivityForResult(juego, 1);6 }

1 @Override2 protected void onCreate(Bundle savedInstanceState) {3     super.onCreate(savedInstanceState);4     requestWindowFeature(Window.FEATURE_NO_TITLE);5     getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,6                         WindowManager.LayoutParams.FLAG_FULLSCREEN);7     acelerometro = new

AcelerometroPong(this.getApplicationContext());8  9     if(getIntent().getExtras() != null) {10         int puntosIzda =

getIntent().getExtras().getInt("PuntosIzda");11         int puntosDcha =

getIntent().getExtras().getInt("PuntosDcha");12         if(puntosIzda == Marcador.MAX_PUNT ||13                 puntosDcha == Marcador.MAX_PUNT)14             view = new PongGameView(this, acelerometro, 0, 0);15         else16             view = new PongGameView(this, acelerometro, puntosIzda,

puntosDcha);17     } else18         view = new PongGameView(this, acelerometro, 0, 0);19  20     setContentView(view);21 }

1 public PongGameView(Context context, AcelerometroPong acelerometro,2         int puntosIzda, int puntosDcha) {3     super(context);4     getHolder().addCallback(this);5  6     this.acelerometro = acelerometro;7     this.marcador = new Marcador(puntosIzda, puntosDcha);8  

Esto, lógicamente, requiere añadir un nuevo constructor al Marcador:

Ahora sí, podemos ejecutar nuestra aplicación y veremos que si volvemos al menú (por ejemplopara cambiar alguna opción) y luego volvemos a dar a Jugar, mantendremos la puntuación queteníamos acumulada. Llegados a este punto podría crearse un menú emergente que permitieraelegir continuar partida existente (si la hay) o iniciar una nueva. Sin embargo considero que essobrecargar sin necesidad la entrada, y sería una cosa a tener en cuenta si ésta fuera una aplicacióncomercial.

Evitar el bloqueo de pantalla

Si utilizamos la aplicación con el acelerómetro nos damos cuenta de que la pantalla acabará porapagarse eventualmente dependiendo de nuestras opciones del timeout para el bloqueo. Sinembargo, nosotros queremos que la pantalla no se bloquee automáticamente para nuestraaplicación si estamos usando el acelerómetro. Esto sin embargo puede ser malo para el consumode batería si un usuario deja la aplicación abierta.

Lo primero será agregar el siguiente atributo a la clase PongJuego e inicializarlo en el constructor:

Ahora añadimos el método onPause() y modificamos el método onResume():

Ahora sólo falta añadir el permiso de usar éste código en el AndroidManifest.xml, o si noobtendremos una excepción que matará nuestra aplicación. Para añadirlo abrimos el manifest, enla pestaña de Permissions. Pulsamos en Add > Uses Permission. En el cuadro derecho añadimosandroid.permission.WAKE_LOCK.Para comprobar que hemos hecho todo correctamente, iniciamos la aplicación vamos a Opciones,cambiamos el control para usar el acelerómetro, volvemos al menú y pulsamos en Jugar. Si todoestá bien la aplicación ejecutará el juego y podremos comprobar que no se apaga la pantalla(probar ésto teniendo un timeout bajo).

Última mejora

Las últimas cosas se dejan para el final, y si nos damos cuenta hasta ahora no hemos usado elbotón de Salir del menú. Queremos que cuando se pulse se cierre la aplicación.Vamos a la clase PongvCActivity, en el método onCreate(), en la parte que añadimos elonTouchListener() al botón de salir. Modificamos su código así:

Al llamar a la función finish() en una actividad lo que hacemos es cerrarla.

9     paint = new Paint();10     paint.setColor(Color.WHITE);11     paint.setTextAlign(Align.CENTER);12     paint.setTypeface(Typeface.createFromAsset(this.getContext().getAssets(),13             "fonts/KellySlab‐Regular.ttf"));14     paint.setTextSize(80);15     paint.setAntiAlias(true);16 }

1 public Marcador(int i, int d) {2     puntosIzda = i;3     puntosDcha = d;4 }

1 private WakeLock wl;2  3 @Override4 protected void onCreate(Bundle savedInstanceState) {5     super.onCreate(savedInstanceState);6     [...]7     setContentView(view);8     PowerManager pm = (PowerManager)

this.getSystemService(Context.POWER_SERVICE);9     wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, "Pong‐vC");10 }

1 @Override2 protected void onPause() {3     super.onPause();4     if(PongOpciones.getInstance().accelerometerEnabled())5         wl.release();6 }7  8 @Override9 protected void onResume() {10     super.onResume();11     acelerometro.register();12     if(PongOpciones.getInstance().accelerometerEnabled())13         wl.acquire();14 }

1 TextView exit = (TextView)findViewById(R.id.exit_button);2 exit.setOnClickListener(new OnClickListener() {3     @Override4     public void onClick(View v) {5         finish();6     }7 });

vidasConcurrentesSitio creado por meta y sshMan

Twittear 1 1 Follow

← Nessus en Backtrack 5: Instalación eintegración con Metasploit

Post-exploitation con WCE y Flu →

Hasta aquí la entrada de hoy. Con esta entrada podemos decir que hemos acabado el desarrollode la aplicación. La siguiente entrada consistirá en todos los pasos necesarios para publicar laaplicación, desde la creación de una cuenta de Google Checkout hasta la publicación.

Quedarían varias cosas que hacer en la aplicación, como por ejemplo la creación de una pequeñainteligencia artificial para la raqueta derecha, uso del multitáctil para poder jugar dos personastocando a la vez o localización de idioma para los botones del menú principal.Sin embargo sería sobrecargar demasiado esta serie de tutoriales puesto que estamos intentandohacer una pequeña introducción a Android con la excusa de crear un juego. Nuestra intención noes crear una aplicación con todo lo que tiene Android a la vez.

Como siempre podéis descargar el proyecto de Eclipse completo para poder importarlo y usarlopulsando aquí (MD5: 209d4e4393a45dadd15c18bfb22621c1).

Una vez más, ¡muchas gracias por vuestro tiempo!

0. Creando una aplicación de Android: la presentación1. Creando una aplicación de Android: primeros pasos

2. Creando una aplicación de Android: visión de conjunto y diseño del menú3. Creando una aplicación de Android: el juego y la lógica (parte 1)4. Creando una aplicación de Android: el juego y la lógica (parte 2)

5. Creando una aplicación de Android: mejoras (parte 1)6. Creando una aplicación de Android: mejoras (parte 2)

7. Creando una aplicación de Android: empaquetado y publicación

Esta entrada fue publicada en Android, Curso introducción Android, Programación y etiquetadacomo acelerometro, activity, aplicacion android, canvas, eclipse, graficos android, graphicsandroid, java, menu, subactivity, wake lock.

3 Respuestas a Creando una aplicación de Android: mejoras(parte 2)

1. alex dijo:30 abril, 2012 at 22:39

Gracias por el tuto, en todo caso como quedaria lo de la IA?

saludos

2. aeropostal tarifas dijo:17 abril, 2012 at 13:14

He encontrado muy buen material aqui. Lo agregue a mis favoritos para volver a visitar lapagina

3. Jumax9 dijo:15 septiembre, 2011 at 16:44

¡Muy buen tutorial, muchas gracias! ^____^!

Share0Like

Home Blog Síguenos Conócenos Contacto Escribe aquí para buscar...

← Post-exploitation con WCE y Flu Rogue AP con karmetasploit →

0. Creando una aplicación de Android: la presentación1. Creando una aplicación de Android: primeros pasos

2. Creando una aplicación de Android: visión de conjunto y diseño del menú3. Creando una aplicación de Android: el juego y la lógica (parte 1)4. Creando una aplicación de Android: el juego y la lógica (parte 2)

5. Creando una aplicación de Android: mejoras (parte 1)6. Creando una aplicación de Android: mejoras (parte 2)

7. Creando una aplicación de Android: empaquetado y publicación

Bienvenidos a la séptima y última parte de la serie de entradas en el ciclo Creando una aplicaciónde Android. Si aún no lo has hecho, comienza desde la primera entrada mostrada en el menúinmediatamente superior. Durante las anteriores entradas nos hemos centrado en el desarrollo dela aplicación paso a paso, y hemos llegado a tener la aplicación acabada. En esta entrada vamos acrear el paquete de la aplicación (es decir, el .apk preparado con todo), vamos a crear nuestracuenta de desarrollador para el Android Market y vamos a publicar la aplicación en él.¡Comencemos! Importante: esta entrada va a basarse en los códigos creados en las anterioresentradas del ciclo al que pertenece. Tienes disponible pinchando aquí (MD5:209d4e4393a45dadd15c18bfb22621c1) el proyecto de Eclipse con todo lo hecho hasta ahora, elcual puedes importar a tu Eclipse y comenzar a trabajar.

Preparación

La primera cosa que tenemos que hacer es preparar la aplicación para poder publicarla. Estoimplica crear el icono, poner el nombre de la aplicación y quitar todos los restos de trazas decódigo y debug. Para poder poner el nombre a la aplicación (el que saldrá debajo del icono) y elpropio icono, debemos ir al AndroidManifest.xml y localizar la etiqueta <application>, como aquímostramos:

Aquí estamos diciendo que el nombre de la aplicación aparece en el fichero strings.xml bajo elstring llamado app_name, y que el icono de la aplicación está en el directorio drawable.Comprobamos el fichero strings.xml y vemos:

Lo vamos a cambiar por:

La parte del nombrado de la aplicación ya está, ahora vamos con el icono. Es interesante consultarlas guías para el diseño de iconos de Android Developers para saber más acerca de los tamañosadecuados y diferentes resoluciones. En nuestro caso comenzamos creando un icono enPhotoshop, el cual guardamos con tamaño 72×72 píxeles y usando Guardar para web ydispositivos… marcando PNG-24 y sin ningún metadato (así, entre otras cosas, reducimos eltamaño). El resultado podría ser el siguiente, que es el que usaremos:

Lo siguiente que tenemos que hacer es incluirlo en nuestro proyecto. Para ello vamos a nuestraestructura de directorios del proyecto y pegamos el fichero en drawable-hdpi/icon_pong.png.Crearemos una versión de 48×48 píxeles y otra de 36×36 píxeles que guardaremos en drawable-mdpi y drawable-ldpi respectivamente. Importante: ¡el nombre del fichero debe ser el mismo!Como ya no vamos a necesitar los icon.png que están en estos directorios, vamos a eliminarlos. Esimportante no incluir cosas innecesarias en nuestras aplicaciones para ahorrar espacio. Al

Creando una aplicación de Android: empaquetadoy publicación

Publicado el 8 septiembre, 2011 por meta

1 <application android:icon="@drawable/icon"android:label="@string/app_name">

1 <string name="app_name">Pong</string>

1 <string name="app_name">Pong‐vC</string>

Categorías

AndroidCurso introducciónAndroidProgramaciónSeguridadSistemas Operativos

Entradas recientes

Automatizando lacreación de entornos dedesarrollo con VagrantColorshapes, el juego develocidad mental y figurasde colores para AndroideyeOS: Trabajando en lanubeIntegrando GoogleAnalytics en aplicacionesAndroidIntegrando Twitter enaplicaciones Android conSignPost y Twitter4J

Etiquetas

acelerometro activityalgoritmo androidaplicacion androidarbol backtrack bash BD

BEeF canvas contraseñas csrf

dns dns spoof eclipseexpresiones regularesgraficos androidgraphics android htc

desire intent javajavascript layout menu

metasploitmetasploitable mitmmysql oauth owasp

pentesting php seguridadpor defecto shodan

eliminarlos veremos que el AndroidManifest.xml se nos queja. Esto es porque nos resta cambiar laruta del icono. La etiqueta <application>entonces quedará así:

Ahora vamos a quitar todos los restos de trazas de código y el debug de la aplicación. Debemosquitar, en caso de tenerlo (no en el nuestro, pero quizá sí en futuras aplicaciones) la opciónandroid:debuggable=”true” de la etiqueta <application>. Debemos buscar todas las llamadas a laclase Log, para quitar toda traza que hayamos usado durante el desarrollo. Es también muyimportante buscar en nuestros códigos si hemos incluido por alguna razón información privadaque no deseemos que se vea, además de todo fichero que no sea necesario del proyecto yposibles ficheros de logging o backup que hayamos usado. Por último es de vital importancia laversión de la aplicación, y sería muy interesante echar un vistazo a la guía sobre versionado deAndroid Developers. Comenzando por la versión 1.0, por cada actualización que hagamosdeberíamos aumentarla. Las dos etiquetas importantes que tenemos que tener en cuenta sonandroid:versionCode y android:versionName en la etiqueta <manifest>. Debemos comprenderpara qué sirve cada una de las dos:

versionCode: este atributo es un número entero que típicamente comienza en 1 y que se vaaumentando por cada actualización. Representa el orden de la versión. Lo suyo es que, cadavez que hagamos una actualización, aumentemos este número en una unidad, ya sea poruna actualización grande o pequeña.versionName: este atributo es una cadena de texto que representa la versión tal y comodebe ser mostrada a los usuarios. Comenzando típicamente en 1.0 irá aumentando a 1.1,1.2… Si es una actualización menor, aumentamos el segundo número. Si es unaactualización grande aumentaremos el primero (para tener 2.0, luego 2.1…).

Por tanto, nuestra etiqueta <manifest>quedará así:

Firmar la aplicación

La última etapa previa a la publicación será el firmado de ésta. De nuevo, deberíamos consultar laguía sobre el firmado de Android Developers. Comenzamos haciendo click derecho sobre nuestroproyecto. Elegimos Android Tools > Export Signed Application Package. Lo siguiente serán unasucesión de ventanas en las que se nos guiará en el proceso. Lo primero que veremos será losiguiente:

Pulsamos en Next y veremos la siguiente ventana:

Elegimos Create new keystore, y elegimos el lugar con el botón Browse. Lo siguiente es escribir lacontraseña que usaremos para el fichero. Recomendamos usar una contraseña fuerte,posiblemente creada con algún generador de contraseñas. Una vez hemos rellenado los campos,damos a Next y vemos la siguiente ventana:

1 <application android:icon="@drawable/icon_pong"android:label="@string/app_name">

1 <manifestxmlns:android="http://schemas.android.com/apk/res/android"

2     package="com.vidasconcurrentes.pongvc" android:versionCode="1"3     android:versionName="1.0">

smartphones SQL SQLi

trasteando twitter twitter4jVirtualBox wireshark xml xss

persistente

Sitios de interés

Android DevelopersAndroid.esBacktrackCommand Line Kung FuDragonJAREl Androide LibreExploits DatabaseFlu ProjectGran AngularHispasecMicrosiervosOpenLibraPentester.esPoesía BinariaSecurity By DefaultUn informático en el ladodel malWorld Wide WebConsistorium

Aquí es donde tenemos que poner toda la información de la firma. Alias debe rellenarse con 8caracteres como máximo, y es el alias de la clave. La contraseña, por experiencia propia, debe serla misma que pusimos anteriormente. Lo siguiente es la validez, en años, que va a tener la clave(entre 1 y 1000). Los campos de la parte de abajo no son obligatorios, si bien debemos rellenar almenos uno para poder continuar. Una vez hayamos concluido con esta ventana, pulsamos Next yveremos esta otra:

Aquí elegimos la ruta donde queremos guardar nuestro .apk ya firmado. Una vez hayamosconcluido pulsamos en Finish y dejamos que Eclipse trabaje. Una vez haya completado el proceso(dependiendo del tamaño de la aplicación puede resultar un proceso relativamente largo),tendremos nuestro fichero de la clave y nuestro .apk firmado. Para comprobar que efectivamenteestá todo correcto, podemos guardar dicho .apk en nuestro dispositivo (por ejemplo por medio deUSB), y ejecutarlo con un Explorador de Ficheros (primero debemos desinstalarlo si lo tenemospor haber desarrollado en el dispositivo). Si hacemos esto, podremos ver que nuestro dispositivomuestra algo similar a lo siguiente:

Una vez instalada veremos que funciona exactamente igual que cuando lo hacíamos al desarrollaren Eclipse y usar Run as Android Application. ¡Ya estamos listos para publicar nuestra aplicación!

Crear nuestra cuenta de desarrollador del Android Market

Lo siguiente que vamos a hacer será crear nuestra cuenta de desarrollador. Efectuaremos un únicopago de 25$ (más o menos 18€) y eso nos permitirá publicar nuestras aplicaciones sin límite ennúmero. Siempre hay un pero, y en este caso es que si queremos llevarnos algún dinero por lasaplicaciones, Google se va a quedar con el 30% de lo que cueste la aplicación (este porcentajepuede cambiar si Google así lo desea en un futuro). Para hacer este tutorial lo más completoposible, vamos a ir por todos los pasos. Comenzamos visitando la página de publicación deaplicaciones para el Market. Si no estamos logueados en nuestra cuenta de Google, veremos losiguiente:

Meteremos los datos de nuestra cuenta de Google (la de gmail, para entendernos), y continuamoscon la siguiente pantalla:

En ella debemos leer el link que dice Acuerdo de distribución para desarrolladores de AndroidMarket. Una vez hemos rellenado los campos (posteriormente podrán editarse), continuamos conla siguiente pantalla:

Aquí simplemente damos a Continuar. El siguiente paso es poner la información para realizar elpago:

Entiendo que, en caso de ya haber comprado algo con Google Checkout, este paso se omitiría olos campos ya estarían completados. En cualquier caso, rellenamos el formulario (importantefijarse en el https:// de la barra de direcciones), y continuamos al siguiente paso:

En este paso nada más que veremos el resumen de la compra que vamos a hacer. Podemos elegirlas opciones que se nos muestran, y luego pulsamos en Realizar pedido ahora. Una vez estécompletado veremos lo siguiente, que confirma que nuestra compra se ha realizadocorrectamente:

En el cuadro amarillo hay un link que dice sitio de desarrolladores de Android Market, en el cualpulsaremos. El siguiente paso consiste en leer el acuerdo de licencia en español y continuar:

Si todo ha ido sin errores (no debería haberlos) veremos que nuestro registro en el Android Marketse ha aprobado y estaremos frente a nuestra Consola del desarrollador:

Con esto hemos acabado nuestro registro en el Android Market como desarrolladores.

Publicar nuestra aplicación

Después del registro, la siguiente parte será publicar nuestra aplicación en el Android Market. Paraello pulsamos en el enlace Subir aplicación de la ventana anterior. Veremos lo siguiente:

Elegimos la ruta de nuestro .apk firmado, y dejamos que se suba. Una vez subido nos hará unresumen de los datos con el código de versión y el nombre de la versión además de todos lospermisos que puedan tener que aceptar los usuarios. La siguiente parte consiste en rellenar loscampos (y también los opcionales si así lo deseamos). En la Especificación de detalles, esimportante que nos demos cuenta de que nos pide la información en inglés (descripción, título…).Podemos elegir añadir nuevos idiomas y poner la información en cada uno de ellos (inclusocambiar el idioma predeterminado). Es muy importante esta parte, ya que será la que vean losusuarios del Android Market. Dato importante: en caso de que queramos cobrar una cantidad pornuestras aplicaciones, lo primero que tenemos que hacer será configurar una cuenta bancaria queserá en la que recibiremos los pagos. Pulsa en el correspondiente enlace en la sección de Precios >¿Quieres vender aplicaciones? Configura una cuenta de comerciante en Google Checkout. Unavez hayamos completado toda la información (importante también el sitio web y el correo decontacto), procedemos a aceptar los Consentimientos de la parte baja de la web. Finalmenteguardamos nuestros progreso pulsando en Guardar en la parte superior derecha de los formulariosy comprobamos que tenemos correcto todas las opciones que hemos querido rellenar. En lapestaña Archivos APK tenemos nuestra aplicación, la cual necesitamos Activar. Una vez hechoesto sólo nos resta pulsar en Publicar, en la parte superior derecha. Seremos redirigidos a lasiguiente ventana:

Nos restaría comprobar que, efectivamente, nuestra aplicación está realmente publicada yaccesible. Se supone que la publicación en el Android Market es instantánea, pero no podremosencontrarla usando la herramienta de búsqueda del market hasta que no haya pasado un tiempo(quizá horas). Veamos las capturas:

Importante: es necesario que probemos que funciona todo correctamente antes de distribuirenlaces a diestro y siniestro. Y es necesario que desinstalemos nuestra versión previa (sea la queusamos diréctamente con Eclipse o desde el .apkfirmado).

Aplicar una actualización

Lo último que vamos a hacer es crear una actualización de nuestra aplicación, la cual aparecerápara todos los usuarios que la tengan instalada y se pedirá su descarga. Para ello modificaremos untrozo del código y aplicaremos todo lo necesario. Vamos a la clase PongGameView y localizamosla siguiente sección de código en el método onTouchEvent():

Lo que vamos a hacer es quitar este if y dejar lo que está dentro de él tal cual. Ahoramodificaremos nuestro AndroidManifest.xml para que se muestre una versión nueva. Comoexplicamos, modificaremos los atributos versionCode y versionName, quedando así:

Lo siguiente será volver a generar el .apk firmado. Para ello hacemos click derecho sobre elproyecto y elegimos Android Tools > Export Signed Application Package. En esta ocasiónelegiremos el keystore que ya generamos previamente, y pondremos la contraseña que usamospara generarlo. Elegimos el alias que sale del menú desplegable y ponemos la contraseña.Continuamos hasta generar de nuevo el .apk. Ahora volvemos a nuestra Consola del desarrollador,y seleccionamos nuestra aplicación pulsando en el nombre. Ahora vamos a la pestaña ArchivosAPK, y hacemos click en Subir APK. Elegimos la ruta en la que se encuentra éste y pulsamos enPublicar. Ahora tendremos dos APK subidos, uno de la versión 1.0 y otra de la 1.1, por lo quetenemos que activar la versión 1.1 y desactivar la 1.0 que ya no vale. Pulsamos en Guardar y yatenemos la versión 1.1 en el Android Market. Sencillo, ¿no? Nuestros usuarios recibirán en susdispositivos el aviso de que tienen que actualizar la aplicación, pero eso ya no es cosa nuestra.

Con esta entrada hemos llegado al final de nuestro humilde curso de introducción a laprogramación para dispositivos móviles Android. A lo largo de siete entradas extensas y conexplicaciones detalladas hemos aprendido a usar las herramientas necesarias para el desarrollo.Entre otras de las cosas aprendidas hemos visto cómo instalar las herramientas necesarias, cómocrear nuevas Actividades y cómo ejecutarlas a través de Intents, cómo mandar información entreActividades, cómo usar la vibración o el acelerómetro… y todo ello a través del desarrollo de unapequeña aplicación como es un juego sencillo, que nos ha ayudado a no notar la pesadez deaprender todas estas cosas sin unirlas. Espero sinceramente que hayáis encontrado este cursointroductorio lo más interesante posible, y que hayáis aprendido con él tanto como yo aprendíhaciéndolo. Un saludo a todos los lectores que habéis seguido el desarrollo y muchas gracias pordedicarle el tiempo que requiere. ¡Que tengáis buen desarrollo de vuestras propias aplicaciones!Podéis visitar el Android Market y descargar nuestra aplicación pulsando aquí. También podéis vercómo habrá quedado la aplicación:

1 if(!PongOpciones.getInstance().accelerometerEnabled()) {2     .......3 }

1 <manifestxmlns:android="http://schemas.android.com/apk/res/android"

2     package="com.vidasconcurrentes.pongvc" android:versionCode="2"3     android:versionName="1.1">