En este video te explicamos en detalle todo el proceso para publicar una Aplicación Android…
Desarrollo App ejemplo en Android Wear: cuenta de usuario
5.
Desarrollo App ejemplo en Android Wear: cuenta de usuario
Vamos a detallar los elementos y el código de la aplicación sobre Android Wear que ya presentamos en un video anterior de esta serie. Como explicamos, esta App nos sirve para mostrar cómo utilizar el sistema de tarjetas en un smartwatch (adaptadas tanto a un diseño redondo como cuadrado), de forma que el usuario pueda navegar entre pantallas para configurar una cuenta de usuario y en el que se le mostrará una ventana de confirmación al final del proceso.
Para realizar dicha tarea, en primer lugar se deberán enumerar los elementos necesarios, tanto para la realización del proyecto principal, como para el funcionamiento de las diferentes vistas que intervienen en la aplicación:
Dos imágenes de la App. En el video del proyecto puedes ver un demo de la misma
Proyecto en Android Studio denominado «CuentaUsuario», formado por las siguientes clases y layouts (módulo «wear»):
- Clase SplashScreen, que herede de la clase base Activity, encargada de lanzar una pantalla de presentación al iniciar la aplicación.
- Clase CuentaUsuario, que herede de la clase base Activity, cuya tarea principal será la de seleccionar la cuenta de usuario a configurar.
- Clase PerfilUsuario, que herede de la clase base Activity, encargada de mostrar los perfiles disponibles para la configuración de la cuenta de usuario seleccionada.
- Clase PasswordCuenta, que herede de la clase base Activity, que permita asignar una contraseña a la cuenta de usuario seleccionada.
- Clase NuevoUsuario, que herede de la clase base Activity, que implemente la interfaz
DelayedConfirmationListener
, que proporciona los mecanismos necesarios para informar al usuario de la realización de una tarea. - Clase Usuario, que declara los métodos de acceso getters y setters, encargados de almacenar y devolver valores de usuario, perfil y contraseña de la cuenta configurada.
- Layout
splash_screen.xml
, que define un componente de tipo ImageView, con la imagen representativa de la aplicación. - Layout
activity_main.xml
, formado por tres vistas personalizadas que proporcionan un diseño único para ambos formatos de pantalla (clasesBoxInsetLayout
,CardScrollView
yCardFrame
), formado por un componente Spinner para la selección de la cuenta de usuario a configurar. - Layout
activity_perfil_usuario.xml
, al igual que el layout anterior, está formado por tres vistas personalizadas, además de un componente de tipo Spinner que mostrará los perfiles de usuario disponibles. - Layout
activity_password.xml
, cuya principal características será la definición de un componente ListView a modo de teclado numérico. Este layout permite la asignación de una contraseña a la cuenta configurada. - Layout
nuevo_usuario.xml
, que define una vista personalizada que mostrará un mensaje de confirmación (además de un temporizador que permita cancelar la acción), indicando que la tarea realizada se ha completado correctamente. Al mostrar dicha confirmación, se añadirán los datos seleccionados al componente ListView declarado. - Layout
spinner.xml
, que define un diseño único para asignar al adaptador del componente de tipo selección Spinner. Estaría formado por un componente TextView. - Layout
listview.xml
, formado por un componente de tipo TextView, que mostrará la configuración seleccionada por el usuario.
Estructura del proyecto
Lógica de navegación
En la siguiente imagen se mostrará la lógica de navegación del proyecto a describir, mostrando de izquierda a derecha, el proceso de configuración de una cuenta de usuario, además de su visualización en pantallas con forma redonda y cuadrada:
- Pantalla de presentación inicial.
- Selección de la cuenta de usuario, a partir de un componente de tipo selección Spinner en modo diálogo.
- Selección del tipo de perfil de la cuenta de usuario a partir de una lista en un componente Spinner.
- Pantalla para establecer una contraseña numérica, que no podrá superar los 6 caracteres.
- Lógica de creación de usuario, con mensaje de confirmación.
Documentación código fuente
A continuación, se describirá el código fuente del proyecto, destacando aquellas partes diferenciadoras entre las clases y Activities declaradas. Como siempre, puedes descargar todo el código al final de este tutorial.
Al definirse estructuras similares de navegación entre Activity y Activity (clases CuentaUsuario.java
, PerfilUsuario.java
y PasswordCuenta.java
), sólo se abordará la construcción de dicha funcionalidad en la primera clase a tratar, permitiendo describir sólo aquellas partes no comunes en el resto de clases:
CuentaUsuario\wear\src\main\java\com\academiaandroid\cuentausuario\CuentaUsuario.java
- Clase que hereda de la clase base Activity, cuya tarea principal será la de
seleccionar la cuenta de usuario a configurar:
12public class CuentaUsuario extends Activity{ - Se asigna el componente declarado a nivel de layout a la clase CardScrollView, además de alinear la tarjeta al centro de la línea vertical que separa la pantalla:
123scrollTarjeta = (CardScrollView)findViewById(R.id.card_scroll_view_cuenta);scrollTarjeta.setCardGravity(Gravity.CENTER_VERTICAL); - También comentar que se implementa el evento que controlará la pulsación de la tarjeta para mostrar la siguiente Activity con los datos de la cuenta de usuario seleccionada:
123456789scrollTarjeta.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Intent intent = new Intent(CuentaUsuario.this,PerfilUsuario.class);intent.putExtra("usuario",usuario.getUsuario());startActivity(intent);}});
CuentaUsuario\wear\src\main\java\com\academiaandroid\cuentausuario\PerfilUsuario.java
Al tratarse de una estructura muy similar a la de la anterior clase (CuentaUsuario.java), es recomendable tomar como referencia dicha clase, ya que presentan un funcionamiento casi idéntico.
CuentaUsuario\wear\src\main\java\com\academiaandroid\cuentausuario\PasswordCuenta.java
- Clase que hereda de la clase base Activity,
que permitirá asignar una contraseña a la cuenta de usuario seleccionada:
12public class PasswordCuenta extends Activity { - Se asignan los recursos a nivel de layout con las clases declaradas:
123456scrollPassword = (CardScrollView) findViewById(R.id.card_scroll_view_password);edPassword = (EditText) findViewById(R.id.edPass);tvUsuario = (TextView) findViewById(R.id.tvUsuario);tvPerfilPass = (TextView) findViewById(R.id.tvPerfilPass);listTeclado = (ListView) findViewById(android.R.id.list); - Se define el evento encargado de controlar la selección de un ítem de la lista, añadiendo su contenido (teclado numérico) al campo EditText:
1234567listTeclado.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {edPassword.setText(edPassword.getText() + parent.getItemAtPosition(position).toString());}}); - Además se declara el evento
onClick()
asociado a un componente EditText, que permitirá borrar la contraseña introducida:
12345public void borrarPassword(View view){edPassword.setText("");}
CuentaUsuario\wear\src\main\java\com\academiaandroid\cuentausuario\NuevoUsuario.java
- Clase que hereda de la clase base Activity, e implementa la interfaz DelayedConfirmationListener, que proporciona los mecanismos necesarios para informar al usuario de la realización de una tarea:
12public class NuevoUsuario extends Activity implements DelayedConfirmationView.DelayedConfirmationListener{ - Se asigna el componente declarado a nivel de layout a la clase DelayedConfirmationView:
12mDelayedView = (DelayedConfirmationView) findViewById(R.id.delayed_confirm); - Se establece un temporizador de 5 segundos para la cancelación de la tarea por parte del usuario:
12mDelayedView.setTotalTimeMs(5000); - Se lanza la tarea al mostrar la nueva Activity, ya que se invoca al método
start()
dentro deonCreate()
:
12mDelayedView.start(); - Para finalizar se sobrescriben los métodos
onTimerFinished()
yonTimerSelected()
, encargados de implementar la acción a realizar transcurrido el tiempo establecido, o en caso contrario de la cancelación de la tarea:
123456789101112131415161718@Overridepublic void onTimerFinished (View view) {datosCuenta.add(datosUsuario);adapter = new ArrayAdapter<String>(this,R.layout.listview, datosCuenta);Intent intent = new Intent(this, ConfirmationActivity.class);intent.putExtra(ConfirmationActivity.EXTRA_ANIMATION_TYPE, ConfirmationActivity.SUCCESS_ANIMATION);intent.putExtra(ConfirmationActivity.EXTRA_MESSAGE, getString(R.string.confirmar_nuevo_usuario));startActivity(intent);listUsuarios.setAdapter(adapter);}@Overridepublic void onTimerSelected(View view) {Toast.makeText(this,"Acción cancelada",5000).show();this.finish();mDelayedView.reset();}
CuentaUsuario\wear\src\main\res\layout\activity_main.xml
- Layout que define tres vistas personalizadas, formada por una principal a partir de la clase
BoxInsetLayout
, que establecerá un diseño único para la aplicación, y anidadas dentro de esta se encontrarían la vistaCardScrollView
, encargada de envolver a la vistaCardFrame
para poder navegar entre tarjetas. Este layout estaría formado principalmente por un componente Spinner que mostrará los elementos disponibles para la configuración:
123456789101112131415161718192021222324252627282930313233343536373839404142<?xml version="1.0" encoding="utf-8"?><android.support.wearable.view.BoxInsetLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="fill_parent"android:layout_height="fill_parent"android:paddingTop="35dp"android:background="@drawable/back_logo"><android.support.wearable.view.CardScrollViewandroid:id = "@+id/card_scroll_view_cuenta"android:layout_height="match_parent"android:layout_width="match_parent"><android.support.wearable.view.CardFrameandroid:layout_height="fill_parent"android:layout_width="fill_parent" ><FrameLayoutandroid:id="@+id/frame_layout"android:layout_width="match_parent"android:layout_height="match_parent"app:layout_box="all"><TableLayout...[...]<TableRow...<Spinnerandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/spUsuario"android:spinnerMode="dialog" /></TableRow></TableLayout></FrameLayout></android.support.wearable.view.CardFrame></android.support.wearable.view.CardScrollView></android.support.wearable.view.BoxInsetLayout>
CuentaUsuario\wear\src\main\res\layout\activity_perfil_usuario.xml
- Al igual que el anterior layout, define tres vistas personalizadas, pero con la diferencia de que se define un componente de tipo TextView que recogerá el valor seleccionado en la configuración anterior, además de un componente de tipo Spinner que mostrará los perfiles de usuario predefinidos:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354<?xml version="1.0" encoding="utf-8"?><android.support.wearable.view.BoxInsetLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="fill_parent"android:layout_height="fill_parent"android:paddingTop="35dp"android:background="@drawable/back_logo"><android.support.wearable.view.CardScrollViewandroid:id="@+id/card_scroll_view_cuenta"android:layout_height="match_parent"android:layout_width="match_parent"><android.support.wearable.view.CardFrameandroid:layout_height="fill_parent"android:layout_width="fill_parent"><FrameLayoutandroid:id="@+id/frame_layout"android:layout_width="match_parent"android:layout_height="match_parent"app:layout_box="all"><TableLayout...[...]<TableRow...[...]<TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:textAppearance="@style/TextView.Small"android:text="@string/total"android:id="@+id/tvUsuarioPerfil"android:textColor="#ffe25521" /></TableRow><TableRow...<Spinnerandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/spUsuario"android:spinnerMode="dialog" /></TableRow></TableLayout></FrameLayout></android.support.wearable.view.CardFrame></android.support.wearable.view.CardScrollView></android.support.wearable.view.BoxInsetLayout>
CuentaUsuario\wear\src\main\res\layout\activity_password.xml
- Estructura similar a los layouts descritos hasta el momento, con la salvedad de que se implementa un componente de tipo EditText (tipo de entrada numérico, password y no superior a 6 caracteres) que recogerá la contraseña introducida por el usuario, y un componente de tipo selección ListView, que funcionará a modo de teclado numérico para introducir dicha contraseña:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566<?xml version="1.0" encoding="utf-8"?><android.support.wearable.view.BoxInsetLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="fill_parent"android:layout_height="fill_parent"android:paddingTop="10dp"android:background="@drawable/back_logo"><android.support.wearable.view.CardScrollViewandroid:id="@+id/card_scroll_view_password"android:layout_height="match_parent"android:layout_width="match_parent"><android.support.wearable.view.CardFrameandroid:layout_height="fill_parent"android:layout_width="fill_parent"><FrameLayoutandroid:id="@+id/frame_layout_conf"android:layout_width="fill_parent"android:layout_height="fill_parent"app:layout_box="all"><TableLayout...[...]<TableRow...[...]<EditTextandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/edPass"android:textColor="#ffa9e297"android:background="#ca42a0e2"android:layout_span="0"android:textSize="@dimen/ednumero"android:hint="Password"android:maxLength="6"android:inputType="numberPassword"android:autoText="false"android:onClick="borrarPassword" /></TableRow></TableLayout><TableLayout...[...]<TableRow...[...]<ListViewandroid:layout_width="80dp"android:layout_height="80dp"android:id="@android:id/list"android:layout_marginTop="10sp"android:layout_marginLeft="20dp"android:layout_weight="1" /></TableRow></TableLayout></FrameLayout></android.support.wearable.view.CardFrame></android.support.wearable.view.CardScrollView></android.support.wearable.view.BoxInsetLayout>
CuentaUsuario\wear\src\main\res\layout\nuevo_usuario.xml
- Layout que al igual que los comentados anteriormente, presenta una estructura principal formada por tres vistas a partir de las clases
BoxInsetLayout
,CardScrollView
yCardFrame
, pero con la principal diferencia de que se incluye a nivel de diseño el elementoDelayedConfirmationView
, al que se le asigna una imagen para la cancelación de una acción realizada por el usuario. Además, se establecen las propiedades de radio y anchura de borde, para simular un temporizador, que se declara e inicializa de manera programática:
12345678910111213141516171819202122232425262728293031323334353637<?xml version="1.0" encoding="utf-8"?><android.support.wearable.view.BoxInsetLayout...<android.support.wearable.view.CardScrollView...<android.support.wearable.view.CardFrame...<FrameLayout...<TableLayout...[...]<TableRow...[...]<ListViewandroid:layout_width="wrap_content"android:layout_height="30dp"android:id="@android:id/list" /></TableRow><TableRow...<android.support.wearable.view.DelayedConfirmationViewandroid:id="@+id/delayed_confirm"android:layout_width="140dp"android:layout_height="wrap_content"android:src="@drawable/cancelar_28"app:circle_border_color="@color/red"app:circle_border_width="5dp"app:circle_radius="22dp"android:layout_weight="1"android:layout_span="0"></android.support.wearable.view.DelayedConfirmationView></TableRow></TableLayout></FrameLayout></android.support.wearable.view.CardFrame></android.support.wearable.view.CardScrollView></android.support.wearable.view.BoxInsetLayout>
CuentaUsuario\wear\src\main\res\layout\spinner.xml
CuentaUsuario\wear\src\main\res\layout\listview.xml
- Se crean dos recursos xml de tipo Drawable, que proporcionan una vista personalizada para tanto listar el nombre y perfil de la cuenta de usuario (componente Spinner), como mostrar la configuración de cuenta creada (componente ListView). Dichos recursos estarán formados cada uno por un componente de tipo TextView:
spinner.xml
1 2 3 4 5 6 7 8 9 10 11 12 |
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="012345678" android:textColor="#ff000000" android:id="@+id/textView" android:background="#ffffffff" android:gravity="center_vertical|center_horizontal" android:paddingLeft="10dp" android:paddingTop="10dp"/> |
listview.xml
1 2 3 4 5 6 7 8 9 10 11 12 |
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="30dp" android:text="012345678" android:textColor="#ff000000" android:id="@+id/textView" android:background="#ffc4ff97" android:gravity="center_vertical|center_horizontal" android:paddingTop="15dp" android:textSize="8dp" /> |
Nota: Al tratarse de una parte común en proyectos utilizados anteriormente, la clase SplashScreen.java
y su layout splash_screen.xml
no se describen dentro del apartado «Documentación de código fuente». También comentar, que para establecer un diseño único dentro de cada layout, es necesario establecer como elemento principal del resto de vistas personalizadas la clase BoxInsetLayout
.
Dependencias declaradas en el Proyecto
Para este proyecto ha sido necesario añadir las siguientes dependencias para soportar dispositivos wearables, además de poder utilizar los servicios de Google Play (archivo «build.gradle» del módulo «wear»):
1 2 3 4 5 6 |
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.google.android.support:wearable:1.1.0' compile 'com.google.android.gms:play-services-wearable:6.5.87' } |
AndroidManifest.xml
Es necesario declarar dentro del elemento <application...
la Activity ConfirmationActivity
, para acceder a las animaciones de confirmación:
1 2 3 4 5 6 7 8 9 10 |
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.academiaandroid.cuentausuario" > <application... [...] <activity android:name="android.support.wearable.activity.ConfirmationActivity"> </activity> </application> </manifest> |