B4A Library WatchFace Library

With this library you can create WatchFaces for Android Wear devices with B4A.

digitalwatchface_preview.pnganalogwatchface_preview.png

The example watchface should work well on round and square displays with or without "flat tire".

To use this library you should be familiar with creating wear apps with B4A. It will also help if you read the complete android developer documentation for watch faces.

Installation:
Copy all files from the WatchFaceLibX_X.zip file to your additional libraries folder (.xml, .jar, .aar)
You need to install the Support Repository and Google Repository from SDK Manager.

The dependencies are removed from the library in the latest version, since they don't work anymore.

Add the following dependencies to your watchface source code:

B4X:
#AdditionalJar: androidx.wear:wear
#AdditionalJar: wearable-2.5.0.aar
#AdditionalJar: com.google.android.wearable:wearable, ReferenceOnly
#AdditionalJar: com.android.support:support-v4, ReferenceOnly
#AdditionalJar: com.android.support:percent, ReferenceOnly
#AdditionalJar: com.android.support:support-annotations, ReferenceOnly
#AdditionalJar: com.android.support:recyclerview-v7, ReferenceOnly

Documentation:
WatchFace
Author:
Markus Stipp
Version: 1
  • WFEngine
    Fields:
    • AMBIENT_PEEK_MODE_HIDDEN As Int
    • AMBIENT_PEEK_MODE_VISIBLE As Int
    • BACKGROUND_VISIBILITY_INTERRUPTIVE As Int
    • BACKGROUND_VISIBILITY_PERSISTENT As Int
    • PEEK_MODE_NONE As Int
    • PEEK_MODE_SHORT As Int
    • PEEK_MODE_VARIABLE As Int
    • PEEK_OPACITY_MODE_OPAQUE As Int
    • PEEK_OPACITY_MODE_TRANSLUCENT As Int
    • PROTECT_HOTWORD_INDICATOR As Int
    • PROTECT_STATUS_BAR As Int
    • PROTECT_WHOLE_SCREEN As Int
    • TAPTYPE_TAP As Int
    • TAPTYPE_TOUCH As Int
    • TAPTYPE_TOUCH_CANCEL As Int
  • Methods:
    • ChinSize As Int
      Returns the chin size (flat tire size) of a round watch like the Moto360.
    • SetWatchFaceStyle
      Updates WatchFace style.

      Uses the following properties:

      AcceptsTapEvents
      AmbientPeekMode
      BackgroundVisiblility
      CardPeekMode
      HideHotwordIndicator
      HideStatusBar
      StatusBarGravity
      HotworkIndicatorGravity
      ShowSystemUiTime
      PeekOpacityMode
      ShowUnreadCountIndicator
      ViewProtectionMode
  • Properties:
    • AcceptsTapEvents As Boolean
      Sets whether this watchface accepts tap events. The default is false.
      Setting this to true enables the TapCommand event.

      This property changes not immediately but only when SetWatchFaceStyle() is called!
    • AmbientPeekMode As Int
      Sets how the first, peeking card will be displayed while the watch is in ambient, black and white mode.

      Must be either AMBIENT_PEEK_MODE_VISIBLE or AMBIENT_PEEK_MODE_HIDDEN

      This property changes not immediately but only when SetWatchFaceStyle() is called!
    • BackgroundVisibility As Int
      Set how to display background of the first, peeking card.

      Must be either BACKGROUND_VISIBILITY_INTERRUPTIVE or BACKGROUND_VISIBILITY_PERSISTENT

      This property changes not immediately but only when SetWatchFaceStyle() is called!
    • BurnInProtection As Boolean [read only]
      Returns if the device needs burn in protections. On such devices don't create
      big white backgrounds.
    • CardPeekMode As Int
      Sets how far into the screen the first card will peek while the watch face is displayed.

      Must be either PEEK_MODE_VARIABLE or PEEK_MODE_SHORT

      This property changes not immediately but only when SetWatchFaceStyle() is called!
    • Height As Int [read only]
      Returns the Height of the screen
    • HideHotwordIndicator As Boolean
      Hides the hotword indicator.

      This property changes not immediately but only when SetWatchFaceStyle() is called!
    • HideStatusBar As Boolean
      Hides the status icons (battery state, lack of connection etc.)

      This property changes not immediately but only when SetWatchFaceStyle() is called!
    • HotwordIndicatorGravity As Int
      Sets position of hotword (OK Google) on the screen.

      This property changes not immediately but only when SetWatchFaceStyle() is called!
    • IsAmbientMode As Boolean [read only]
      Returns if the watchface is in ambient mode.
    • IsRound As Boolean [read only]
      Returns true if the device has a round display.
    • IsVislible As Boolean [read only]
      Returns if the watchface is visible.
    • LowBitAmbient As Boolean [read only]
      Returns if the device has reduced colors in ambient mode. Disable antialias of your
      drawings to reduce CPU usage.
    • MuteMode As Boolean [read only]
      Returns if the device is muted.
    • NotificationCount As Int [read only]
      Returns the total number of Notification cards.
    • OuterBounds As RectWrapper [read only]
      Returns a Rect object that has the complete screen size without any insets etc.
    • PeekCardBounds As RectWrapper [read only]
      Returns a Rect object for the first PeekCard Bounds.
    • PeekOpacityMode As Int
      Sets whether the first, peeking card should be opaque when the watch face is displayed.

      Must be either PEEK_OPACITY_MODE_OPAQUE or PEEK_OPACITY_MODE_TRANSLUCENT

      This property changes not immediately but only when SetWatchFaceStyle() is called!
    • ShowSystemUiTime As Boolean
      Sets if the system will draw the system-style time over the watch face.

      This property changes not immediately but only when SetWatchFaceStyle() is called!
    • ShowUnreadCountIndicator As Boolean
      Sets whether to add an indicator of how many unread cards there are in the stream.
      The indicator will be displayed next to status icons (battery state, lack of connection).

      This property changes not immediately but only when SetWatchFaceStyle() is called!
    • StatusBarGravity As Int
      Sets position of status icons (battery state, lack of connection) on the screen.

      This property changes not immediately but only when SetWatchFaceStyle() is called!
    • Tag As Object
      Property to store any information in the engine.
    • UnreadCount As Int [read only]
      Returns the number of unread Notification cards.
    • ViewProtectionMode As Int
      Adds background color to UI elements of the home screen, so they are readable on the watch face. This should be used if the watch face color is close to being white.

      Must be any combination of PROTECT_STATUS_BAR, PROTECT_HOTWORD_INDICATOR and PROTECT_WHOLE_SCREEN

      This property changes not immediately but only when SetWatchFaceStyle() is called!
    • Width As Int [read only]
      Returns the Width of the screen
  • WFManager
    Events:
    • AmbientModeChanged (Engine as WFEngine As , AmbientMode as Boolean As )
    • Created (Engine As WFEngine)
    • Draw (Engine as WFEngine As , Canvas as Canvas As , Bounds as Rect As )
    • EngineDestroyed (Engine As WFEngine)
    • SizeChanged (Engine As WFEngine, Width as Int As , Height as Int As )
    • TapCommand (Engine as WFEngine As , TapType As Int, XPos as Int As , YPos as Int As , EventTime as Long As )
    • VisibilityChanged (Engine As WFEngine, Visible As Boolean)
  • Methods:
    • Initialize (EventName As String, IntervalMs As Int)
      Initialize the WatchFaceManager object.

      EventName: The name prefix for the events
      IntervalMs: Timer interval in milliseconds. This will setup a timer which will call the Draw event so the WatchFace gets updated. This timer will fire only in interactive mode and when the WatchFace is visible.
    • InvalidateEngine
      Invalidate the Engine. This will cause a redraw of the WatchFace.
    • IsInitialized As Boolean
      Check if the manager is initialized
  • Permissions:
    • android.permission.WAKE_LOCK
  • Properties:
    • Interval As Int
      Set or get the timer interval. The timer fires only in interactive mode.
      In ambient mode a refresh is done every minute.
    • WFEngine As WFEngine [read only]
      Returns the WatchFace engine. This may be null if the WatchFace engine is not fully initialized yet.

