Yalantis: iOS, Android And Web App Development Company

Customizable Constructor for Designers of Android Wear

Gone are the days when watches were devices to check out the time. Now people use smart watches for doing a handful of things from reading texts to keeping up to date with exchange rates – all on a small screen called a watch face.

The watch face is essentially a digital substitute for a regular watch, but with additional functionalities, such as step count, battery life and upcoming events. These features are called complications just like chronographs or calendars are on regular wristwatches. You can add as many complications as you wish, but sometimes the only thing you want to check on your wrist is the time.

Yalantis Watch Face for Android Wear

[Yalantis WatchFace designed at Yalantis. Check it out on Google Play]

Why did we create a watch face constructor for Android Wear?

The Android Wear market offers countless watch face designs. But sometimes it’s quite difficult to find a watch face design that perfectly fits your needs. Just like with traditional watches, you’re always looking for the style that can best reflect your personality.  

For example, the Yalantis WatchFace that we launched a few months ago features a minimalistic design style, Yalantis logo, and symbolic colors of the Ukrainian national flag. The watch face looks great, but unless you work at Yalantis and live in Ukraine, you will probably look for something else. Independent WatchFace is another app that we created for Independence Day in the USA. It undoubtedly fits the mood on the 4th of July, but we didn’t get many downloads after the holiday.

Yalantis design for a watch face

[Independent WatchFace designed at Yalantis. Check it out on Dribbble]

Since it’s hard to design a watch face that everybody will love, we came up with an idea for a watch face constructor. With this app users can customize their own watch face styles instead of wading through the ocean of designs on Google Play.

What can our watch face constructor do?

Before we developed our watch face constructor, we looked at the existing constructors on Google Play. In most of these apps users can customize the following parts of a watch face:

  1. Background colors or images
  2. Watch hands
  3. Font style
  4. Small details (for example, brand logo, e.g. Rolex)
  5. Widgets
  6. Ambient mode

When a user is satisfied with the watch face design they have constructed, they can save their creation and transfer it to their paired Android Wear device.

watch face constructor for Android WearOur constructor is similar to the ones available on Google Play, but we decided to make it a little bit simpler. It offers customization of the following features:

  1. Background colors and images
  2. Watch hands
  3. Placement of watch hands   
  4. Ambient mode

As you can see, there aren’t too many features yet. Once we understand what features are most useful, we’ll add more possibilities to our watch face constructor. At the moment the app is being tested by our designers, and as soon as we get their feedback we’ll make the constructor available for everybody who uses Android Wear.

Now let’s move on to how we actually made the watch face constructor.    

The main source code for making a watchface constructor

To start development of the watch face constructor app, you need to create a configuration screen. You should place the declaration in the AndroidManifest file.

 <activity
            android:name=".view.configuration.ConfigurationActivity"
            android:label="ConfigurationWatchface">

            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <action android:name="com.yalantis.watchface.CONFIG_CHRON"/>

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

As you can see, the category COMPANION_CONFIGURATION is responsible for a configuration function.

Here is a screenshot of our configuration screen, which is quite minimalistic for the current version of our watch face constructor:

WatchFace constructor

[WatchFace Contructor project made by Yalantis. Check it out on Github]

The Connection Algorithm

When we created a configuration activity, we gained the potential to fetch internal storage resources. Next, we need to send these resources to Android Wear to update the watch face, and for that we need a connection algorithm.  

Here is a step by step description of how to make a connection between an Android mobile device and Android wear:

1. Create an intent to get files from the external storage.

private void startFileChooser(int fileSelectCode) {
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.setType("image/*");
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        mConfigurationView.startFileChooser(intent, fileSelectCode);
    }

2. Initialize GoogleApiClient.

mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(Wearable.API)
                .build();

Call lifecycle methods.

@Override
    protected void onStart() {
        super.onStart();
        mGoogleApiClient.connect();
    }

    @Override
    protected void onStop() {
        mGoogleApiClient.disconnect();
        super.onStop();
    }

