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

It's Time to Develop a Watch Face

jbarr21
April 10, 2015

It's Time to Develop a Watch Face

How can you fit time, weather, wind, precipitation, and sunlight onto a functional small screen?

The Watch Face API is an exciting way to build customized experiences for wearables. This talk shares pro-tips and lessons learned during the development of the Specialized Bikes Watch Face featured in Google’s watch face collection.

First, the basics; an overview of the API, design considerations, and some common tasks. Next, a guided tour through watch face development dropping practical advice you can use for your own watch face implementations. At the end, we'll go over some optimizations and performance tuning.

jbarr21

April 10, 2015
Tweet

More Decks by jbarr21

Other Decks in Technology

Transcript

  1. It's%Time%to%Develop%a%Watch%Face
    James&Barr
    @jbarr21
    Two&Toasters

    View full-size slide

  2. What%is%a%Watch%Face?

    View full-size slide

  3. Watch&Face&Shapes

    View full-size slide

  4. Watch&Face&Modes

    View full-size slide

  5. Watch&Face&Device&Proper0es

    View full-size slide

  6. Watch&Face&System&Objects

    View full-size slide

  7. Extra&Watch&Face&Data

    View full-size slide

  8. User%Customiza.on

    View full-size slide

  9. Watch&Face&API&Overview
    • Provides*base*WatchFaceService*class
    • Has*Canvas*or*OpenGL*ES*2.0*variants
    • Callbacks*for*lifecycle*events,*mode*changes,*&*info
    • Provides*mechanism*for*launching*seEngs*acFvies
    • Packaged*like*a*regular*Wear*app

    View full-size slide

  10. Watch&Face&Project&Setup
    • Wear&module
    • Mobile&module
    • Common&module

    View full-size slide

  11. Wear%Module%Setup
    • Add$Gradle$dependencies
    • Set$minSdk$to$API$21
    • Add$permissions$
    • Add$uses$features
    • Declare$service$in$manifest$with$metadata

    View full-size slide

  12. Watch&Face&Service&Declara/on

    View full-size slide

  13. Watch&Face&Service&Metadata

    View full-size slide

  14. Wear%Se'ngs%Screen%Declara.on
    • Add$ac'vity$for$wearable$se4ngs$screen

    View full-size slide

  15. Mobile'Module'Setup
    • Add$dependencies$and$set$minSdk$to$18
    • Add$mobile$and$wear$permissions

    View full-size slide

  16. Common%Module%Setup
    • Op$onal,*but*highly*recommended
    • Should*contain*shared*data*such*as:
    • DataMap*&*message*paths
    • U$li$es*for*working*with*DataMap
    • Shared*data*models
    • Shared*image*and*string*resources
    • Bundle*key*names*and*default*seBng*values

    View full-size slide

  17. CanvasWatchFaceService
    • Provides*an*invalida.on*mechanism*for*drawing*the*watch*face
    • Override*onCreateEngine()*to*return*your*
    CanvasWatchFaceService.Engine*implementa.on

    View full-size slide

  18. CanvasWatchFaceService.Engine2Lifecycle
    • onCreate(SurfaceHolder)232Init2watch2face2objects2and2set2style

    View full-size slide

  19. Build&Watch&Face&Style
    • Peek%card%height%&%opacity
    • Peek%card%visibility%in%ambient%mode
    • Hotword%indicator%posi:oning
    • Status%bar%icon%posi:oning
    • Hotword%&%status%bar%icon%background
    • System%:me%UI%visibility

    View full-size slide

  20. CanvasWatchFaceService.Engine2Lifecycle
    • onCreate(SurfaceHolder)232Init2watch2face2objects2and2set2style
    • onVisibilityChanged(boolean)232Manage2listeners2&2receivers
    • onDraw(Canvas,2Rect)232Draw2the2watch2face2with2given2state
    • onDestroy()232Clean2up2handler2messages

    View full-size slide

  21. CanvasWatchFaceService.Engine2Callbacks
    • onApplyWindowInsets(WindowInsets)
    • onPeekCardPosi7onUpdate(Rect)
    • onProper7esChanged(Bundle)
    • onAmbientModeChanged(boolean)
    • onInterrup7onFilterChanged(int)
    • onTimeTick()

    View full-size slide

  22. Drawing(the(Watch(Face
    • Use%bitmaps%efficiently
    • In%ambient%mode:
    • Draw%with%less%color%(usually%grayscale)
    • Update%only%every%minute%via%onTimeTick()
    • Cancel%any%delayed%messages%used%for%update%Bmer

    View full-size slide

  23. Drawing(the(Watch(Face(in(Special(Modes
    • In$low(bit$ambient$mode:
    • Do$not$an2(alias$text$or$shapes
    • When$burn(in$protec2on$enabled:
    • Don't$draw$within$10px$of$border$since$content$may$shi@
    • Don't$draw$large$patches$of$solid$color

    View full-size slide

  24. Displaying*the*Time
    • Maintain'a'Time'object
    • Handle'0me'zone'changes
    • Honor'the'12/24;hour'se=ng
    • Manage'a'0mer'used'to'schedule'next'update

    View full-size slide

  25. Displaying*Addi-onal*Info
    • Many&op)ons&(calendar,&sensor,&loca)on)
    • Perform&data&requests&and&computa)ons&on&mobile
    • Use&WearableListenerService&for&response&handling
    • Don't&let&your&watch&face&turn&into&an&app

    View full-size slide

  26. Allowing(User(Customiza3on

    View full-size slide

  27. Allowing(User(Customiza3on
    • Wearable(se*ngs(screen
    • Limit(available(op5ons(to(simple(toggles(and(short(lists
    • Indicate(that(more(se*ngs(are(available(on(the(mobile(device
    • Companion(se*ngs(screen
    • Display(full(set(of(possible(customiza5ons
    • Includes(set(and(forget(op5ons(like(units

    View full-size slide

  28. Syncing'Se)ngs
    • Keep%se'ngs%in%sync%between%devices
    • Use%DataMap%to%manage%buffering%of%updates%and%storage
    • Only%redraw%the%watch%face%when%se'ng%changes%values
    • Prevent%infinite%loops%from%DataMap%callbacks%&%widget%listeners

    View full-size slide

  29. WearableListView
    • Extension*of*RecyclerView
    • Included*in*wearable*support*library
    • Allows*for*easy*selec8on*of*list*items

    View full-size slide

  30. Using&WearableListView
    • Don't'set'a'LayoutManager
    • WearableListView.ClickListener'handles'item'selec1on
    • Use'addOnScrollListener(),'not'setOnScrollListener()
    • Animate'the'transi1ons'to/from'the'center'list'item
    • Scroll'1tle'header'text'along'with'list

    View full-size slide

  31. Performance*Op-miza-ons
    • Don't'draw'unnecessary'transparent'pixels
    • Don't'update'the'display'unnecessarily
    • Don't'do'lengthy'opera7ons'(bitmap'resize/load)'in'onDraw(...)
    • Don't'allocate'objects'in'onDraw(...)

    View full-size slide

  32. Ba#ery'Life'Op-miza-ons
    • Don't'animate'unnecessarily
    • Update'rate
    • Features'vs'ba8ery
    • Monitor'ba8ery'life

    View full-size slide

  33. Tes$ng'with'Emulator
    • Use%F7%to%toggle%screen%on/off%for%tes2ng%ambient%mode
    • emulator -avd -prop
    ro.ambient.low_bit_enabled=true
    • emulator -avd -prop
    ro.ambient.burn_in_protection=true

    View full-size slide

  34. Pro$Tips
    • Install(Wear(APK(directly(to(wearable(during(dev
    • Separate(drawing(logic(from(WatchFaceService
    • Create(a(skeleton(watch(face(with(Android(Studio(1.1
    • Gracefully(handle(wearable(not(connected(to(mobile
    • Use(JobScheduler(for(scheduling(data(requests

    View full-size slide

  35. Useful'Links
    Google’s(Watch(Face(Training(Docs:
    developer.android.com/training/wearables/watch=faces/index.html
    Watch&Face&API&Blog&Post&on&ToastDroid:
    h8p:/
    /toastdroid.com/tag/watch>face/
    Chron&Watch&Face&Source&Code:
    h1ps:/
    /github.com/twotoasters/chron
    Slide&Deck
    h+ps:/
    /speakerdeck.com/jbarr21

    View full-size slide

  36. Thanks!
    Specialized*Bikes*Watch*Face*|*Chron*Watch*Face
    @jbarr21(|(h+p:/
    /twotoasters.com

    View full-size slide