Examples:
There is an example provided which implements an analog clock and a digital clock watchface.

The WatchFaceWear app is the watchface implementation for the wear device. If you have a device with USB port you can directly deploy this app on the device with B4A. If not then you have to create a companion app which is provided with the WatchFaceMobile app. To create the WatchFaceMobile app copy the generated WatchFaceWear.apk to the resouce/raw folder and name it "watchfacewear.apk" (all lower case). Then compile and deploy to your mobile phone.
The WatchFaces should show up in the wear app and directly on the wear device.

The example requires the ABExtDrawing library.

History:
V0.1
  • initial release
V0.2
  • more complete implementation
V1.0
  • First official release
V2.0
  • Should work with AndroidX
Since the library is too large now you can download it here:
WatchfaceLib2_0.zip
 

Attachments

  • WatchFaceMobile2_0.zip
    7.6 KB · Views: 616
  • WatchfaceWear2_0.zip
    34 KB · Views: 619
Last edited:

Peter Simpson

Expert
Licensed User
Longtime User
Hello All,
I created an Android Wear watch face and then decided to add a user configuration parameters screen (settings screen). Android Wear supplies an easy way for your users to open an activity which would be for example your watch face settings screen, just hold your finger on your watch face for about one second and the setting screen will open.

If implemented correctly, a small settings icon will appear below your watch face in the preview screen.
settings-icon.png

