Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Android Wear 2.0 Features for Developers

DZone's Guide to

Android Wear 2.0 Features for Developers

From complications to wrist gestures, there's a lot to consider when it comes to smart watches. What are the most important features that you need to know about?

· Mobile Zone
Free Resource

Download this comprehensive Mobile Testing Reference Guide to help prioritize which mobile devices and OSs to test against, brought to you in partnership with Sauce Labs.

This article provides an overview of key Android Wear 2.0 features and a short tutorial on complications. Android Wear 2.0 Developer Preview was launched in May 2016. The full version release is expected to be part of an Android N release. Now, let's look into various features and the implementation of Wear 2.0.

Complications

First, I want to give a short note on WatchFace. WatchFace is a dynamic digital canvas for Android Wear. It shows the time on the watch with colors and animations. The user can select the watch face either by Android Wear companion app or through the wearable. Watch faces supports both round and square wears of Android.

Developers can create watch face applications with the customized graphical designs supporting the wears and publish to the play store. The wearable user can install his or her favorite watch face application downloaded from play store and set it to wearable as a default watch face.

Image title

The complication API adds extra information like battery info and steps counted to the watch face. The companion data provider app can send this information to watch face using complications API. What does “companion data provider” app mean? Any app that shares its data to watch face is called a companion data provider. The data provider app shares its data alone and rendering of the data is controlled by the watch face app.

Adding Complications to a Watch Face Application

A developer has to take care of the following coding to render complications in the watch face. Watch face app should call the setActiveComplications method in WatchFaceService.Engine class. The argument of this method contains the list of complication IDs. The complication IDs identify the slot (left, right, top, or bottom) of the watch face. Watch face app can activate the required slots by mentioning the complications IDs. Rendering of complication data takes place in the activated slots.

On calling the createProviderChooserIntent method from the activity, the system will display all provider apps. The user can choose the complication data from the provider apps list. The data is displayed in the selected slot based on the ID passed to this method.

The watch face app requires the below permission in the manifest file to receive the complications data:

<uses-permission android:name="com.google.android.wearable.permission.RECEIVE_COMPLICATION_DATA" />

To make it easier, wearable support library provides ComplicationHelperActivity class. This helper class grants permission at the run time. We need to use the ComplicationHelperActivity.createProviderChooserHelperIntent method to get the provider interface.

Type of the complication data is the last parameter of the createProviderChooserHelperIntent method. Complications data type can vary from SHORT_TEXT, ICON, RANGED_VALUE, LONG_TEXT, SMALL_IMAGE, and LARGE_IMAGE.

The below sample registers the left and right dials on the watch face using a class which extends CanvasWatchFaceService.

private static final int LFT_DIAL_COMPLICATIONID = 0;
private static final int RGHT_DIAL_COMPLICATIONID = 1;

public static final int[] COMPIDS = { LFT_DIAL_COMPLICATIONID, RGHT_DIAL_COMPLICATIONID};

// Left and right dial supported types.
public static final int[][] COMPLICATION_SUPPORTED_DATATYPES = {
        {ComplicationData.TYPE_LONG_TEXT},
        {ComplicationData.TYPE_LONG_TEXT}
};

The below method is declared in the service class extending CanvasWatchFaceService.

setActiveComplications(COMPIDS);

In the Activity class of WatchFace, WearableListView is loaded with the number of dials of WatchFace registered for the complications. Activity class calls the provider apps list interface on click of the wearable configuration list. The adapter class is extended with WearableListView.Adapter. It can be created based on how you want to show your registered dials in the wearable list view.

private static final int PROVIDER_CHOOSER_REQ_CODE = 1;
private WearableListView mWearableListView;
private WearableListAdapter mWearableListAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.watchfacecomp_activity);

    mWearableListAdapter = new WearableListAdapter(getApplicationContext(), getCompItems());

    mWearableListView = (WearableListView) findViewById(R.id.wearablelist);
    mWearableListView.setAdapter(mWearableListAdapter);
    mWearableListView.setClickListener(this);
}

