Skip to content

Most visited

Recently visited

navigation

Migrating Wear Apps to GoogleApi

Starting with version 11.8.0 of Google Play services, Wear apps should migrate away from the GoogleApiClient class and instead use client objects that are based on the GoogleApi class.

Use of GoogleApi makes it easier to set up asynchronous operations. For example, as described in the introduction to the Tasks API, you can obtain a Task object instead of a PendingResult object.

This page includes:

Note: This update does not apply to Android Wear apps for China, which generally use version 10.2.0 of Google Play services.

Replacements for Deprecated Components

When you use classes that extend the GoogleApi class, such as DataClient and 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 objects. Also see Accessing Google APIs and the reference page for the Wearable class.

The following table contains deprecated components and their replacements:

Deprecated component Replacement component
CapabilityApi CapabilityClient
Channel ChannelClient.Channel
ChannelApi ChannelClient
DataApi DataClient
MessageApi MessageClient
NodeApi NodeClient

Also note the following:

Migration Example for a Wear app

As a migration example, the code snippets below illustrate how the Wear Data Layer sample, which uses the Data Layer API, was updated for version 11.8.0 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:

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.

For example, formerly the Wear Data Layer sample included the following import statement in the MainActivity.java file. This import statement should be removed:

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

In the Wear Data Layer sample, import statements such as the above were replaced with, for example, the following (the second one is for handling task exceptions):

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

Implement the new client interfaces

Remove any usage of the GoogleApiClient 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) 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:

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:

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 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:

@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);
}

Requesting 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, in conjunction with the Tasks API and a result class (that is, as Task<ResultType>).

For example, as shown in the Wear Data Layer sample, you can use the Tasks API to find connected nodes with any given capabilities:

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. 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:

@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);
    mAssetFragment.setBackgroundImage(bitmap);
  }
}
This site uses cookies to store your preferences for site-specific language and display options.

Get the latest Android developer news and tips that will help you find success on Google Play.

* Required Fields

Hooray!

WeChat で Google Developers をフォローする

Browse this site in ?

You requested a page in , but your language preference for this site is .

Would you like to change your language preference and browse this site in ? If you want to change your language preference later, use the language menu at the bottom of each page.

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a short survey?
Help us improve the Android developer experience. (Dec 2017 Android Platform & Tools Survey)