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

Introduction in Android Wear and Watchfaces

Introduction in Android Wear and Watchfaces

Avatar for Dionysis Lorentzos

Dionysis Lorentzos

April 21, 2016

More Decks by Dionysis Lorentzos

Other Decks in Programming

Transcript

  1. Packaging !" no variants wearApp project(':wearable') !" variants debugWearApp project(path:

    ':wear', configuration: 'snapshotDebug')
 internalWearApp project(path: ':wear', configuration: 'snapshotInternal')
 releaseWearApp project(path: ':wear', configuration: 'productionRelease') Two apps: • The mobile (could be empty) • The wear app Mobile build.gradle:
  2. Node API example Wearable.NodeApi.getConnectedNodes(googleApiClient)
 .setResultCallback(new ResultCallbacks<NodeApi.GetConnectedNodesResult>() {
 @Override
 public void

    onSuccess(@NonNull NodeApi.GetConnectedNodesResult getConnectedNodesResult) {
 
 List<Node> nodes = getConnectedNodesResult.getNodes();
 
 }
 
 @Override public void onFailure(@NonNull Status status) {
 
 }
 });

  3. Node API example Wearable.NodeApi.getConnectedNodes(googleApiClient)
 .setResultCallback(new ResultCallbacks<NodeApi.GetConnectedNodesResult>() {
 @Override
 public void

    onSuccess(@NonNull NodeApi.GetConnectedNodesResult getConnectedNodesResult) {
 
 List<Node> nodes = getConnectedNodesResult.getNodes();
 
 }
 
 @Override public void onFailure(@NonNull Status status) {
 
 }
 });

  4. Node API example Wearable.NodeApi.getConnectedNodes(googleApiClient)
 .setResultCallback(new ResultCallbacks<NodeApi.GetConnectedNodesResult>() {
 @Override
 public void

    onSuccess(@NonNull NodeApi.GetConnectedNodesResult getConnectedNodesResult) {
 
 List<Node> nodes = getConnectedNodesResult.getNodes();
 
 }
 
 @Override public void onFailure(@NonNull Status status) {
 
 }
 });

  5. Node API example Wearable.NodeApi.getConnectedNodes(googleApiClient)
 .setResultCallback(new ResultCallbacks<NodeApi.GetConnectedNodesResult>() {
 @Override
 public void

    onSuccess(@NonNull NodeApi.GetConnectedNodesResult getConnectedNodesResult) {
 
 List<Node> nodes = getConnectedNodesResult.getNodes();
 
 }
 
 @Override public void onFailure(@NonNull Status status) {
 
 }
 });

  6. Capability API example Wearable.CapabilityApi.getCapability(googleApiClient, "NOTIFY-WEATHER", CapabilityApi.FILTER_REACHABLE)
 .setResultCallback(new ResultCallbacks<CapabilityApi.GetCapabilityResult>() {
 @Override


    public void onSuccess(@NonNull CapabilityApi.GetCapabilityResult getCapabilityResult) {
 
 Set<Node> nodes = getCapabilityResult.getCapability().getNodes();
 
 }
 
 @Override public void onFailure(@NonNull Status status) {
 
 }
 });
  7. Capability API example Wearable.CapabilityApi.getCapability(googleApiClient, "NOTIFY-WEATHER", CapabilityApi.FILTER_REACHABLE)
 .setResultCallback(new ResultCallbacks<CapabilityApi.GetCapabilityResult>() {
 @Override


    public void onSuccess(@NonNull CapabilityApi.GetCapabilityResult getCapabilityResult) {
 
 Set<Node> nodes = getCapabilityResult.getCapability().getNodes();
 
 }
 
 @Override public void onFailure(@NonNull Status status) {
 
 }
 });
  8. Capability API example Wearable.CapabilityApi.getCapability(googleApiClient, "NOTIFY-WEATHER", CapabilityApi.FILTER_REACHABLE)
 .setResultCallback(new ResultCallbacks<CapabilityApi.GetCapabilityResult>() {
 @Override


    public void onSuccess(@NonNull CapabilityApi.GetCapabilityResult getCapabilityResult) {
 
 Set<Node> nodes = getCapabilityResult.getCapability().getNodes();
 
 }
 
 @Override public void onFailure(@NonNull Status status) {
 
 }
 });
  9. Slicknode CapabilityObservable.getInfoReachable(googleApiClient, capability) .flatMapIterable { it !→ it.nodes }
 .map

    { it.id } .flatMap { MessageObservable.sendMessage(googleApiClient, it, "/message-path", ByteArray(0)) }
 .subscribe() /Diolor/Slicknode
  10. Slicknode CapabilityObservable.getInfoReachable(googleApiClient, capability) .flatMapIterable { it !→ it.nodes }
 .map

    { it.id } .flatMap { MessageObservable.sendMessage(googleApiClient, it, "/message-path", ByteArray(0)) }
 .subscribe() /Diolor/Slicknode
  11. Slicknode CapabilityObservable.getInfoReachable(googleApiClient, capability) .flatMapIterable { it !→ it.nodes }
 .map

    { it.id } .flatMap { MessageObservable.sendMessage(googleApiClient, it, "/message-path", ByteArray(0)) }
 .subscribe() /Diolor/Slicknode
  12. Slicknode CapabilityObservable.getInfoReachable(googleApiClient, capability) .flatMapIterable { it !→ it.nodes }
 .map

    { it.id } .flatMap { MessageObservable.sendMessage(googleApiClient, it, "/message-path", ByteArray(0)) }
 .subscribe() /Diolor/Slicknode
  13. The CanvasWatchFaceService 
 <service
 android:name=".momentuum.MomentuumFaceService"
 android:label="@string/momentuum"
 android:permission="android.permission.BIND_WALLPAPER"> 
 <meta-data
 android:name="android.service.wallpaper"


    android:resource="@xml/watch_face"/>
 <meta-data
 android:name="com.google.android.wearable.watchface.preview"
 android:resource="@drawable/preview_square"/>
 <meta-data
 android:name="com.google.android.wearable.watchface.preview_circular"
 android:resource="@drawable/preview_circular"/>
 <meta-data
 android:name="com.google.android.wearable.watchface.wearableConfigurationAction"
 android:value="com.lorentzos.aplo.CONFIG_DIGITAL"/>
 
 <intent-filter>
 <action android:name="android.service.wallpaper.WallpaperService"/>
 
 <category android:name="com.google.android.wearable.watchface.category.WATCH_FACE"/>
 </intent-filter> 
 </service>
  14. The CanvasWatchFaceService 
 <service
 android:name=".momentuum.MomentuumFaceService"
 android:label="@string/momentuum"
 android:permission="android.permission.BIND_WALLPAPER"> 
 <meta-data
 android:name="android.service.wallpaper"


    android:resource="@xml/watch_face"/>
 <meta-data
 android:name="com.google.android.wearable.watchface.preview"
 android:resource="@drawable/preview_square"/>
 <meta-data
 android:name="com.google.android.wearable.watchface.preview_circular"
 android:resource="@drawable/preview_circular"/>
 <meta-data
 android:name="com.google.android.wearable.watchface.wearableConfigurationAction"
 android:value="com.lorentzos.aplo.CONFIG_DIGITAL"/>
 
 <intent-filter>
 <action android:name="android.service.wallpaper.WallpaperService"/>
 
 <category android:name="com.google.android.wearable.watchface.category.WATCH_FACE"/>
 </intent-filter> 
 </service>
  15. The CanvasWatchFaceService 
 <service
 android:name=".momentuum.MomentuumFaceService"
 android:label="@string/momentuum"
 android:permission="android.permission.BIND_WALLPAPER"> 
 <meta-data
 android:name="android.service.wallpaper"


    android:resource="@xml/watch_face"/>
 <meta-data
 android:name="com.google.android.wearable.watchface.preview"
 android:resource="@drawable/preview_square"/>
 <meta-data
 android:name="com.google.android.wearable.watchface.preview_circular"
 android:resource="@drawable/preview_circular"/>
 <meta-data
 android:name="com.google.android.wearable.watchface.wearableConfigurationAction"
 android:value="com.lorentzos.aplo.CONFIG_DIGITAL"/>
 
 <intent-filter>
 <action android:name="android.service.wallpaper.WallpaperService"/>
 
 <category android:name="com.google.android.wearable.watchface.category.WATCH_FACE"/>
 </intent-filter> 
 </service>
  16. The CanvasWatchFaceService 
 <service
 android:name=".momentuum.MomentuumFaceService"
 android:label="@string/momentuum"
 android:permission="android.permission.BIND_WALLPAPER"> 
 <meta-data
 android:name="android.service.wallpaper"


    android:resource="@xml/watch_face"/>
 <meta-data
 android:name="com.google.android.wearable.watchface.preview"
 android:resource="@drawable/preview_square"/>
 <meta-data
 android:name="com.google.android.wearable.watchface.preview_circular"
 android:resource="@drawable/preview_circular"/>
 <meta-data
 android:name="com.google.android.wearable.watchface.wearableConfigurationAction"
 android:value="com.lorentzos.aplo.CONFIG_DIGITAL"/>
 
 <intent-filter>
 <action android:name="android.service.wallpaper.WallpaperService"/>
 
 <category android:name="com.google.android.wearable.watchface.category.WATCH_FACE"/>
 </intent-filter> 
 </service>
  17. The CanvasWatchFaceService 
 <service
 android:name=".momentuum.MomentuumFaceService"
 android:label="@string/momentuum"
 android:permission="android.permission.BIND_WALLPAPER"> 
 <meta-data
 android:name="android.service.wallpaper"


    android:resource="@xml/watch_face"/>
 <meta-data
 android:name="com.google.android.wearable.watchface.preview"
 android:resource="@drawable/preview_square"/>
 <meta-data
 android:name="com.google.android.wearable.watchface.preview_circular"
 android:resource="@drawable/preview_circular"/>
 <meta-data
 android:name="com.google.android.wearable.watchface.wearableConfigurationAction"
 android:value="com.lorentzos.aplo.CONFIG_DIGITAL"/>
 
 <intent-filter>
 <action android:name="android.service.wallpaper.WallpaperService"/>
 
 <category android:name="com.google.android.wearable.watchface.category.WATCH_FACE"/>
 </intent-filter> 
 </service>
  18. The CanvasWatchFaceService 
 <service
 android:name=".momentuum.MomentuumFaceService"
 android:label="@string/momentuum"
 android:permission="android.permission.BIND_WALLPAPER"> 
 <meta-data
 android:name="android.service.wallpaper"


    android:resource="@xml/watch_face"/>
 <meta-data
 android:name="com.google.android.wearable.watchface.preview"
 android:resource="@drawable/preview_square"/>
 <meta-data
 android:name="com.google.android.wearable.watchface.preview_circular"
 android:resource="@drawable/preview_circular"/>
 <meta-data
 android:name="com.google.android.wearable.watchface.wearableConfigurationAction"
 android:value="com.lorentzos.aplo.CONFIG_DIGITAL"/>
 
 <intent-filter>
 <action android:name="android.service.wallpaper.WallpaperService"/>
 
 <category android:name="com.google.android.wearable.watchface.category.WATCH_FACE"/>
 </intent-filter> 
 </service>
  19. The CanvasWatchFaceService class MomentuumFaceService : CanvasWatchFaceService() {
 
 override fun

    onCreateEngine(): Engine = MomentuumEngine()
 
 
 inner class MomentuumEngine : CanvasWatchFaceService.E ngine() {
 
 override fun onCreate(holder: SurfaceHolder?) {
 super.onCreate(holder)
 }
 
 override fun onDestroy() {
 super.onDestroy()
 }
 
 override fun onDraw(canvas: Canvas?, bounds: Rect?) {
 super.onDraw(canvas, bounds)
 }
 
 override fun onAmbientModeChanged(inAmbientMode: Boolean) {
 super.onAmbientModeChanged(inAmbientMode)
 }
 
 override fun onVisibilityChanged(visible: Boolean) {
 super.on VisibilityChanged(visible)
 }
 
 override fun onTimeTick() {
 super.onTimeTick()
 }
 
 }
 }
  20. The CanvasWatchFaceService class MomentuumFaceService : CanvasWatchFaceService() {
 
 override fun

    onCreateEngine(): Engine = MomentuumEngine()
 
 
 inner class MomentuumEngine : CanvasWatchFaceService.E ngine() {
 
 override fun onCreate(holder: SurfaceHolder?) {
 super.onCreate(holder)
 }
 
 override fun onDestroy() {
 super.onDestroy()
 }
 
 override fun onDraw(canvas: Canvas?, bounds: Rect?) {
 super.onDraw(canvas, bounds)
 }
 
 override fun onAmbientModeChanged(inAmbientMode: Boolean) {
 super.onAmbientModeChanged(inAmbientMode)
 }
 
 override fun onVisibilityChanged(visible: Boolean) {
 super.on VisibilityChanged(visible)
 }
 
 override fun onTimeTick() {
 super.onTimeTick()
 }
 
 }
 }
  21. The CanvasWatchFaceService.Engine class MomentuumFaceService : CanvasWatchFaceService() {
 
 override fun

    onCreateEngine(): Engine = MomentuumEngine()
 
 
 inner class MomentuumEngine : CanvasWatchFaceService.E ngine() {
 
 override fun onCreate(holder: SurfaceHolder?) {
 super.onCreate(holder)
 }
 
 override fun onDestroy() {
 super.onDestroy()
 }
 
 override fun onDraw(canvas: Canvas?, bounds: Rect?) {
 super.onDraw(canvas, bounds)
 }
 
 override fun onAmbientModeChanged(inAmbientMode: Boolean) {
 super.onAmbientModeChanged(inAmbientMode)
 }
 
 override fun onVisibilityChanged(visible: Boolean) {
 super.on VisibilityChanged(visible)
 }
 
 override fun onTimeTick() {
 super.onTimeTick()
 }
 
 }
 }
  22. The CanvasWatchFaceService.Engine class MomentuumFaceService : CanvasWatchFaceService() {
 
 override fun

    onCreateEngine(): Engine = MomentuumEngine()
 
 
 inner class MomentuumEngine : CanvasWatchFaceService.E ngine() {
 
 override fun onCreate(holder: SurfaceHolder?) {
 super.onCreate(holder)
 }
 
 override fun onDestroy() {
 super.onDestroy()
 }
 
 override fun onDraw(canvas: Canvas?, bounds: Rect?) {
 super.onDraw(canvas, bounds)
 }
 
 override fun onAmbientModeChanged(inAmbientMode: Boolean) {
 super.onAmbientModeChanged(inAmbientMode)
 }
 
 override fun onVisibilityChanged(visible: Boolean) {
 super.on VisibilityChanged(visible)
 }
 
 override fun onTimeTick() {
 super.onTimeTick()
 }
 
 }
 }
  23. The CanvasWatchFaceService.Engine class MomentuumFaceService : CanvasWatchFaceService() {
 
 override fun

    onCreateEngine(): Engine = MomentuumEngine()
 
 
 inner class MomentuumEngine : CanvasWatchFaceService.E ngine() {
 
 override fun onCreate(holder: SurfaceHolder?) {
 super.onCreate(holder)
 }
 
 override fun onDestroy() {
 super.onDestroy()
 }
 
 override fun onDraw(canvas: Canvas?, bounds: Rect?) {
 super.onDraw(canvas, bounds)
 }
 
 override fun onAmbientModeChanged(inAmbientMode: Boolean) {
 super.onAmbientModeChanged(inAmbientMode)
 }
 
 override fun onVisibilityChanged(visible: Boolean) {
 super.on VisibilityChanged(visible)
 }
 
 override fun onTimeTick() {
 super.onTimeTick()
 }
 
 }
 } Draw your watch face here
  24. The CanvasWatchFaceService.Engine class MomentuumFaceService : CanvasWatchFaceService() {
 
 override fun

    onCreateEngine(): Engine = MomentuumEngine()
 
 
 inner class MomentuumEngine : CanvasWatchFaceService.E ngine() {
 
 override fun onCreate(holder: SurfaceHolder?) {
 super.onCreate(holder)
 }
 
 override fun onDestroy() {
 super.onDestroy()
 }
 
 override fun onDraw(canvas: Canvas?, bounds: Rect?) {
 super.onDraw(canvas, bounds)
 }
 
 override fun onAmbientModeChanged(inAmbientMode: Boolean) {
 super.onAmbientModeChanged(inAmbientMode)
 }
 
 override fun onVisibilityChanged(visible: Boolean) {
 super.on VisibilityChanged(visible)
 }
 
 override fun onTimeTick() {
 super.onTimeTick()
 }
 
 }
 }
  25. Your challenges • Deal with a canvas -> no dp

    • Deal with a canvas -> stupid square wearables
  26. Your challenges • Deal with a canvas -> no dp

    • Deal with a canvas -> stupid square wearables • Deal with time/timezone/ambient mode changes
  27. Your challenges • Deal with a canvas -> no dp

    • Deal with a canvas -> stupid square wearables • Deal with time/timezone/ambient mode changes • You will remember high-school trigonometry
  28. The preferences <activity
 android:name=".momentuum.config.ConfigActivity"
 android:launchMode="singleInstance"
 android:label="@string/config_title"> 
 <intent-filter>
 <action android:name="com.lorentzos.aplo.CONFIG_DIGITAL"/>


    
 <category android:name="com.google.android.wearable.watchface.category.WEARABLE_CONFIGURATION"/> 
 <category android:name="android.intent.category.DEFAULT"/>
 </intent-filter> 
 </activity>

  29. The preferences <activity
 android:name=".momentuum.config.ConfigActivity"
 android:launchMode="singleInstance"
 android:label="@string/config_title"> 
 <intent-filter>
 <action android:name="com.lorentzos.aplo.CONFIG_DIGITAL"/>


    
 <category android:name="com.google.android.wearable.watchface.category.WEARABLE_CONFIGURATION"/> 
 <category android:name="android.intent.category.DEFAULT"/>
 </intent-filter> 
 </activity>

  30. The preferences <activity
 android:name=".momentuum.config.ConfigActivity"
 android:launchMode="singleInstance"
 android:label="@string/config_title"> 
 <intent-filter>
 <action android:name="com.lorentzos.aplo.CONFIG_DIGITAL"/>


    
 <category android:name="com.google.android.wearable.watchface.category.WEARABLE_CONFIGURATION"/> 
 <category android:name="android.intent.category.DEFAULT"/>
 </intent-filter> 
 </activity>

  31. The preferences class BaseOptionsActivity : Activity(), WearableList View.ClickListener, WearableList View.OnScrollListener

    {
 
 override fun onTopEmptyRegion Click() {
 }
 
 override fun onAbsoluteScrollChange(scroll: Int) { }
 
 override fun onScroll(p0: Int) {
 }
 
 override fun onCentralPositionChanged(p0: Int) {
 }
 
 override fun onScrollStateChanged(p0: Int) {
 }
 
 override fun onClick(p0: WearableList View.ViewHolder) {
 }
 
 }
  32. Challenges • Slow APK installation on Emulator • Even slower

    installation on real device • Have fun debugging on real device…
  33. Challenges • Slow APK installation on Emulator • Even slower

    installation on real device • Have fun debugging on real device… • Google Location services don’t work in emulator
  34. Intro in Android Wear & watch faces Dionysis Lorentzos https://github.com/

    Diolor/Slicknode http://bit.ly/ Diolor-Momentuum https://twitter.com/ Diolor