Please note, I personally use StateManager to store and restore the user setting.

Example below, replace com.example.watchface with your actual package name followed by a dot then your settings activity name.
B4X:
#Region Configuration Activities

AddServiceText(TixWatchFace,
    android:name =".DigitalWatchFaceService" ... />

    <!-- wearable configuration activity -->
    <meta-data
        android:name = "com.google.android.wearable.watchface.wearableConfigurationAction"
        android:value = "com.example.watchface.configuration" />
)

AddActivityText(Configuration,
    android:name=".DigitalWatchFaceWearableConfigActivity"
    android:label="@string/digital_config_name">

    <intent-filter>
        <action android:name = "com.example.watchface.configuration" />
        <category android:name = "com.google.android.wearable.watchface.category.WEARABLE_CONFIGURATION" />
        <category android:name = "android.intent.category.DEFAULT" />
    </intent-filter>
)

#End Region


If you are going to upload your watch face onto the Android Wear store, you should also add the following code to your manifest file.
B4X:
#Region Android Play store options

'Let Android Play Store know it's for Android Wear Only (a watch)
AddManifestText(
    package="com.simplysoftware.tixwatchface"
        xmlns:android="http://schemas.android.com/apk/res/android">
        <uses-feature android:name="android.hardware.type.watch"/>
)


'Let Android Play Store know it's a stand alone app
AddApplicationText(
    <meta-data
        android:name="com.google.android.wearable.standalone"
        android:value="true" />
)

#End Region

Enjoy...
 
Last edited:

ilan

