workshop de android wear impartido en el codemotion 2014
TRANSCRIPT
Workshop de Android Wear
Mobile Software Engineer en
Redbooth Inc. (formerly Teambox).
Organizador del GDG Barcelona
(Google Developer Group).
Previously: UAB (Universidad
Autonoma de Barcelona) y
Citigroup.
¿Quien soy?
Twitter: @Nescafemix
About.me: about.me/joan.fuentes.hernandez
•Versión de Android para wearables (Kitkat actualmente)
•Pretende facilitarnos la vida reduciendo tiempo de interacción
con el móvil
•Debe mostrar información concisa y útil.
¿Qué es Android Wear?
VIDA REAL
INTERACCIÓN DISPOSITIVO
SECOND SCREEN + FAST ACTIONS
Nuevo paradigma
¿Qué NO debería ser Android Wear?
¿Qué NO debería ser Android Wear?
¿Qué NO debería ser Android Wear?
¿Qué NO debería ser Android Wear?
¿Que necesitan nuestras apps para wear?
NADA
¿Que necesitan nuestras apps para wear?
NADA
¿Que necesitan nuestras apps para wear?
¿Que necesitan nuestras apps para wear?
CASI
¿Que necesitan nuestras apps para wear?
Vamos al lio. Que necesitamos
• Conocimientos previos de Java y desarrollo en Android
• Java Development Kit
• Android Studio 0.8.14 o superior (recomendado 0.9.3)
• SDK de API 19 (4.4.X) (Android SDK Manager)
• SDK de API 20 (Android 4.4W.2) (Android SDK Manager)
• Android Support Library (Android SDK Manager -> Extras)
• Intel x86 Emulator Accelerator (Android SDK Manager -> Extras)
• Dispositivo real o emulador con Google Play Services (Genymotion)
• App de Android Wear instalada en el dispositivo real o emulador
Preparando el entorno
• Crear maquina virtual de Android Wear (si es necesario)
• Si usas emulador: conectar con el emulador hay que redireccionar el puerto
de comunicaciones del AVD al dispositivo, cada vez que se conecta el
dispositivo.
adb -d forward tcp:5601 tcp:5601
o
adb -s identificador forward tcp:5601 tcp:5601
Preparando el entorno
Programando para Wear - tipos
• Notificaciones de sistema con funcionalidad de Wear
• Aplicaciones de Wear
Notificaciones de sistema con funcionalidad de Wear
Código con todos los ejemplos usados en:
https://github.com/Nescafemix/workshop-android-wear-notifications
Notificaciones de sistema con funcionalidad de Wear
•Cualquier notificación básica por defecto aparecerá en Wearint notificationId = 001;
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Default title")
.setContentText("Default text.”)
.setTicker("New notification!");
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(notificationId, notificationBuilder.build());
Notificaciones de sistema con funcionalidad de Wear
•Añadiendo una simple imagen de fondo
Extendiendo a Wear
int notificationId = 001;
NotificationCompat.Extender extender = new NotificationCompat.WearableExtender()
.setHintHideIcon(true)
.setBackground(BitmapFactory.decodeResource(getResources(), R.drawable.trollface));
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Default title")
.setContentText("Default text.”)
.setTicker("New notification!")
.extend(extender);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(notificationId, notificationBuilder.build());
Notificaciones de sistema con funcionalidad de Wear
Extendiendo a Wear
•Pages
Notificaciones de sistema con funcionalidad de Wear
Extendiendo a Wear
// Create a second page notification
Notification secondPageNotification = new NotificationCompat.Builder(this)
.setContentTitle("Second Page title”)
.setContentText("Default second page text”)
.build();
•Pages
// Specific extender to show only background in this notification page
NotificationCompat.Extender extenderOnlyImage = new
NotificationCompat.WearableExtender()
.setHintShowBackgroundOnly(true);
// Create a third page notification with only background
Notification thirdPageNotification = new NotificationCompat.Builder(this)
.extend(extenderOnlyImage)
.build();
Notificaciones de sistema con funcionalidad de Wear
Extendiendo a Wear
•Pages
Notificaciones de sistema con funcionalidad de Wear
Extendiendo a Wear
NotificationCompat.Extender extender = new NotificationCompat.WearableExtender()
.setBackground(BitmapFactory.decodeResource(getResources(), R.drawable.trollface))
.addPage(secondPageNotification)
.addPage(thirdPageNotification);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Default title”)
.setContentText("Default text.”)
.setTicker("New notification!");
.extend(extender);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(notificationId, notificationBuilder.build());
•Pages
Notificaciones de sistema con funcionalidad de Wear
Extendiendo a Wear
•Pages con otro estilo
BigTextStyle
InboxStyle
BigPictureStyle
Notificaciones de sistema con funcionalidad de Wear
Extendiendo a Wear
•Pages con otro estilo
// Create a big text style for the second page
NotificationCompat.BigTextStyle secondPageStyle = new NotificationCompat.BigTextStyle()
.setBigContentTitle("BigTextStyle title")
.bigText(getString(R.string.a_very_large_text));
// Create second page notification
Notification secondPageNotification = new NotificationCompat.Builder(this)
.setStyle(secondPageStyle)
.build();
NotificationCompat.Extender extender = new NotificationCompat.WearableExtender()
.addPage(secondPageNotification)
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Default title")
.setContentText("Default text.")
.setTicker("New notification!")
.extend(extender);
BigTextStyle
Notificaciones de sistema con funcionalidad de Wear
Extendiendo a Wear
•Pages con otro estilo
InboxStyle// Create a Inbox style for the third page
NotificationCompat.InboxStyle thirdPageStyle = new NotificationCompat.InboxStyle()
.setBigContentTitle("InboxStyle title”)
.addLine("Line 1”)
.addLine("Line 2”)
.addLine("Line 3");
// Create third page notification
Notification thirdPageNotification = new NotificationCompat.Builder(this)
.setStyle(thirdPageStyle)
.build();
NotificationCompat.Extender extender = new NotificationCompat.WearableExtender()
.addPage(thirdPageNotification)
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Default title")
.setContentText("Default text.")
.setTicker("New notification!")
.extend(extender);
Notificaciones de sistema con funcionalidad de Wear
Extendiendo a Wear
•Pages con otro estilo
PigPictureStyle// Create a BigPicture style for the fourth page
NotificationCompat.BigPictureStyle fourthPageStyle = new NotificationCompat.BigPictureStyle()
.setBigContentTitle("BigPictureStyle title”)
.bigPicture(BitmapFactory.decodeResource(getResources(), R.drawable.trollface));
// Create third page notification
Notification fourthPageNotification = new NotificationCompat.Builder(this)
.setStyle(fourthPageStyle)
.build();
NotificationCompat.Extender extender = new NotificationCompat.WearableExtender()
.addPage(fourthPageNotification)
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Default title")
.setContentText("Default text.")
.setTicker("New notification!")
.extend(extender);
Notificaciones de sistema con funcionalidad de Wear
Extendiendo a Wear
•Actions
Notificaciones de sistema con funcionalidad de Wear
Extendiendo a Wear
•Actions// Create an intent to open DetailActivity action
Intent actionIntent = new Intent(this, DetailActivity.class);
PendingIntent actionPendingIntent = PendingIntent.getActivity(
this,
requestCode,
actionIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
// Create the action
NotificationCompat.Action action = new NotificationCompat.Action.Builder(
android.R.drawable.ic_menu_view,
"Open detail”,
actionPendingIntent)
.build();
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Default title”)
.setContentText("Default text.”)
.setTicker("New notification!”)
.setContentIntent(actionPendingIntent)
.addAction(action)
.extend(extender);
Notificaciones de sistema con funcionalidad de Wear
Extendiendo a Wear
•Actions : Entrada por voz en una notificación
Notificaciones de sistema con funcionalidad de Wear
Extendiendo a Wear
•Actions : Entrada por voz en una notificación
1) Definimos la entrada de voz con un RemoteInputpublic static final String EXTRA_VOICE_REPLY = "extra_voice_reply";
RemoteInput voiceRemoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
.setLabel("Reply by voice")
.setChoices(getResources().getStringArray(R.array.reply_choices))
.build();
<string-array name="reply_choices">
<item>Yes</item>
<item>No</item>
<item>Maybe</item>
<item>Lo que diga la rubia</item>
<item>1 segundo</item>
<item>Estoy detrás de ti</item>
</string-array>
Notificaciones de sistema con funcionalidad de Wear
Extendiendo a Wear
•Actions : Entrada por voz en una notificación
2) Añadimos el RemoteInput a una acción de la notificación// Create an intent to open the ShowMessageActivity action
Intent showMessageIntent = new Intent(this, ShowMessageActivity.class);
PendingIntent showMessagePendingIntent = PendingIntent.getActivity(this, ++requestCode,
showMessageIntent, PendingIntent.FLAG_UPDATE_CURRENT);
// Create the ReplyByVoiceAction and add the remote input
NotificationCompat.Action replyVoiceAction = new NotificationCompat.Action.Builder(
android.R.drawable.ic_menu_add,
"Speak now”,
showMessagePendingIntent)
.addRemoteInput(voiceRemoteInput)
.build();
Notificaciones de sistema con funcionalidad de Wear
Extendiendo a Wear
•Actions : Entrada por voz en una notificación
3) Creamos nueva activity que reciba el dato y lo muestre@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_message);
TextView messageTextView = (TextView) findViewById(R.id.message);
CharSequence message = "";
Intent intent = getIntent();
if (intent != null) {
message = getMessageText(intent);
}
messageTextView.setText(message);
}
private CharSequence getMessageText(Intent intent) {
Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
if (remoteInput != null) {
return remoteInput.getCharSequence(EXTRA_VOICE_REPLY);
}
return null;
}
Notificaciones de sistema con funcionalidad de Wear
Extendiendo a Wear
•Actions : Entrada por voz en una notificación
4) Añadimos la acción a la notificación - Sólo para Wear
NotificationCompat.Extender extender = new
NotificationCompat.WearableExtender()
.setBackground(BitmapFactory.decodeResource(getResources(),
R.drawable.trollface))
.addAction(replyVoiceAction);
Notificaciones de sistema con funcionalidad de Wear
Extendiendo a Wear
•Stack de notificaciones
Notificaciones de sistema con funcionalidad de Wear
Extendiendo a Wear
•Stack de notificaciones
1) Añadimos el grupo al que pertenece a cada notificación
private static final String GROUP_KEY_WORKSHOP_WEAR = "group_key_workshop_wear";
int notification1Id = 1;
NotificationCompat.Builder notification1Builder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Default title 1")
.setContentText("Default text 1.")
.setTicker("New notification: 1!")
.setGroup(GROUP_KEY_WORKSHOP_WEAR);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(notification1Id, notification1Builder.build());
Notificaciones de sistema con funcionalidad de Wear
Extendiendo a Wear
•Stack de notificaciones
2) Creamos una notificación “resumen” para el móvil/tablet
private static final String GROUP_KEY_WORKSHOP_WEAR = "group_key_workshop_wear";
int notificationSummaryId = 3;
NotificationCompat.Builder notificationSummaryBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Summary title")
.setContentText("Sumary description")
.setTicker("New notification!")
.setGroup(GROUP_KEY_WORKSHOP_WEAR)
.setGroupSummary(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(notificationSummaryId, notificationSummaryBuilder.build());
Notificaciones de sistema con funcionalidad de Wear
Extendiendo a Wear
•Stack de notificaciones
Aplicaciones de Wear
Aplicaciones de Wear
Aplicaciones de Wear
Aplicaciones de Wear
Aplicaciones de Wear
SÓLO CON CLAVE DE RELEASE
Aplicaciones de Wear
Consideraciones
Aplicaciones de Wear
• Bajas especificaciones (procesador, batería, conectividad):
• Operaciones costosas, se ejecutan en el móvil/tablet
• Operaciones de red se ejecutan en el móvil/tablet
• Pantalla pequeña + dedos grandes
• Crear nuevo proyecto con módulo de Wear
Aplicaciones de Wear
• Listado de librerías correctas
• Módulo mobile:
• Librería de soporte (v4 o v7) si es necesario:
compile ‘com.android.support:appcompat-v7:21.0.2'
• Wearable Data Layer (incluida en Google Play Services)
compile ‘com.google.android.gms:play-services:6.1.71’
• Módulo wear:
• Librería de soporte (v4 o v7)
• Wearable Data Layer (incluida en Google Play Services)
compile ‘com.google.android.gms:play-services-wearable:6.1.71'
• Wearable UI support library (unofficial)
compile 'com.google.android.support:wearable:1.0.0'
Aplicaciones de Wear
• referencia a la aplicación de Wear en build.gradle de la app de móvil/tablet
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
wearApp project(':wear')
compile 'com.android.support:appcompat-v7:21.0.2'
compile 'com.google.android.gms:play-services:6.1.71'
}
• si nos comunicamos con el móvil/tablet, añadir la version de Google Play
Services como meta-data en nuestro Manifest (dentro de Application)
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
Aplicaciones de Wear
Aplicaciones de Wear
Wearable UI Library:
• BoxInsetLayout
• CardFragment
• CircledImageView
• ConfirmationActivity
• DismissOverlayView
• GridViewPager
• GridPagerAdapter
• FragmentGridPagerAdapter
• WatchViewStub
• WearableListView
Aplicaciones de Wear
Caso de estudio:
Crear una Android que envíe un mensaje de texto a otra app de
nuestro Wearable, y este muestre dicho mensaje en una Custom
screen.
Aplicaciones de Wear
Código en:https://github.com/Nescafemix/workshop-android-wear-app
1) Creamos un cliente de Google Play Services en la app del
móvil/tablet. Un ejemplo sería crearlo en la propia Activity,
aunque no es la mejor.
2) Añadir métodos de Callback para la DATA LAYER y los eventos
del ciclo de vida
3) Definir una Asynctask (o clases que extienda de Thread) que
envíe tu mensaje a todos los nodos actualmente conectados
Aplicaciones de Wear
4) En la aplicación de Wear, crearemos un Listener service para
recibir los mensajes.
• Añadir el servicio en el Manifest
• Crear un servicio que extienda de WearableListenerService
5) Reenviar el mensaje a la Activity que necesita el dato. (Intent,
LocalBroadcastManager, … depende del caso)
Aplicaciones de Wear
¡MUCHAS GRACIAS!