2. ¿Quien soy?
Mobile Software Engineer en
Redbooth Inc. (formerly Teambox).
Organizador del GDG Barcelona
(Google Developer Group).
Previously: UAB (Universidad
Autonoma de Barcelona) y
Citigroup.
Twitter: @Nescafemix
About.me: about.me/joan.fuentes.hernandez
3. ¿Qué es Android Wear?
•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.
VIDA REAL
INTERACCIÓN DISPOSITIVO
14. 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
15. 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
17. Programando para Wear - tipos
• Notificaciones de sistema con funcionalidad de Wear
• Aplicaciones de Wear
18. Notificaciones de sistema con funcionalidad de Wear
Código con todos los ejemplos usados en:
https://github.com/Nescafemix/workshop-android-wear-notifications
19. Notificaciones de sistema con funcionalidad de Wear
•Cualquier notificación básica por defecto aparecerá en Wear
int 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());
20. Notificaciones de sistema con funcionalidad de Wear
Extendiendo a Wear
•Añadiendo una simple imagen de fondo
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());
22. Notificaciones de sistema con funcionalidad de Wear
Extendiendo a Wear
•Pages
// Create a second page notification
Notification secondPageNotification = new NotificationCompat.Builder(this)
.setContentTitle("Second Page title”)
.setContentText("Default second page text”)
.build();
23. Notificaciones de sistema con funcionalidad de Wear
Extendiendo a Wear
// 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();
•Pages
24. Notificaciones de sistema con funcionalidad de Wear
Extendiendo a Wear
•Pages
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());
25. Notificaciones de sistema con funcionalidad de Wear
Extendiendo a Wear
•Pages con otro estilo
BigTextStyle
InboxStyle
BigPictureStyle
26. Notificaciones de sistema con funcionalidad de Wear
Extendiendo a Wear
•Pages con otro estilo
BigTextStyle
// 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);
27. 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);
28. 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);
30. 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);
31. Notificaciones de sistema con funcionalidad de Wear
Extendiendo a Wear
•Actions : Entrada por voz en una notificación
32. 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 RemoteInput
public 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>
33. 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();
34. 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;
}
35. 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);
37. 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());
38. 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());
46. 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
48. 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'
49. 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" />
52. 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
53. Aplicaciones de Wear
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
54. 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)