private List<CompItem> getCompItems() {
    ComponentName watchFaceObj = new ComponentName(
            getApplicationContext(), CustomWatchFaceService.class);

    String[] compNames =
            getResources().getStringArray(R.array.compnames);

    int[] compIds = CustomWatchFaceService.COMPIDS;

    TypedArray compicons = getResources().obtainTypedArray(R.array.compicons);

    List<CompItem> compitems = new ArrayList<>();
    for (int i = 0; i < complicationIds.length; i++) {
        compitems.add(new CompItem(watchFaceObj,
                compIds[i],
                CustomWatchFaceService.COMPLICATION_SUPPORTED_DATATYPES[i],
                compicons.getDrawable(i),
                compNames[i]));
    }
    return compitems;
}
@Override
public void onClick(WearableListView.ViewHolder viewHolder) {
    Integer tag = (Integer) viewHolder.itemView.getTag();
    CompItem compItem = mWearableListAdapter.getItem(tag);

    startActivityForResult(
            ComplicationHelperActivity.createProviderChooserHelperIntent(
                    getApplicationContext(),
                    compItem.watchFace,
                    compItem.compId,
                    compItem.supportedDataTypes),
            PROVIDER_CHOOSER_REQ_CODE);
}

Selected Complication data is updated in the canvas by the onComplicationDataUpdate method of WatchFaceService.Engine class. This callback contains the complicationID and ComplicationData as arguments. Triggering of this callback happens in three different scenarios.

  1. When a watch face complication becomes active.

  2. When a watch face complication has changed the providers.

  3. When the provider has updated its data.

@Override
public void onComplicationDataUpdate(
        int complicationId, ComplicationData complicationData) {
    // Adds/updates active complication data in the array.
    mActiveCompDataArray.put(complicationId, complicationData);
    invalidate();
}

Exposing Complications Data to Watch Face Applications

Data provider apps must define a service extending the ComplicationProviderService. This service class sends the complication data to the watch face apps by the onComplicationUpdate callback. Triggering of this callback happens at following scenarios.

  • When a complication of your provider becomes active.

  • When the defined time is elapsed.

  • When an active complication is changed to use this provider

  • When a request is triggered from our own class using ProviderUpdateRequester.requestUpdate().

The provider service requires following permission in service declaration of the manifest file to expose complications data to watch faces.

android:permission="com.google.android.wearable.permission.BIND_COMPLICATION_PROVIDER"

Service declaration should also contain below intent-filter in manifest and the metadata information to define the data type of complications (i.e., LONG_TEXT) and the time period interval on which data has to be updated to the watch face.

<intent-filter>
    <action android:name="android.support.wearable.complications.ACTION_COMPLICATION_UPDATE_REQUEST"/>
</intent-filter>

<meta-data android:name="android.support.wearable.complications.SUPPORTED_TYPES"
           android:value="LONG_TEXT"/>
<meta-data android:name="android.support.wearable.complications.UPDATE_PERIOD_SECONDS"
           android:value="180"/>

The below sample code of provider app sends a simple text to the complications of watch face apps.

@Override
public void onComplicationUpdate(
        int complication_Id, int data_Type, ComplicationManager complicationMgr) {

    ComplicationData compData = null;
    switch (data_Type) {
        case ComplicationData.TYPE_LONG_TEXT:
            compData = new
   ComplicationData.Builder(ComplicationData.TYPE_LONG_TEXT)                                                                              
                    .setLongText(
                            ComplicationText.plainText("Say Hi to Watchface"))
                    .build();
            break;
        default:
            Log.w(TAG, "complication type is not supported" + data_Type);

    }
    if (compData!= null) {
        complicationMgr.updateComplicationData(complication_Id, compData);
    }
}

Wear Navigations and Actions

Wear 2.0 provides material design features by using navigation drawer and action drawer APIs. The navigation drawer appears when the user swipes from top to bottom in the wearable. The action drawer appears on swiping from bottom to top in the wearable. The user can jump between different views within the app using navigation drawer. Action drawer loads with context-specific menus like action bar in mobile phones.

Wearable support library provides two classes named WearableNavigationDrawer and WearableActionDrawer. These classes are required to create the navigation and action drawer designs. The views are embedded with the root layout named WearableDrawerLayout.

Curved Layout    

The curved layout is the vertical list of items specific to the round display of wearables. Wear 2.0 gives WearableRecyclerView API to create scrollable list items. The scrollable list will match with the round display of wears.

The DefaultOffsettingHelper class is used to define offsetting items in the curved layout by default. Custom offsetting logic is possible by extending WearableRecyclerView.OffsettingHelper abstract class and attach it to the WearableRecyclerView class by using the setOffsettingHelper method.

Notification Changes in Wear 2.0

Wear 2.0 provides advanced notification interface adding buttons with user actions and more detailed content. The user gets an app like experience when interacting with the notifications of Wear 2.0. The main notification features are inline action, expanded notification, and messaging style.

Inline Action allows developers to add button in the notification stream card. Immediate user action performed on tap of the button in the notification. Few examples are replying to a text, archiving an email message and stopping a fitness action. The inline action is used only if any action required based on the notification received.

