Starting with [version
11.8.0](https://developers.google.com/android/guides/releases) of Google Play services, Wear OS apps should migrate away
from the [GoogleApiClient](https://developers.google.com/android/guides/google-api-client)
class and instead use client objects that are based on the [GoogleApi](https://developers.google.com/android/reference/com/google/android/gms/common/api/GoogleApi) class.


Use of [GoogleApi](https://developers.google.com/android/reference/com/google/android/gms/common/api/GoogleApi) makes it easier to set up asynchronous operations.
For example, as described in the [introduction to the
Tasks API](https://developers.google.com/android/guides/tasks), you can obtain a `Task` object instead of a
[PendingResult](https://developers.google.com/android/reference/com/google/android/gms/common/api/PendingResult) object.


This page includes:

- A table of replacement components
- An example of updating an existing app to use the [Tasks API](https://developers.google.com/android/guides/tasks)

**Note:** This update does not apply to [Wear OS apps for
China](https://developer.android.com/training/wearables/apps/creating-app-china), which generally use version 10.2.0 of Google Play services.

**Note:** This API is currently only available on Android phones
and Wear OS watches that are paired with Android phones. For Wear OS watches paired with iOS
phones, apps can query other cloud-based APIs if Internet connectivity is available.

## Replacements for deprecated components


When you use classes that extend the [GoogleApi](https://developers.google.com/android/reference/com/google/android/gms/common/api/GoogleApi) class, such as [DataClient](https://developers.google.com/android/reference/com/google/android/gms/wearable/DataClient) and [MessageClient](https://developers.google.com/android/reference/com/google/android/gms/wearable/MessageClient), the Google Play services SDK manages
connections to Google Play services for you.


Apps that use the replacement classes below do not need to create and
manage [GoogleApiClient](https://developers.google.com/android/guides/google-api-client)
objects. Also see [Accessing
Google APIs](https://developers.google.com/android/guides/api-client) and the [reference page for the Wearable class](https://developers.google.com/android/reference/com/google/android/gms/wearable/Wearable).


The following table contains deprecated components and their
replacements:

|----------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------|
| **Deprecated component**                                                                                       | **Replacement component**                                                                                                      |
| [CapabilityApi](https://developers.google.com/android/reference/com/google/android/gms/wearable/CapabilityApi) | [CapabilityClient](https://developers.google.com/android/reference/com/google/android/gms/wearable/CapabilityClient)           |
| [Channel](https://developers.google.com/android/reference/com/google/android/gms/wearable/Channel)             | [ChannelClient.Channel](https://developers.google.com/android/reference/com/google/android/gms/wearable/ChannelClient.Channel) |
| [ChannelApi](https://developers.google.com/android/reference/com/google/android/gms/wearable/ChannelApi)       | [ChannelClient](https://developers.google.com/android/reference/com/google/android/gms/wearable/ChannelClient)                 |
| [DataApi](https://developers.google.com/android/reference/com/google/android/gms/wearable/DataApi)             | [DataClient](https://developers.google.com/android/reference/com/google/android/gms/wearable/DataClient)                       |
| [MessageApi](https://developers.google.com/android/reference/com/google/android/gms/wearable/MessageApi)       | [MessageClient](https://developers.google.com/android/reference/com/google/android/gms/wearable/MessageClient)                 |
| [NodeApi](https://developers.google.com/android/reference/com/google/android/gms/wearable/NodeApi)             | [NodeClient](https://developers.google.com/android/reference/com/google/android/gms/wearable/NodeClient)                       |


Also note the following:

- For notifications of changes to channels, [Channel.ChannelListener](https://developers.google.com/android/reference/com/google/android/gms/wearable/ChannelApi.ChannelListener) is replaced by [ChannelClient.ChannelCallback](https://developers.google.com/android/reference/com/google/android/gms/wearable/ChannelClient.ChannelCallback)
- For setting the thread for listener callbacks, [GoogleApiClient.Builder.setHandler](https://developers.google.com/android/reference/com/google/android/gms/common/api/GoogleApiClient.Builder.html#setHandler(android.os.Handler)) is replaced by the `setLooper` method of [WearableOptions.Builder](https://developers.google.com/android/reference/com/google/android/gms/wearable/Wearable.WearableOptions.Builder)

## Migration example for a Wear app


As a migration example, the code snippets below illustrate how the
[Wear Data
Layer sample](https://github.com/android/wear-os-samples/tree/main/DataLayer), which uses the [Data Layer API](https://developer.android.com/training/wearables/data-layer), was
updated for [version
11.8.0](https://developers.google.com/android/guides/releases) of Google Play services. If your app has a phone module, its
updates may be similar to those for the Wear module.

### Update the dependency on Google Play services


Since your app may depend on an earlier version of Google Play services,
update the following dependency in the `build.gradle` file of
your Wear module:  

```groovy
dependencies {
...
compile 'com.google.android.gms:play-services-wearable:11.8.0'
}
```

### Update the import statements of your app


Import the necessary classes, including classes in the [Tasks API](https://developers.google.com/android/guides/tasks).


For example, formerly the [Wear Data Layer
sample](https://github.com/android/wear-os-samples/tree/main/DataLayer) included the following import statement in the
`MainActivity.java` file. This `import` statement
should be removed:  

### Kotlin

```kotlin
...
import com.google.android.gms.common.api.GoogleApiClient
...
```

### Java

```java
...
import com.google.android.gms.common.api.GoogleApiClient;
...
```


In the [Wear
Data Layer sample](https://github.com/android/wear-os-samples/tree/main/DataLayer), `import` statements such as the above
were replaced with, for example, the following (the second one is for
handling task exceptions):  

### Kotlin

```kotlin
...
import com.google.android.gms.tasks.Tasks
import java.util.concurrent.ExecutionException
...
```

### Java

```java
...
import com.google.android.gms.tasks.Tasks;
import java.util.concurrent.ExecutionException;
...
```

### Implement the new client interfaces


Remove any usage of the [GoogleApiClient](https://developers.google.com/android/guides/google-api-client)
class and associated interfaces (`ConnectionCallbacks`,
`OnConnectionFailedListener`, etc.) and replace the other
Listener implementations with their new versions. The actual methods to
override generally have the same names as before, so the main change is
similar to the example below.


The main activity of the Wear Data Layer sample (as indicated in a diff
on [GitHub](https://github.com/android/wear-os-samples/blob/master/DataLayer/Wearable/src/main/java/com/example/android/wearable/datalayer/MainActivity.java)) had implemented, for example, the
`CapabilityApi.CapabilityListener` interface. But now, the
main activity implements
`CapabilityClient.OnCapabilityChangedListener`.


Below is a comparison of the class definitions.


Here is a snippet before the use of version 11.8.0 of Google Play
services:  

### Kotlin

```kotlin
class MainActivity :
        Activity(),
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener,
        DataApi.DataListener,
        MessageApi.MessageListener,
        CapabilityApi.CapabilityListener
```

### Java

```java
public class MainActivity extends Activity implements
  ConnectionCallbacks,
  OnConnectionFailedListener,
  DataApi.DataListener,
  MessageApi.MessageListener,
  CapabilityApi.CapabilityListener
```


Here is a snippet after the use of version 11.8.0 of Google Play
services:  

### Kotlin

```kotlin
class MainActivity :
        Activity(),
        DataClient.OnDataChangedListener,
        MessageClient.OnMessageReceivedListener,
        CapabilityClient.OnCapabilityChangedListener
```

### Java

```java
public class MainActivity extends Activity implements
  DataClient.OnDataChangedListener,
  MessageClient.OnMessageReceivedListener,
  CapabilityClient.OnCapabilityChangedListener
```

### Remove and add listeners


The new client objects are cached and shared between [GoogleApi](https://developers.google.com/android/reference/com/google/android/gms/common/api/GoogleApi) instances, so it is unnecessary to keep member
variables; clients are inexpensive to create and won't lose their
listeners.


Below is a snippet from the revised [Wear Data Layer
sample](https://github.com/android/wear-os-samples/tree/main/DataLayer):  

### Kotlin

```kotlin
override fun onResume() {
    super.onResume()
    Wearable.getDataClient(this).addListener(this)
    Wearable.getMessageClient(this).addListener(this)
    Wearable.getCapabilityClient(this)
            .addListener(
                    this,
                    Uri.parse("wear://"),
                    CapabilityClient.FILTER_REACHABLE
            )
}

override fun onPause() {
    super.onPause()
    Wearable.getDataClient(this).removeListener(this)
    Wearable.getMessageClient(this).removeListener(this)
    Wearable.getCapabilityClient(this).removeListener(this)
}
```

### Java

```java
@Override
protected void onResume() {
  super.onResume();
  Wearable.getDataClient(this).addListener(this);
  Wearable.getMessageClient(this).addListener(this);
  Wearable.getCapabilityClient(this)
  .addListener(
    this, Uri.parse("wear://"), CapabilityClient.FILTER_REACHABLE);
}

@Override
protected void onPause() {
  super.onPause();
  Wearable.getDataClient(this).removeListener(this);
  Wearable.getMessageClient(this).removeListener(this);
  Wearable.getCapabilityClient(this).removeListener(this);
}
```

### Request information with the Tasks API


You may want to request information outside of the listeners that update
your app when there is a data change. In such cases, make a request using
a client such as [DataClient](https://developers.google.com/android/reference/com/google/android/gms/wearable/DataClient), in conjunction with the [Tasks API](https://developers.google.com/android/guides/tasks) and
a result class (that is, as `Task<ResultType>`).


For example, as shown in the [Wear Data Layer
sample](https://github.com/android/wear-os-samples/tree/main/DataLayer), you can use the [Tasks API](https://developers.google.com/android/guides/tasks) to
find connected nodes with any given capabilities:  

### Kotlin

```kotlin
private fun showNodes(vararg capabilityNames: String) {
    Wearable.getCapabilityClient(this)
            .getAllCapabilities(CapabilityClient.FILTER_REACHABLE).apply {
                addOnSuccessListener { capabilityInfoMap ->
                    val nodes: Set<Node> = capabilityInfoMap
                            .filter { capabilityNames.contains(it.key) }
                            .flatMap { it.value.nodes }
                            .toSet()
                    showDiscoveredNodes(nodes)
                }
            }
}

private fun showDiscoveredNodes(nodes: Set<Node>) {
    val nodesList: Set<String> = nodes.map { it.displayName }.toSet()
    val msg: String = if (nodesList.isEmpty()) {
        Log.d(TAG, "Connected Nodes: No connected device was found for the given capabilities")
        getString(R.string.no_device)
    } else {
        Log.d(TAG, "Connected Nodes: ${nodesList.joinToString(separator = ", ")}")
        getString(R.string.connected_nodes, nodesList)
    }
    Toast.makeText(this@MainActivity, msg, Toast.LENGTH_LONG).show()
}
```

### Java

```java
private void showNodes(final String... capabilityNames) {
  Task<Map<String, CapabilityInfo>> capabilitiesTask =
    Wearable.getCapabilityClient(this)
            .getAllCapabilities(CapabilityClient.FILTER_REACHABLE);
  capabilitiesTask.addOnSuccessListener(new
    OnSuccessListener<Map<String, CapabilityInfo>>() {
      @Override
      public void onSuccess(Map<String, CapabilityInfo>
        capabilityInfoMap) {
          Set<Node> nodes = new HashSet<>();
          if (capabilityInfoMap.isEmpty()) {
            showDiscoveredNodes(nodes);
            return;
          }
          for (String capabilityName : capabilityNames) {
            CapabilityInfo capabilityInfo = capabilityInfoMap.get(capabilityName);
            if (capabilityInfo != null) {
              nodes.addAll(capabilityInfo.getNodes());
            }
          }
          showDiscoveredNodes(nodes);
      }
  });
}

private void showDiscoveredNodes(Set<Node> nodes) {
  List<String> nodesList = new ArrayList<>();
  for (Node node : nodes) {
    nodesList.add(node.getDisplayName());
  }
  LOGD(TAG, "Connected Nodes: " + (nodesList.isEmpty()
    ? "No connected device was found for the given capabilities"
    : TextUtils.join(",", nodesList)));
  String msg;
  if (!nodesList.isEmpty()) {
    msg = getString(R.string.connected_nodes, TextUtils.join(", ", nodesList));
  } else {
    msg = getString(R.string.no_device);
  }
  Toast.makeText(MainActivity.this, msg, Toast.LENGTH_LONG).show();
}
```


For additional code that utilizes the Wearable and Tasks APIs, see the
[Wear Data Layer
sample](https://github.com/android/wear-os-samples/tree/main/DataLayer). And as an example of using heavy tasks off of the UI thread
or in a service, there is another option available. Here is an example of
how to block on a task and get the result synchronously:  

### Kotlin

```kotlin
override fun doInBackground(vararg params: Asset): Bitmap? {
    if (params.isNotEmpty()) {
        val asset = params[0]
        val getFdForAssetResponseTask: Task<DataClient.GetFdForAssetResponse> =
                Wearable.getDataClient(applicationContext).getFdForAsset(asset)
        return try {
            // Block on a task and get the result synchronously. This is generally done
            // when executing a task inside a separately managed background thread. Doing
            // this on the main (UI) thread can cause your application to become
            // unresponsive.
            val getFdForAssetResponse: DataClient.GetFdForAssetResponse =
                    Tasks.await(getFdForAssetResponseTask)
            getFdForAssetResponse.inputStream?.let { assetInputStream ->
                BitmapFactory.decodeStream(assetInputStream)
            } ?: run {
                Log.w(TAG, "Requested an unknown Asset.")
                null
            }

        } catch (exception: ExecutionException) {
            Log.e(TAG, "Failed retrieving asset, Task failed: $exception")
            return null
        } catch (exception: InterruptedException) {
            Log.e(TAG, "Failed retrieving asset, interrupt occurred: $exception")
            return null
        }

    } else {
        Log.e(TAG, "Asset must be non-null")
        return null
    }
}

override fun onPostExecute(bitmap: Bitmap?) {
    bitmap?.also {
        Log.d(TAG, "Setting background image on second page..")
        moveToPage(1)
        assetFragment.setBackgroundImage(it)
    }
}
```

### Java

```java
@Override
protected Bitmap doInBackground(Asset... params) {
  if (params.length > 0) {
    Asset asset = params[0];
    Task<DataClient.GetFdForAssetResponse> getFdForAssetResponseTask =
      Wearable.getDataClient(getApplicationContext()).getFdForAsset(asset);
    try {
      // Block on a task and get the result synchronously. This is generally done
      // when executing a task inside a separately managed background thread. Doing
      // this on the main (UI) thread can cause your application to become
      // unresponsive.
      DataClient.GetFdForAssetResponse getFdForAssetResponse =
        Tasks.await(getFdForAssetResponseTask);
      InputStream assetInputStream = getFdForAssetResponse.getInputStream();
      if (assetInputStream != null) {
        return BitmapFactory.decodeStream(assetInputStream);
      } else {
        Log.w(TAG, "Requested an unknown Asset.");
        return null;
      }

    } catch (ExecutionException exception) {
      Log.e(TAG, "Failed retrieving asset, Task failed: " + exception);
      return null;
    } catch (InterruptedException exception) {
      Log.e(TAG, "Failed retrieving asset, interrupt occurred: " + exception);
      return null;
    }
  } else {
    Log.e(TAG, "Asset must be non-null");
    return null;
  }
}

@Override
protected void onPostExecute(Bitmap bitmap) {
  if (bitmap != null) {
    LOGD(TAG, "Setting background image on second page..");
    moveToPage(1);
    assetFragment.setBackgroundImage(bitmap);
  }
}
```