3. In onActivityResult write the following code:

try {
            if (resultCode == Activity.RESULT_OK) {
                Uri selectedImageUri = data.getData();
                Bitmap bitmap = MediaStore.Images.Media.getBitmap(mConfigurationView.getContext().getContentResolver(), selectedImageUri);
                App.getConfigurationManager().updateField(requestCode, bitmap);
                new SendToDataLayerThread(Constants.resourceKeyMap.get(requestCode), bitmap, googleApiClient).start();
            }
        } catch (IOException e) {
            Log.e("TAG", e.getMessage());
        }

Then, create a bitmap, and start a new thread.

public class SendToDataLayerThread extends Thread {
 
    private static final int MAX_SIZE = 2000000;
 
    private String path;
    private Bitmap bitmap;
    private GoogleApiClient mGoogleApiClient;
 
    public SendToDataLayerThread(String path, Bitmap bitmap, GoogleApiClient googleApiClient) {
        this.path = path;
        this.bitmap = bitmap;
        mGoogleApiClient = googleApiClient;
    }
 
    public void run() {
        NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).await();
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
        if (bitmap.getByteCount() < MAX_SIZE) {
            for (Node node : nodes.getNodes()) {
                Wearable.MessageApi.sendMessage(mGoogleApiClient, node.getId(), path,  stream.toByteArray()).await();
            }
        } else {
            Log.e("myTag", "big image");
        }
    }
}

That’s all you need for the smartphone app. Now let’s take a look at what we did for the watch face application.

Android Wear application

First, we created a WearebleListenerService that can receive messages from the mobile app. By doing this, we could change the resource of the watch face. Take a look at the code below:

public class WearableListenerService extends com.google.android.gms.wearable.WearableListenerService {
 
    @Override
    public void onMessageReceived(MessageEvent messageEvent) {
         byte[] message = messageEvent.getData();
         Bitmap bitmap = BitmapFactory.decodeByteArray(message, 0, message.length, null);
         EventBus.getDefault().post(new WatchfaceUpdatedEvent(messageEvent.getPath(), bitmap));  
    }
}

To declare an Android Manifest file:

<service android:name="com.yalantis.watchface.sevrice.WearableListenerService">
        <intent-filter>
              <action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
        </intent-filter>
</service>

As you can see, we made a connection between services using the EventBus event. But you can also make a connection with BroadcastReceiver. It’s pretty simple. After Android Wear receives a message, you should replace the resource in CanvasWatchFaceService and update the watch screen:

public void onEvent(WatchfaceUpdatedEvent event) {
    if (event.getResourceBitmap() != null) {
        bundle.put(event.getResourceKey(), event.getResourceBitmap());
        initBitmaps();
     } else {
        initOffset(event.getResourceKey(), event.getOffset());
     }
     invalidate();
}

The early version of our constructor is ready and being reviewed by our design team.

If you’d like to join our testing team and create new designs for watch faces, you can also use our constructor. You can send us an email, and we’ll give you access to the apk file we created. Here are some instructions about what you should do once you get the file:   

First, make a new background png file and upload it to the file system of your smartphone. Then, choose the png file from the app and the look of the watch face will change immediately. If you like how it looks on the smartwatch, then you can work with an Android developer to add functionality to your design. A developer can work with you to develop your watch face concept, sign the apk file for the design, and get your watch face ready to be published.

In the future, we plan to roll out the following features:

  1. Changing resource colors
  2. Creating new widgets with information
  3. Putting logos on watch faces
  4. Creating digital watch faces
  5. Launching the app on Google Play

You can check the source code here. Еnjoy!

You might also like:

Tech

How We Created Animated My Day Watch App Inspired by Apple’s Activity App

Tech

The Dark Side of Android App Widgets

Design

How We Developed the Guillotine Menu Animation for Android

Excited to create something outstanding?

We share the same interests.

Let's team up!