En este video te explicamos en detalle todo el proceso para publicar una Aplicación Android…
Proyecto: diseños para Smartwatches Android Wear
4.
Proyecto: diseños para Smartwatches Android Wear
En este tutorial, desarrollaremos un proyecto con Android Studio, que nos servirá para explicar la asignación de diferentes diseños, acorde a las características de las pantallas de los dispositivos smartwatches.
En este ejercicio práctico, mostraremos el cambio de diseño en tiempo de ejecución, comprobando la forma del dispositivo y estableciendo el layout (formato) más acorde a la pantalla. Este proyecto (módulo «wear») permitirá la realización de llamadas desde el dispositivo Android Wear, vinculado con el dispositivo móvil.
Para realizar esta tarea, en primer lugar enumeraremos los elementos necesarios, tanto para la realización del proyecto principal, como para el funcionamiento de la lógica de asignación de cada layout diseñado:
Pantalla de presentación de la aplicación.
Menú principal de la aplicación.
Muestra el desplegable con lista de contactos almacenados.
Lista de contactos disponibles.
Proyecto en Android Studio denominado «AppSmartWatches»
Este proyecto está formado por las siguientes clases y layouts:
- Clase SplashScreen, que herede de la clase base Activity, encargada de lanzar una pantalla de presentación al iniciar la aplicación, proporcionando una mayor inmersión del usuario.
- Clase MainActivity, que herede de la clase base Activity, cuya tarea principal será la gestión de llamadas, ya sea introduciendo directamente el número deseado, o a partir de un listado de contactos almacenados.
- Layout
activity_main.xml
, formado por una vista personalizada denominadaWatchViewStub
, encargada de asignar el diseño más apropiado en función de la forma de la pantalla. - Layout
activity_splash_screen.xml
, que al igual que el layoutactivity_main.xml
, define una vista personalizada a partir del componenteWatchViewStub
. - Layout
rect_activity_main.xml
, diseñado para pantallas con forma cuadrada, define los siguientes componentes:- Componente TabHost que permitirá crear una interfaz de usuario basado en pestañas (Llamar y Contacto).
- Componente de tipo EditText para introducir el número de teléfono al que se va a llamar.
- 3 componentes de tipo ImageButton, encargados de, borrar el número de teléfono introducido, efectuar y cancelar una llamada.
- 10 componentes de tipo Button, que proporcionan la lógica de marcación de un teclado numérico.
- Componente de tipo ImageView que mostrará un icono asociado a contactos.
- Componente de tipo selección Spinner, que mostrará los datos de contactos almacenados (números de teléfono).
- Layout
rect_splash_screen.xml
, que define un componente de tipo ImageView, para el diseño sobre pantallas con forma cuadrada. - Layout
round_activity_main.xml
, define el mismo número de componentes que el layoutrect_activity_main.xml
, con la salvedad de que al tratarse de un diseño destinado a pantallas redondas, se asigna un nuevo estilo a los botones del teclado numérico, con la idea de ocupar el menor espacio posible. - Layout
round_splash_screen.xml
, al igual que el layoutrect_splash_screen.xml
, define un componente de tipo ImageView, pero en este caso el diseño se asignará a pantallas con forma redonda. - 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.
Estructura del proyecto
Lógica de navegación de la Aplicación
1. Pantalla de presentación inicial.
2. Pestaña principal con teclado numérico para realización de llamadas.
3. Pestaña secundaria para acceso a listado telefónico.
4. Selección de número de contacto almacenado.
Documentación código fuente
Como es habitual, puedes descargar todo el código del proyecto al final de este tutorial
AppSmartWatches\wear\src\main\java\com\academiaandroid\appsmartwatches\MainActivity.java
- Se declara e inicializa la clase
WatchViewStub, para almacenar los dos diseños definidos. Además permitirá incorporar uno de los dos diseños creados en función de la forma de la pantalla del dispositivo:
123456789@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);final WatchViewStub stub = new WatchViewStub(this);stub.setRectLayout(R.layout.round_activity_main);stub.setRoundLayout(R.layout.rect_activity_main);[...] - Dentro del método
onCreate(), se implementa el evento encargado de ser lanzado cuando el diseño interno apropiado haya sido incorporado:
123456stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {@Overridepublic void onLayoutInflated(WatchViewStub stub) {[...] - Se definen los eventos encargados de controlar las pulsaciones de los diferentes botones asociados al teclado numérico para la realización de llamadas:
1234567btn0.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {edNumero.setText(edNumero.getText() + "0");}}); - Se inicializa la clase ArrayAdapter, que reciben entre sus argumentos un layout personalizado. A continuación, se invoca al método
setAdapter() para construir la lista de contactos:
123adapter = new ArrayAdapter<String>(MainActivity.this, R.layout.spinner, contactos);spContactos.setAdapter(adapter); - Se asigna la clase
TabHost declarada con su componente a nivel de layout. Posteriormente, se crean las pestañas «Llamar» y «Contacto», mostrando la primera de ellas el teclado numérico junto con los botones de realizar y cancelar llamada, y la segunda pestaña, los teléfonos de contacto almacenados en un componente de tipo selección Spinner:
123456789101112131415161718192021tabHost = (TabHost)findViewById(R.id.tabHost);tabHost.setup();TabHost.TabSpec tSpec = tabHost.newTabSpec("Llamar");tSpec.setContent(R.id.tabLlamada);tSpec.setIndicator("Llamar");tabHost.addTab(tSpec);tSpec = tabHost.newTabSpec("Contacto");tSpec.setContent(R.id.tabContacto);tSpec.setIndicator("Contacto");tabHost.addTab(tSpec);/*Se establece como contenido inicial de la aplicación la pestaña "Llamar".*/tabHost.setCurrentTab(0);[...]});}}); - Por último, antes de cerrar el método
onCreate(), se infla el layout en la Activity principal, con el layout más adecuado para la forma del dispositivo. Para ello, se invoca al método
setContentView(), y se indica como parámetro la vista a inflar:
123setContentView(stub);}//Llave de cierre de método onCreate(). - Para finalizar con la clase
MainActivity, se declaran los métodos
realizarLlamada() y
finalizarLlamada(), que permitirán, por un lado lanzar un intent con la acción de marcar un número de teléfono, invocando al método
setData(), que recibirá el número como argumento, y por otro lado, invocar al método
finish() para finalizar la Activity en caso de cancelar la llamada:
12345678910111213141516171819private void realizarLlamada(String telf) {try {intentLlamada = new Intent(Intent.ACTION_DIAL);intentLlamada.setData(Uri.parse(telf));startActivity(intentLlamada);} catch (Exception ex) {Toast.makeText(this,"No ha sido posible contactar con el número: " + edNumero.getText().toString(),Toast.LENGTH_SHORT).show();}}public void finalizarLlamada() {try{this.finish();}catch(Exception ex){Toast.makeText(this,"Error al finalizar llamada: " + ex.getMessage(),Toast.LENGTH_SHORT).show();}}
AppSmartWatches\wear\src\main\res\layout\activity_main.xml
- Layout que implementa una vista personalizada a partir de la clase
WatchViewStub. Este tipo de vista declara los dos diseños creados para diferentes formas, en lo que se refiere a la pantalla del dispositivo:
1234567891011121314<?xml version="1.0" encoding="utf-8"?><android.support.wearable.view.WatchViewStubxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/watch_view_stub"android:layout_width="match_parent"android:layout_height="match_parent"<!--Se asignan los valores de los diseños creados a sus respectivos atributos.-->app:rectLayout="@layout/rect_activity_main"app:roundLayout="@layout/round_activity_main"tools:context=".MainActivity"tools:deviceIds="wear"/>
AppSmartWatches\wear\src\main\res\layout\rect_activity_main.xml
- Layout que define el diseño para dispositivos con la pantalla cuadrada, donde destacan principalmente el componente de tipo TabHost, que permitirá al usuario moverse entre dos pestañas para la realización de llamadas o la selección de contactos telefónicos almacenados, y el componente de tipo selección Spinner, que mostrará la lista indicada anteriormente. Para acceder a este layout se debe establecer el atributo
android:id="@+id/rect_activity_layout"
:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"android:id="@+id/rect_activity_layout"tools:deviceIds="wear_square"><TabHostandroid:layout_width="fill_parent"android:layout_height="fill_parent"android:id="@+id/tabHost"android:layout_column="0"android:focusableInTouchMode="true"><LinearLayoutandroid:layout_width="fill_parent"android:layout_height="fill_parent"android:orientation="vertical"android:id="@+id/linearLayout"><TabWidgetandroid:id="@android:id/tabs"android:layout_width="fill_parent"android:layout_height="18dp"android:background="#e91bbefa"android:showDividers="middle"android:dividerPadding="2dp"></TabWidget><FrameLayoutandroid:id="@android:id/tabcontent"android:layout_width="fill_parent"android:layout_height="fill_parent"android:layout_weight="1"android:background="#FFFFFF"><LinearLayoutandroid:id="@+id/tabLlamada"android:layout_width="fill_parent"android:layout_height="fill_parent"android:orientation="vertical"android:background="#000000"android:showDividers="middle"><TableLayoutandroid:layout_width="fill_parent"android:layout_height="fill_parent"><TableRowandroid:layout_width="0dip"android:layout_height="wrap_content"android:layout_weight="1"><EditTextandroid:layout_width="140dp"android:layout_height="35dp"android:inputType="number"tools:text="012345678"android:ems="10"android:id="@+id/edNumero"android:layout_weight="1" /><ImageButtonandroid:layout_width="0dip"android:layout_height="wrap_content"android:id="@+id/imgbtnBorrar"android:layout_weight="2"android:src="@drawable/borrar_white"android:background="#54071829" /></TableRow><TableRowandroid:layout_width="0dip"android:layout_height="wrap_content"android:layout_weight="1"><Buttonstyle="?android:attr/buttonStyleSmall"android:layout_width="0dip"android:layout_height="wrap_content"android:text="@string/uno"android:id="@+id/btn1"android:layout_weight="1" />[...]</TableRow><TableRowandroid:layout_width="0dip"android:layout_height="wrap_content"android:layout_weight="1">[...]<ImageButtonandroid:layout_width="0dip"android:layout_height="wrap_content"android:id="@+id/imgbtnLlamar"android:src="@drawable/icono_llamar_24"android:background="#ff4fff3b"android:layout_weight="1"style="?android:attr/buttonStyleSmall" /><ImageButtonstyle="?android:attr/buttonStyleSmall"android:layout_width="0dip"android:layout_height="wrap_content"android:text="Colgar"android:id="@+id/imgbtnColgarLlamada"android:src="@drawable/icono_colgar_24"android:background="#ffff5a5f"android:layout_weight="1" /></TableRow></TableLayout></LinearLayout><LinearLayoutandroid:id="@+id/tabContacto"android:layout_width="fill_parent"android:layout_height="fill_parent"android:orientation="vertical"android:background="#FFFFFF"android:showDividers="middle"><TableLayoutandroid:layout_width="fill_parent"android:layout_height="fill_parent"><TableRowandroid:layout_width="fill_parent"android:layout_height="fill_parent"><ImageViewandroid:layout_width="0dp"android:layout_height="30dp"android:id="@+id/imageView3"android:src="@drawable/contacto"android:layout_weight="1" /><Spinnerandroid:layout_width="0dp"android:layout_height="wrap_content"android:id="@+id/spContactos"android:prompt="@string/contacto"android:spinnerMode="dialog"android:layout_weight="2"/></TableRow>[...]</TableLayout></LinearLayout></FrameLayout></LinearLayout></TabHost></LinearLayout>
AppSmartWatches\wear\src\main\res\layout\round_activity_main.xml
- Layout formado por los mismos componentes definidos en
rect_activity_main.xml
, pero su peculiaridad radica en que está destinado a pantallas con forma redonda, y por lo tanto se asignan diferentes valores para su adaptación visual a dicha forma (propiedades de ancho, alto y márgenes de los componentes con los límites de la pantalla). Al tratarse de un diseño muy similar, es recomendable visualizar dichas diferencias directamente en el editor de layouts de Android Studio.
AppSmartWatches\wear\src\main\res\layout\spinner.xml
- Se crea un archivo xml de tipo Drawable, que proporciona una vista personalizada para el listado de contactos telefónico. Dicho recurso estará formado por un componente de tipo TextView:
123456789101112<?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="30dp"android:paddingTop="30dp" />
Nota: Al tratarse de una parte común en proyecto utilizados anteriormente, la clase SplashScreen.java y sus correspondientes layouts (activity_splash_screen.xml, rect_splash_screen.xml y round_splash_screen.xml) no se describen dentro del apartado «Documentación de código fuente».
Dependencias declaradas:
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(include: ['*.jar'], dir: 'libs') compile 'com.google.android.support:wearable:1.0.0' compile 'com.google.android.gms:play-services-wearable:6.1.71' } |
Permisos de aplicación en AndroidManifest.xml
Será necesario declarar permisos que permitan a la aplicación realizar llamadas, y poder gestionar dicha llamada desde el dispositivo Android Wear:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.academiaandroid.appsmartwatches" > <uses-permission android:name="android.permission.CALL_PHONE" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@android:style/Theme.DeviceDefault" > [...] </application> </manifest> |