RemoteInput.Builder class instance is created and set in the NotificationCompat.Action.Builder using the method addRemoteInput to add an inline action to the notification. The expanded notifications API adds more content along with button in the notification. Expanded notifications are used in two cases:

  1. When notification generated from the paired phone.

  2. When notification does not have content intent. It means there should not be an activity launch on tap of the notification.

Extra content pages appear vertical in the order they have added. One primary action mapped to this expanded notification. Any extra actions are added if required.

In a chat app, notification views customized by embedding Messaging style in it. It provides a rich chat-like experience in the app when doing chat in the notification. Messaging Style provides the feature called smart reply. List of choices provided in the expanded notification. When the user taps on any of the choices, the tapped text posted back in the chat. Smart reply choices generated by the machine learning of wearable based on the notification context.

The following actions should take place to enable the smart reply in the notification.

  1. The NotificationCompat.MessagingStyle class needs to be used.

  2. The value of setAllowGeneratedReplies method has to be set as true.

  3. You need to ensure that notification action has RemoteInput.
    Image title

Bridging Mode for Notifications

Generally, notifications are shared between Android the wear app and the companion phone app. There are chances of same notifications notified on both wearable and phone app resulting to duplicating of alerts. Android Wear 2.0 introduces the bridging mode to avoid this duplication issue. The bridging mode can be configured in three different ways.

Bridging Configuration in the Manifest File

If developers declare the metadata information of notificationBridgeMode as NO_BRIDGING in the manifest, notifications cannot be bridged from phone app to Android Wear app.

If we don’t declare the value of notificationBridgeMode metadata or the value is BRIDGING in manifest, bridging of notification would be enabled mode by default.

Runtime Bridging Configuration

The bridging mode can be disabled at runtime by using BridgingManager and BridgingConfig class objects. Setting the value of setBridgingEnabled method as false disables bridging for all notifications. By default, the bridging mode is enabled if we don’t use the method or if the value is set as true.

If we want to enable bridging mode for some notifications alone, we can exclude them using addExcludedTag method mentioning the tag names of notifications.

Also, vice versa is applicable if we set the value as true in setBridgingEnabled. It means all notifications are enabled with bridging mode except the tagged ones.

Setting a Dismissal ID to Sync Notification Dismissals

The NotificationCompat.WearableExtender class provides methods to set and get the dismissal ID for each notification. A unique ID is set for each notification. When a notification is dismissed, all other notifications with the same dismissal ID are dismissed on watches and the companion phone apps.

public WearableExtender setDismissalId(String dismissalId)
public String getDismissalId()

Wear Input Method Framework

Wear 2.0 supports virtual onscreen keyboard support other than voice input for giving user inputs. Same Input Method Framework (IMF) APIs of Android used for phones are used to develop the custom IMF for wearables. The APIs are exposed to third party developers to create the custom Input Method Editors (IME). When creating for wear, developers have to keep in mind the IMEs size should not occupy more space in the wear.

Wrist Gestures

Wear 2.0 provides a wrist gestures feature to avoid hand interaction with wear device. Wrist gestures give the flexibility to scroll the list items. The user can scroll list just by quickly flicking the wrist away from him and slowly turn back towards the user. To scroll back on the list, the user can slowly flick the wrist away from themselves and quickly turn back towards themselves.

Standalone Apps

Before Wear 2.0, a companion phone app was mandatory to install the watch app. Phone APK embeds the watch APK in it. The wear app is installed in the watch when the corresponding phone app installed in the handheld device and paired with wear. In 2.0, creating independent standalone apps are possible for wears without phone apps. Play store is available for watches from 2.0 version. The standalone apps are published to the wearable play store. The user can install wear apps directly from the play store of the watch.

In standalone apps, network calls can be made from wear apps if the watch has WiFi or a cellular network. Data storage is also available for wear apps like how we use shared preference, SQLite, or internal storage in phones.

Cloud messaging servers like Firebase or GCM are used to send the notifications to wearables in standalone apps.

App Distribution

Minimum and target API versions can be set to 24 in standalone wear apps. The minimum API version should be 23 and the wear APK has to be embedded in the phone APK to continue the support for Wear 1.0. If the app supports 2.0 alone, there's no need to embed the wear APK inside phone APK.

Analysts agree that a mix of emulators/simulators and real devices are necessary to optimize your mobile app testing - learn more in this white paper, brought to you in partnership with Sauce Labs.

Topics:
mobile ,wearables ,watch 2.0 ,android

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}