📜 ⬆️ ⬇️

Google I / O 2016: WatchFace 2.0 - Complications

Hi, Habr! Google I / O passed quite recently (if someone missed our report - you are here), where a new API for displaying data on the watch faces was released. Its name came from the watch industry: in Russian they are traditionally called “Complications”, but in English - “Complications”.



In short, this is a mechanism for displaying any additional information on the clock, in addition to the actual time: in the real world there can be all sorts of planets, star calendars, and in our case everything that comes to your mind. Today we will show what API Watch Face Complications is capable of and how to work with it.



Note: the text and the API review was prepared for you by the GDG leader of Rostov-on-Don Alexander Kulikovsky , then the entire text is on his behalf. :)


')

Meet WatchFace 2.0


Hi, I'm Alexander Kulikovsky, I’ve been developing for Android since 2010. Currently I work for Sebbia in the position of Senior Android Engineer and head GDG Rostov-on-Don.

Getting Started


So, to try the new features of Android Watch 2.0, we need a clean project. We create it, specify API N as the minimum SDK version (minSdk) for the phone and for the clock.


We do not need an activity for the phone, so we select the “Add no activity” template. For watches, take the standard Watch Face pattern. Give the name of the service ComplicationWatchFaceService , style - analog.



After that we will receive the standard project.

Before we continue, we need to make sure that in the gradle file that describes the wear module, in the wearable dependencies section, we have at least 2.0.0 connected:
compile 'com.google.android.support:wearable:2.0.0-alpha1' 


We connect "complications"


Add complication to our watchface. In a real application, the user will be able to select sources of information for obtaining complication-data, we also need to ensure that such information is received and displayed.

To start getting complication data, we call the setActiveComplications method in ComplicationWatchFaceService.Engine , and get a list of footprint identifiers to display information:
 // Unique IDs for each complication. private static final int LEFT_DIAL_COMPLICATION = 0; private static final int RIGHT_DIAL_COMPLICATION = 1; // Left and right complication IDs as array for Complication API. public static final int[] COMPLICATION_IDS = {LEFT_DIAL_COMPLICATION, RIGHT_DIAL_COMPLICATION}; …. public void onCreate(SurfaceHolder holder) { ... setActiveComplications(COMPLICATION_IDS); ... } 

The data to display come in the onComplicationDataUpdate method of our ComplicationWatchFaceService.Engine .


It is important:


According to the specification, we are free to display the received data as you please, but for each data type there is a set of required fields for display. More details about this can be found in the table .


We return to our example. The onComplicationDataUpdate method gave us a set of data that we can display. Since the drawing of our watchface occurs only in the onDraw method, the obtained data must first be saved somewhere. To do this, create a SparseArray <ComplicationData> , initialize it in onCreate and add all the values ​​to it in the onComplicationDataUpdate method :
 @Override public void onComplicationDataUpdate(int watchFaceComplicationId, ComplicationData data) { super.onComplicationDataUpdate(watchFaceComplicationId, data); mActiveComplicationDataSparseArray.put(watchFaceComplicationId, data); invalidate(); } 

Drawing on the canvas itself is not interesting for us - it has already been told about it a hundred times already. But what should be paid attention to is where, in fact, from which to take the data that we will display. In the case of TYPE_SHORT_TEXT, the code will look like this:

 private void drawComplications(Canvas canvas, long currentTimeMillis) { ComplicationData complicationData; for (int i = 0; i < COMPLICATION_IDS.length; i++) { complicationData = mActiveComplicationDataSparseArray.get(COMPLICATION_IDS[i]); if ((complicationData != null) && (complicationData.isActive(currentTimeMillis)) && (complicationData.getType() == ComplicationData.TYPE_SHORT_TEXT)) { ComplicationText mainText = complicationData.getShortText(); ComplicationText subText = complicationData.getShortTitle(); CharSequence complicationMessage = mainText.getText(getApplicationContext(), currentTimeMillis); if (subText != null) { complicationMessage = TextUtils.concat( complicationMessage, " ", subText.getText(getApplicationContext(), currentTimeMillis)); } …….. 

But now, if you run the project, we will not see any complications. And all because the user did not specify the sources of information for display. Because I could not - the settings menu, we didn’t select it ... We’ll fix it: we’ll create activations and set it in the manifest:

 <service …. <meta-data android:name="com.google.android.wearable.watchface.wearableConfigurationAction" android:value="com.example.complicationwatchface.CONFIG_COMPLICATION_SIMPLE"/> …. </service> <activity android:name=".ComplicationConfigActivity" android:label="@string/complication_simple"> <intent-filter> <action android:name="com.example.complicationwatchface.CONFIG_COMPLICATION_SIMPLE"/> <category android:name="com.google.android.wearable.watchface.category.WEARABLE_CONFIGURATION"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </activity> 

In this activity, we will display a list of information about the available seats for complications, and we will launch a standard screen for selecting available data sources by clicking on an item:

 Integer tag = (Integer) viewHolder.itemView.getTag(); ComplicationItem complicationItem = mAdapter.getItem(tag); startActivityForResult(ProviderChooserIntent.createProviderChooserIntent( complicationItem.watchFace, complicationItem.complicationId, complicationItem.supportedTypes), PROVIDER_CHOOSER_REQUEST_CODE); 


If you did everything correctly, then as a result at the moment of selection you will have something like this:



Let's check the interface in business: we choose the date display for the left complication, and just an arbitrary number for the right one.

Now, as soon as new data appears in the information sources selected by the user, the onCompliationDataUpdate method will be called, all data will be saved in SparseArray and the next time you call onDraw will be displayed on the dial of our dial.

As you can see, working with “complications” is as simple as possible: a dozen or so lines of code, and everything works. Things are easy - update your projects and add support for new features. Good luck!

Source: https://habr.com/ru/post/304260/


All Articles