Introduction to Android Wear - A Glimpse Into the Future

Introduction to Android Wear - A Glimpse Into the Future

The recent unveiling of Android Wear introduced a brand new set of challenges and opportunities for application designers and developers. Indeed, wearable computing requires designers to think in a radically different manner while offering tremendous new ways to improve people lives. This session acts as a complete overview of the new Android Wear ecosystem and explains how developers can push their existing apps to the wearable level from both a designer and a developer perspective.

E9bf8f6d5480ea2a2623df7dccfd1f70?s=128

Cyril Mottier

November 14, 2014
Tweet

Transcript

  1. Android Wear 101 A glimpse into the future

  2. TWITTER @cyrilmottier ! WEBSITE cyrilmottier.com

  3. None
  4. None
  5. None
  6. None
  7. Introducing Android Wear paradigms

  8. Real life Get phone Use phone

  9. None
  10. Micro interactions Reducing interactions to their minimum

  11. wearable paradigms handheld paradigms ≠

  12. Think different …or at least differently ?

  13. Android Wear UX main principles

  14. 3 main principles Contextual

  15. 3 main principles Contextual | Glanceable

  16. 3 main principles Contextual | Glanceable Low interaction |

  17. Contextual The right info at the right time

  18. Context helpers Sensors Activity Time Location Devices Identity Calendar

  19. Glanceable The essential info in a blink of an eye

  20. None
  21. 1 6 1 2 3 4 5 2 3

  22. None
  23. Low interaction Design for big gestures

  24. Low interaction Design for big gestures

  25. None
  26. Favour non error-prone input fullscreen tap/swipe voice actions

  27. Simplified Activity lifecycle Device goes to sleep → Activity destroyed

  28. Think your app as a row of cards in a

    grid
  29. None
  30. Understanding the Android Wear ecosystem

  31. 1 device - 1 OS

  32. 1 device - 1 OS No shared code No shared

    resources
  33. Different code base Different applications 1 device - 1 OS

  34. ?

  35. Google Play Services

  36. No Play Store on Android Wear

  37. Imbricated APKs for distribution An APK in an APK…

  38. Play Store Wearable

  39. Play Store Wearable

  40. Play Store Wearable

  41. Developing for Android Wear devices

  42. 2 possibilities Notifications Custom app |

  43. If your app already uses notifications, you have nothing to

    do
  44. If your app already uses notifications, you have nothing to

    do almost
  45. final Intent detailsIntent = DetailsActivity.
 newIntent(this, travelId);
 final PendingIntent detailPendingIntent

    = PendingIntent.
 getActivity(this, 0, detailsIntent, 0);
 
 final NotificationCompat.Builder builder = new NotificationCompat.Builder(this).
 setSmallIcon(R.drawable.ic_status_capitaine).
 setContentTitle(travelTitle).
 setContentIntent(detailPendingIntent);
 
 final Notification notif = new NotificationCompat.BigTextStyle(builder).
 bigText(travelDescription).
 build();
 
 NotificationManagerCompat.from(this).notify(NOTIFICATION_ID, notif);
  46. None
  47. Wearable specific notifications WearableExtender to the rescue

  48. final Bitmap background = 
 BitmapFactory.decodeResource(
 getResources(), R.drawable.paris);
 
 builder.extend(new

    NotificationCompat.
 WearableExtender().setBackground(background));
  49. Stacks setGroup() setSortKey() setGroupSummary()

  50. Pages addPage(Notification)

  51. Pages addPage(Notification)

  52. Voice input RemoteInput

  53. There are some case where notifications are not enough

  54. From To

  55. Wearable apps are fundamentally the same as apps built for

    other devices
  56. android.webkit android.print android.app.backup android.appwidget android.hardware.usb Unsupported APIs

  57. NodeApi Learn about local & connected nodes MessageApi Send messages

    on a “fire & forget” basis DataApi Sync data between nodes on the network
  58. Handheld - ReminderService.java final Notification notification = new NotificationCompat.Builder(context).
 //

    ... setLocalOnly(true).
 // ...
 build();
  59. if (mGoogleApiClient == null) {
 mGoogleApiClient = new GoogleApiClient.Builder(this).
 addApi(Wearable.API).


    addOnConnectionFailedListener(mOnConnectionFailedListener).
 addConnectionCallbacks(mConnectionCallbacks).
 build();
 }
 mGoogleApiClient.connect();
 
 private final GoogleApiClient.OnConnectionFailedListener mOnConnectionFailedListener
 = new GoogleApiClient.OnConnectionFailedListener() {
 @Override
 public void onConnectionFailed(ConnectionResult connectionResult) { /* ... */ }
 };
 
 private final GoogleApiClient.ConnectionCallbacks mConnectionCallbacks = 
 new GoogleApiClient.ConnectionCallbacks() {
 @Override
 public void onConnected(Bundle bundle) { /* TODO */ }
 
 @Override
 public void onConnectionSuspended(int i) { /* ... */ }
 }; Handheld - ReminderService.java
  60. Handheld - ReminderService.java @Override
 public void onConnected(Bundle bundle) {
 


    final PutDataMapRequest request = PutDataMapRequest.
 create("/show-reminder/travel");
 final DataMap map = request.getDataMap();
 
 map.putString("departureStation", departureStation);
 map.putString("arrivalStation", arrivalStation);
 map.putString("barcodeData", barcodeData); // ...
 
 Wearable.DataApi.putDataItem(mGoogleApiClient, request.asPutDataRequest()).
 setResultCallback(new ResultCallback<DataApi.DataItemResult>() {
 @Override
 public void onResult(DataApi.DataItemResult dataItemResult) {
 if (!dataItemResult.getStatus().isSuccess()) {
 // Deal with errors
 }
 }
 });
 }
  61. Wearable - ReminderReceiverService.java public class ReminderReceiverService extends WearableListenerService {
 


    @Override
 public void onDataChanged(DataEventBuffer dataEvents) {
 super.onDataChanged(dataEvents);
 for (DataEvent dataEvent : dataEvents) {
 final Uri uri = dataEvent.getDataItem().getUri();
 final DataMap dataMap = DataMapItem. fromDataItem(dataEvent.getDataItem()).getDataMap();
 switch (dataEvent.getType()) {
 case DataEvent.TYPE_CHANGED:
 onDataEventChanged(uri, dataMap);
 break;
 
 case DataEvent.TYPE_DELETED:
 onDataEventDeleted(uri, dataMap);
 break;
 }
 }
 }
 
 protected void onDataEventChanged(Uri uri, DataMap dataMap) { /* TODO */ }
 protected void onDataEventDeleted(Uri uri, DataMap dataMap) { /* TODO */ }
 }
  62. Wearable - ReminderReceiverService.java @Override
 protected void onDataEventChanged(Uri uri, DataMap dataMap)

    {
 final List<String> segments = uri.getPathSegments();
 if (segments != null && segments.size() > 1 && "show-reminder".equals(segments.get(0))) {
 final String notificationId = segments.get(1);
 
 final String departureStation = dataMap.getString("departureStation");
 final String arrivalStation = dataMap.getString("arrivalStation");
 final String barcodeData = dataMap.getString("barcodeData");
 // ...
 
 final Notification notification = new NotificationCompat.Builder(this).
 setLocalOnly(true).
 // ...
 build();
 
 mNotificationManager.notify(notificationId, NOTIFICATION_ID, notification);
 }
 }
  63. Wearable - ReminderReceiverService.java @Override
 protected void onDataEventDeleted(Uri uri, DataMap dataMap)

    {
 final List<String> segments = uri.getPathSegments();
 if (segments != null && segments.size() > 1 && "show-reminder".equals(segments.get(0))) {
 final String notificationId = segments.get(1);
 mNotificationManager.cancel(notificationId, REMINDER_NOTIFICATION_ID);
 }
 }
  64. android {
 // ...
 }
 
 dependencies { // ...


    wearApp project(':wearable')
 } Packaging wearable apps a simple Gradle dependency
  65. Design from scratch Do not create a small version of

    your handheld app. Start a completely new design process
  66. Think “cards” first Always think about the notification cards pattern

    first. The wear app pattern is a fallback
  67. Keep simplicity in mind Your wearables apps should be as

    rudimentary as interactions with these devices are
  68. Thank you! @cyrilmottier cyrilmottier.com

  69. Fonts Source Sans Pro Menlo Resources Dressed for Iceland •

    Cécile Bernard Moelwynion, Eryri, Cymru • Marc Poppleton