lightbulb_outline Please take our October 2018 developer survey. Start survey

在 Android Wear 上检测位置

手表小巧、一览无余的外形特征使得 Android Wear 成为记录、报告和响应用户位置的应用的理想平台。例如,您可以构建应用,为用户提供其运动距离、速度和方向的实时更新信息,或者提供一览无余的用户周边位置队列。

有些手表带有内置 GPS 传感器,可直接检索位置数据,而无需绑定手机。不过,当您在手表应用中请求位置数据时,您不必担心位置数据的来源;系统使用最节能的方法获取数据。然而,正如以下几节中介绍的那样,您的应用需要解决位置数据丢失的问题。

本文介绍如何检查手表内置位置传感器、如何接收位置数据以及如何监控绑定的数据连接。另请参阅与 iPhone 配对的手表的位置数据

:本文假设您了解如何使用 Google Play Services API 检索位置数据

使用 Fused Location Provider

在手表上,您应使用 FusedLocationProviderApi (FLP) 获取位置数据。如果手表不带 GPS 传感器,FLP 将会自动使用手机提供的位置数据。如需了解详细信息,请参阅创建位置信息服务客户端

有关如何请求位置更新和持续跟踪用户位置的信息,请参阅接收位置更新

检测板载 GPS

如果用户佩戴未内置 GPS 传感器的手表出去慢跑,但却忘记携带与之配对的手机,您的手表应用将无法通过绑定连接获取位置数据。您的应用应检测位置并警告用户位置功能不可用。

要确定手表是否带有内置 GPS 传感器,可使用 hasSystemFeature() 函数。以下代码可在您启动某个 Activity 时检测手表是否带有内置 GPS 传感器:

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

处理断开连接 Event

如果手表没有内置 GPS 传感器,则当手表与手机的绑定数据连接断开时,手表的位置数据流将会突然断开。如果您的应用需要不间断的数据流,您的应用必须检测连接是否断开,向用户发出警告,然后妥善地降级功能。

要检测绑定的数据连接是否断开,请使用 NodeApi GetConnectedNodesResult 函数。例如:

  1. 初始化 GoogleApiClient 并创建一个调用 NodeApi 的函数,例如,一个名为 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. 使用以下回调函数获取 inspectNodes 函数的输出结果:
    @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);
    }
    

处理未找到位置事件

当 GPS 信号断开时,您可以检索用户手表的最近已知位置。当您无法修复 GPS 连接,或者手表没有内置 GPS 并与手机断开连接时,检索最近已知位置会很有帮助。如需了解详细信息,请参阅获取最近已知位置

同步数据

如果您的手表应用使用内置 GPS 传感器记录数据,则您可能需要与手持式设备同步位置数据。借助 LocationListener,您可实现 onLocationChanged() 函数以检测和记录位置的变化情况。

适用于手表应用的以下代码可检测位置在何时发生变化,并使用 Data Layer API 存储数据,以供您的手机应用日后检索之用:

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

如需了解如何使用 Data Layer API 的详细信息,请参阅发送和同步数据