Expert
Licensed User
Longtime User
i wanted for a long time to create smartwatch apps using b4a and i ordered yesterday a new smartwatch because i knew we have a way to do it with b4a using this library. unfortunately, i did not notice that the watch i was ordering has not android wear installed. :(

its the Samsung gear s3 frontier and it is using Tizen OS. so i guess i will need to learn Tizen Studio.
Any chance there will be a possibility using b4x to create apps for Samsung watches?
 

ilan

Expert
Licensed User
Longtime User
Why not just send the watch back, I presume that you purchased it from new????????????

yes, of course, its new but i like Samsung and i like a lot the design of this watch so i will keep it and learn Tizen Studio. You can code in C,C++ and also in Html, JS, CSS.
 

corwin42

Expert
Licensed User
Longtime User
@corwin42 , the library needs to be updated in order to work with AndroidX sdk. The update shouldn't be too complicated. The base class name should be updated and the depends on list.
I will have a look at it in the next days.
 

corwin42

Expert
Licensed User
Longtime User
@corwin42 , the library needs to be updated in order to work with AndroidX sdk. The update shouldn't be too complicated. The base class name should be updated and the depends on list.

Seems to be not so easy.

As I understand correctly, there is no AndroidX version of com.google.android.support:wearable:2.5.0 library.
So even in AndroidStudio you add the following line to compile AndroidWear projects:
Java:
    implementation 'androidx.wear:wear:1.0.0'
    implementation 'com.google.android.support:wearable:2.5.0'
    compileOnly 'com.google.android.wearable:wearable:2.5.0'

So I always get the following error output:
B4A Version: 9.80
Java Version: 11
Parse den Code. (0.01s)
Building folders structure. (0.02s)
Kompiliere den Code. (0.02s)

Die Datei ObfuscatorMap.txt wurde im Objects-Verzeichnis angelegt.
Kompiliere Layoutcode. (0.00s)
Organisiere Libraries. (0.02s)
(AndroidX SDK)
Generiere R Datei. (0.00s)
Kompiliere generierten Java Code. Error
src\de\amberhome\watchfacedemo\analogwatchface.java:8: error: cannot access CanvasWatchFaceService
public class analogwatchface extends de.amberhome.wearwrapper.WatchFaceService{
^
class file for android.support.wearable.watchface.CanvasWatchFaceService not found
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
1 error

javac 11.0.1
 

corwin42

Expert
Licensed User
Longtime User
First post updated with library version 2.0 which is compatible with AndroidX.

Be aware that you need to add the dependencies for the library in the watchface code. See first post.
 

Peter Simpson

Expert
Licensed User
Longtime User
First post updated with library version 2.0 which is compatible with AndroidX.

Hello @corwin42
I've just updated all my personal watch faces and your updates are working 100% perfect. This also means that I can now finally delete my old SDK folder as I was only keeping that folder as it was the only way that I could update my wear watch faces.

Thank you 🍻🍻🍻
 

Watchkido1

Active Member
Licensed User
Longtime User
It makes you cry .....
I've been sitting here for two days now, installing new, copying, extracting with 7-Zip ... 2 times I did the reinstallation according to the specifications ...
Nothing achieved ...
I just can't get this error message away.
I'm totally desperate.
I just want to make a watchface ...


B4A Version: 10.5 BETA # 1
Code analysieren. (0,03 s)
Java Version: 8
Ordnerstruktur erstellen. (0,01 s)
Kompiliere den Code. (0,33 s)
Kompiliere Layoutcode. (0,01 s)
Organisationsbibliotheken. (0,00 s)
(AndroidX SDK)
Generiere R Datei. Error
c: \ android \ tools \ .. \ extras \ b4a_remote \ androidx \ Constraintlayout \ Constraintlayout \ 2.0.4 \ Unpacked-Constraintlayout-2.0.4 \ res \ values \ values.xml: 339: Fehler: Attribut "android: alpha" wurde bereits definiert
c: \ android \ tools \ .. \ extras \ b4a_remote \ androidx \ Constraintlayout \ Constraintlayout \ 2.0.4 \ Unpacked-Constraintlayout-2.0.4 \ res \ values \ values.xml: 342: Fehler: Attribut "android: translationX" wurde bereits definiert
c: \ android \ tools \ .. \ extras \ b4a_remote \ androidx \ Constraintlayout \ Constraintlayout \ 2.0.4 \ Unpacked-Constraintlayout-2.0.4 \ res \ values \ values.xml: 342: Fehler: Attribut "android: translationY" wurde bereits definiert
c: \ android \ tools \ .. \ extras \ b4a_remote \ androidx \ Constraintlayout \ Constraintlayout \ 2.0.4 \ Unpacked-Constraintlayout-2.0.4 \ res \ values \ values.xml: 342: Fehler: Attribut "android: translationZ" wurde bereits definiert [/ QUOTE]
 
Top