Skip to content

Most visited

Recently visited

navigation

Detecting Location on Android Wear

A watch's small, glanceable form factor makes Android Wear an ideal platform for apps that record, report, and respond to user location. As examples, you can build apps that give users real-time updates on their distance, speed, and direction, or provide glanceable queues about users' surroundings.

Some watches have a built-in GPS sensor that retrieves location data without requiring a tethered phone. When you request location data in a watch app, however, you don't have to worry about where the location data originates; the system gets the data via the most power-efficient method. However, as described in sections below, your app does need to handle the loss of location data.

This document describes how to check for on-watch location sensors, receive location data, and monitor tethered data connections. Also see Location Data for Watches Paired to iPhones.

Note: This document assumes that you know how to use the Google Play services API to retrieve location data.

Use the Fused Location Provider

On a watch, you should get location data using the FusedLocationProviderApi (FLP). The FLP automatically uses location data from the phone if the watch lacks a GPS sensor. For more information, see Create Location Services Client.

For information about requesting location updates and continuously tracking a user's location, see Receiving Location Updates.

Detect On-Board GPS

If a user goes jogging with a watch that lacks a built-in GPS sensor, but leaves the paired phone behind, your watch app cannot get location data through a tethered connection. Your app should detect the situation and warn the user that location functionality is unavailable.

To determine if a watch has a built-in GPS sensor, use the hasSystemFeature() method. The following code detects whether the watch has a built-in GPS sensor when you start an activity:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_activity);

    if (!hasGps()) {
        Log.d(TAG, "This hardware doesn't have GPS.");
        // Fall back to functionality that does not use location or
        // warn the user that location function is not available.
    }

    ...
}

private boolean hasGps() {
    return getPackageManager().hasSystemFeature(PackageManager.FEATURE_LOCATION_GPS);
}

Handle Disconnection Events

If a watch has no built-in GPS sensor, the watch abruptly loses its location data stream upon losing the tethered data connection to a phone. If your app expects a constant stream of data, your app must detect the loss of a connection, warn the user, and gracefully degrade in functionality.

To detect the loss of a tethered data connection, use the GetConnectedNodesResult method of the NodeApi. For example:

  1. Initialize a GoogleApiClient and create a method that calls the NodeApi, e.g. a method called inspectNodes:
    private GoogleApiClient mGoogleApiClient;
    private boolean mWearableConnected = false;
    
    @Override
    public void onCreate() {
        super.onCreate();
    
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addApi(Wearable.API)
                .addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
                    @Override
                    public void onConnected(Bundle connectionHint) {
                        inspectNodes();
                    }
    
                    @Override
                    public void onConnectionSuspended(int cause) {
                    }
                })
                .build();
    }
    
    private void inspectNodes(){
        Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).setResultCallback(this, 1000, TimeUnit.MILLISECONDS);
    }
    
  2. Use the following callback method to get the result of using the inspectNodes method:
    @Override
    public void onResult(NodeApi.GetConnectedNodesResult getConnectedNodesResult) {
        if (getConnectedNodesResult != null && getConnectedNodesResult.getNodes() != null){
            mWearableConnected = false;
            for (Node node : getConnectedNodesResult.getNodes()){
                if (node.isNearby()){
                    mWearableConnected = true;
                }
            }
        }
        Log.v("TEST", "mWearableConnected: " + mWearableConnected);
    }
    

Handle Location Not Found

When the GPS signal is lost, you can retrieve the last known location of the user's watch. Retrieving the last known location is helpful when you cannot get a GPS fix, or when the watch lacks built-in GPS and loses its connection with the phone. For more information, see Getting the Last Known Location.

Synchronize Data

If your watch app records data using a built-in GPS sensor, you may want to synchronize the location data with the handset. With the LocationListener, you implement the onLocationChanged() method to detect and record the location as it changes.

The following code for watch apps detects when the location changes and uses the data layer API to store the data for later retrieval by your phone app:

@Override
public void onLocationChanged(Location location) {
    ...
    addLocationEntry(location.getLatitude(), location.getLongitude());
}

private void addLocationEntry(double latitude, double longitude) {
    if (!mSaveGpsLocation || !mGoogleApiClient.isConnected()) {
        return;
    }

    mCalendar.setTimeInMillis(System.currentTimeMillis());

    // Set the path of the data map
    String path = Constants.PATH + "/" + mCalendar.getTimeInMillis();
    PutDataMapRequest putDataMapRequest = PutDataMapRequest.create(path);

    // Set the location values in the data map
    putDataMapRequest.getDataMap()
            .putDouble(Constants.KEY_LATITUDE, latitude);
    putDataMapRequest.getDataMap()
            .putDouble(Constants.KEY_LONGITUDE, longitude);
    putDataMapRequest.getDataMap()
            .putLong(Constants.KEY_TIME, mCalendar.getTimeInMillis());

    // Prepare the data map for the request
    PutDataRequest request = putDataMapRequest.asPutDataRequest();

    // Request the system to create the data item
    Wearable.DataApi.putDataItem(mGoogleApiClient, request)
            .setResultCallback(new ResultCallback() {
                @Override
                public void onResult(DataApi.DataItemResult dataItemResult) {
                    if (!dataItemResult.getStatus().isSuccess()) {
                        Log.e(TAG, "Failed to set the data, "
                                + "status: " + dataItemResult.getStatus()
                                .getStatusCode());
                    }
                }
            });
}

For more information on how to use the Data Layer API, see Sending and Syncing Data.

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!

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.
(Sep 2017 survey)