Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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.

Cyril Mottier

November 14, 2014
Tweet

More Decks by Cyril Mottier

Other Decks in Programming

Transcript

  1. Android Wear 101
    A glimpse into the future

    View Slide

  2. TWITTER
    @cyrilmottier
    !
    WEBSITE
    cyrilmottier.com

    View Slide

  3. View Slide

  4. View Slide

  5. View Slide

  6. View Slide

  7. Introducing
    Android Wear paradigms

    View Slide

  8. Real life
    Get
    phone
    Use
    phone

    View Slide

  9. View Slide

  10. Micro interactions
    Reducing interactions to their minimum

    View Slide


  11. View Slide

  12. wearable
    paradigms
    handheld
    paradigms

    View Slide

  13. Think different
    …or at least differently ?

    View Slide

  14. Android Wear
    UX main principles

    View Slide

  15. 3 main principles
    Contextual

    View Slide

  16. 3 main principles
    Contextual | Glanceable

    View Slide

  17. 3 main principles
    Contextual | Glanceable Low interaction
    |

    View Slide

  18. Contextual
    The right info
    at the right time

    View Slide

  19. Context helpers
    Sensors
    Activity
    Time
    Location
    Devices
    Identity
    Calendar

    View Slide

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

    View Slide

  21. View Slide

  22. 1
    6
    1
    2
    3
    4
    5 2
    3

    View Slide

  23. View Slide

  24. Low interaction
    Design for big gestures

    View Slide

  25. Low interaction
    Design for big gestures

    View Slide

  26. View Slide

  27. Favour non
    error-prone input
    fullscreen tap/swipe
    voice actions

    View Slide

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

    View Slide

  29. Think your app as a row of
    cards in a grid

    View Slide

  30. View Slide

  31. Understanding the
    Android Wear ecosystem

    View Slide

  32. 1 device - 1 OS

    View Slide

  33. 1 device - 1 OS
    No shared code
    No shared resources

    View Slide

  34. Different code base
    Different applications
    1 device - 1 OS

    View Slide

  35. ?

    View Slide

  36. Google
    Play Services

    View Slide

  37. No Play Store
    on Android Wear

    View Slide

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

    View Slide

  39. Play Store
    Wearable

    View Slide

  40. Play Store
    Wearable

    View Slide

  41. Play Store
    Wearable

    View Slide

  42. Developing for
    Android Wear devices

    View Slide

  43. 2 possibilities
    Notifications Custom app
    |

    View Slide

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

    View Slide

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

    View Slide

  46. 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);

    View Slide

  47. View Slide

  48. Wearable specific notifications
    WearableExtender to the rescue

    View Slide

  49. final Bitmap background = 

    BitmapFactory.decodeResource(

    getResources(), R.drawable.paris);


    builder.extend(new NotificationCompat.

    WearableExtender().setBackground(background));

    View Slide

  50. Stacks
    setGroup()
    setSortKey()
    setGroupSummary()

    View Slide

  51. Pages
    addPage(Notification)

    View Slide

  52. Pages
    addPage(Notification)

    View Slide

  53. Voice input
    RemoteInput

    View Slide

  54. There are some case where
    notifications are not enough

    View Slide

  55. From To

    View Slide

  56. Wearable apps are
    fundamentally the same as
    apps built for other devices

    View Slide

  57. android.webkit
    android.print
    android.app.backup
    android.appwidget
    android.hardware.usb
    Unsupported APIs

    View Slide

  58. NodeApi
    Learn about local &
    connected nodes
    MessageApi
    Send messages on
    a “fire & forget” basis
    DataApi
    Sync data between
    nodes on the network

    View Slide

  59. Handheld - ReminderService.java
    final Notification notification = new NotificationCompat.Builder(context).

    // ...
    setLocalOnly(true).

    // ...

    build();

    View Slide

  60. 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

    View Slide

  61. 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() {

    @Override

    public void onResult(DataApi.DataItemResult dataItemResult) {

    if (!dataItemResult.getStatus().isSuccess()) {

    // Deal with errors

    }

    }

    });

    }

    View Slide

  62. 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 */ }

    }

    View Slide

  63. Wearable - ReminderReceiverService.java
    @Override

    protected void onDataEventChanged(Uri uri, DataMap dataMap) {

    final List 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);

    }

    }

    View Slide

  64. Wearable - ReminderReceiverService.java
    @Override

    protected void onDataEventDeleted(Uri uri, DataMap dataMap) {

    final List 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);

    }

    }

    View Slide

  65. android {

    // ...

    }


    dependencies {
    // ...

    wearApp project(':wearable')

    }
    Packaging wearable apps
    a simple Gradle dependency

    View Slide

  66. Design from scratch
    Do not create a small version of your handheld
    app. Start a completely new design process

    View Slide

  67. Think “cards” first
    Always think about the notification cards
    pattern first. The wear app pattern is a fallback

    View Slide

  68. Keep simplicity in mind
    Your wearables apps should be as rudimentary
    as interactions with these devices are

    View Slide

  69. Thank you!
    @cyrilmottier
    cyrilmottier.com

    View Slide

  70. Fonts
    Source Sans Pro
    Menlo
    Resources
    Dressed for Iceland • Cécile Bernard
    Moelwynion, Eryri, Cymru • Marc Poppleton

    View Slide