It's Time to Develop a Watch Face

Dccb5651578c54429ec81782a0bf881a?s=47 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.

Dccb5651578c54429ec81782a0bf881a?s=128

jbarr21

April 10, 2015
Tweet

Transcript

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

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

  3. Watch&Face&Shapes

  4. Watch&Face&Modes

  5. Watch&Face&Device&Proper0es

  6. Watch&Face&System&Objects

  7. Extra&Watch&Face&Data

  8. User%Customiza.on

  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
  10. Watch&Face&Project&Setup • Wear&module • Mobile&module • Common&module

  11. Wear%Module%Setup • Add$Gradle$dependencies • Set$minSdk$to$API$21 • Add$permissions$ • Add$uses$features •

    Declare$service$in$manifest$with$metadata
  12. Watch&Face&Service&Declara/on

  13. Watch&Face&Service&Metadata

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

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

  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
  17. CanvasWatchFaceService • Provides*an*invalida.on*mechanism*for*drawing*the*watch*face • Override*onCreateEngine()*to*return*your* CanvasWatchFaceService.Engine*implementa.on

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

  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
  20. CanvasWatchFaceService.Engine2Lifecycle • onCreate(SurfaceHolder)232Init2watch2face2objects2and2set2style • onVisibilityChanged(boolean)232Manage2listeners2&2receivers • onDraw(Canvas,2Rect)232Draw2the2watch2face2with2given2state • onDestroy()232Clean2up2handler2messages

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

    onInterrup7onFilterChanged(int) • onTimeTick()
  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
  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
  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

  25. None
  26. 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

  27. Allowing(User(Customiza3on

  28. 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
  29. 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

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

  31. 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
  32. 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(...)

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

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

    emulator -avd <avd_name> -prop ro.ambient.burn_in_protection=true
  35. 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
  36. 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
  37. Thanks! Specialized*Bikes*Watch*Face*|*Chron*Watch*Face @jbarr21(|(h+p:/ /twotoasters.com