2. Mobile Software Engineer en
Redbooth Inc. (formerly Teambox).
!
Organizador del GDG Barcelona
(Google Developer Group).
!
Previously: UAB (Universidad
A u t o n o m a d e B a rc e l o n a ) y
Citigroup.
¿Quien soy?
Twitter: @Nescafemix
About.me: about.me/joan.fuentes.hernandez
Google+: plus.google.com/+JoanFuentesHernández
3. •Versión de Android para wearables (Lollipop 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
26. 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());
27. 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());
29. 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
30. // 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
31. 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
32. Notificaciones de sistema con funcionalidad de Wear
Extendiendo a Wear
•Pages con otro estilo
BigTextStyle
InboxStyle
BigPictureStyle
33. 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
34. 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);
35. 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);
37. 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);
38. Notificaciones de sistema con funcionalidad de Wear
Extendiendo a Wear
•Actions : Entrada por voz en una notificación
39. 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>
40. 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();
41. 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;
}
42. 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);
44. 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());
45. 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());
53. 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
54. ¿Cómo se ejecutan las aplicaciones?
Aplicaciones de Wear
• Por comando de voz • Mediante el menu Start
55. ¿Cómo se ejecutan las aplicaciones?
Aplicaciones de Wear
• Por comando de voz, tan simple como añadir label en la activity que
queremos iniciar
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@android:style/Theme.DeviceDefault" >
!
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
!
<activity
android:name="com.droids4dev.wearapp.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
!
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
56. ¿Cómo se ejecutan las aplicaciones?
Aplicaciones de Wear
• Por comando de voz, tan simple como añadir label en la activity que
queremos iniciar
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@android:style/Theme.DeviceDefault" >
!
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
!
<activity
android:name="com.droids4dev.wearapp.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
!
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
57. • Listado de librerías necesarias
• 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
58. • 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
62. 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
63. 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
64. 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
65. Tips de configuración
•Si usas emulador: para 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
66. +Info
Código de las aplicaciones de ejemplo:
https://github.com/Nescafemix/workshop-android-wear-notifications
https://github.com/Nescafemix/workshop-android-wear-app