1

I am using Google Fit APIs for the first time. I have modified the BasicSensorsApi sample code to calculate steps count. It is working fine, but the problem is when I call GoogleApiClient.disconnect() in onStop() function and then again call GoogleApiClient.connect() in onStart() function, OnDataPointListener stops getting callbacks. I am not unregistering this listener any where.

When I don't call GoogleApiClient.disconnect() it is working fine and I get callbacks event after activity's onStop() function is called.

I am not sure whether I should disconnect GoogleApiClient in onStop() function or not. If yes then how can I solve above problem?

Here is the relavent code:

private void buildFitnessClient() {
    // Create the Google API Client
    mClient = new GoogleApiClient.Builder(this)
            .addApi(Fitness.SENSORS_API)
            .addScope(new Scope(Scopes.FITNESS_LOCATION_READ))
            .addScope(new Scope((Scopes.FITNESS_ACTIVITY_READ)))
            .addScope(new Scope((Scopes.FITNESS_BODY_READ)))
            .addConnectionCallbacks(
                    new GoogleApiClient.ConnectionCallbacks() {

                        @Override
                        public void onConnected(Bundle bundle) {
                            Log.i(TAG, "Connected!!!");
                            // Now you can make calls to the Fitness APIs.
                            // Put application specific code here.
                            findFitnessDataSources();
                        }

                        @Override
                        public void onConnectionSuspended(int i) {
                            // If your connection to the sensor gets lost at some point,
                            // you'll be able to determine the reason and react to it here.
                            if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_NETWORK_LOST) {
                                Log.i(TAG, "Connection lost.  Cause: Network Lost.");
                            } else if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED) {
                                Log.i(TAG, "Connection lost.  Reason: Service Disconnected");
                            }
                        }
                    }
            )
            .addOnConnectionFailedListener(
                    new GoogleApiClient.OnConnectionFailedListener() {
                        // Called whenever the API client fails to connect.
                        @Override
                        public void onConnectionFailed(ConnectionResult result) {
                            Log.i(TAG, "Connection failed. Cause: " + result.toString());
                            if (!result.hasResolution()) {
                                // Show the localized error dialog
                                GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(), MainActivity.this, 0).show();
                                return;
                            }
                            // The failure has a resolution. Resolve it.
                            // Called typically when the app is not yet authorized, and an
                            // authorization dialog is displayed to the user.
                            if (!authInProgress) {
                                try {
                                    Log.i(TAG, "Attempting to resolve failed connection");
                                    authInProgress = true;
                                    result.startResolutionForResult(MainActivity.this, REQUEST_OAUTH);
                                } catch (IntentSender.SendIntentException e) {
                                    Log.e(TAG, "Exception while starting resolution activity", e);
                                }
                            }
                        }
                    }
            )
            .build();
}

@Override
protected void onStart() {
    super.onStart();
    // Connect to the Fitness API
    Log.i(TAG, "Connecting...");
    mClient.connect();
}

@Override
protected void onStop() {
    super.onStop();
    if (mClient.isConnected()) {
        //mClient.disconnect();
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_OAUTH) {
        authInProgress = false;
        if (resultCode == RESULT_OK) {
            // Make sure the app is not already connected or attempting to connect
            if (!mClient.isConnecting() && !mClient.isConnected()) {
                mClient.connect();
            }
        }
    }
}

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putBoolean(AUTH_PENDING, authInProgress);
}

// [END auth_connection_flow_in_activity_lifecycle_methods]

/**
 * Find available data sources and attempt to register on a specific {@link DataType}.
 * If the application cares about a data type but doesn't care about the source of the data,
 * this can be skipped entirely, instead calling
 * {@link com.google.android.gms.fitness.SensorsApi
 * #register(GoogleApiClient, SensorRequest, DataSourceListener)},
 * where the {@link SensorRequest} contains the desired data type.
 */
private void findFitnessDataSources() {
    // [START find_data_sources]
    Fitness.SensorsApi.findDataSources(mClient, new DataSourcesRequest.Builder()
            // At least one datatype must be specified.
            .setDataTypes(DataType.TYPE_STEP_COUNT_CADENCE)
            .setDataTypes(DataType.TYPE_STEP_COUNT_CUMULATIVE)
            .setDataTypes(DataType.TYPE_STEP_COUNT_DELTA)
                    // Can specify whether data type is raw or derived.
            .setDataSourceTypes(DataSource.TYPE_DERIVED)
            .build())
            .setResultCallback(new ResultCallback<DataSourcesResult>() {
                @Override
                public void onResult(DataSourcesResult dataSourcesResult) {
                    Log.i(TAG, "Result: " + dataSourcesResult.getStatus().toString());
                    for (DataSource dataSource : dataSourcesResult.getDataSources()) {
                        Log.i(TAG, "Data source found: " + dataSource.toString());
                        Log.i(TAG, "Data Source type: " + dataSource.getDataType().getName());

                        //Let's register a listener to receive Activity data!
                        if (dataSource.getDataType().equals(DataType.TYPE_STEP_COUNT_CADENCE) && mListener == null) {
                            Log.i(TAG, "Data source for TYPE_STEP_COUNT_CADENCE found!  Registering.");
                            registerFitnessDataListener(dataSource, DataType.TYPE_STEP_COUNT_CADENCE);
                        } else if (dataSource.getDataType().equals(DataType.TYPE_STEP_COUNT_CUMULATIVE) && mListener == null) {
                            Log.i(TAG, "Data source for TYPE_STEP_COUNT_CUMULATIVE found!  Registering.");
                            registerFitnessDataListener(dataSource, DataType.TYPE_STEP_COUNT_CUMULATIVE);
                        } else if (dataSource.getDataType().equals(DataType.TYPE_STEP_COUNT_DELTA) && mListener == null) {
                            Log.i(TAG, "Data source for TYPE_STEP_COUNT_DELTA found!  Registering.");
                            registerFitnessDataListener(dataSource, DataType.TYPE_STEP_COUNT_DELTA);
                        }
                    }
                }
            });
    // [END find_data_sources]
}

/**
 * Register a listener with the Sensors API for the provided {@link DataSource} and
 * {@link DataType} combo.
 */
private void registerFitnessDataListener(DataSource dataSource, DataType dataType) {
    // [START register_data_listener]
    mListener = new OnDataPointListener() {
        @Override
        public void onDataPoint(DataPoint dataPoint) {
            for (Field field : dataPoint.getDataType().getFields()) {
                Value val = dataPoint.getValue(field);
                Log.i(TAG, "Detected DataPoint field: " + field.getName());
                Log.i(TAG, "Detected DataPoint value: " + val);
            }
        }
    };

    Fitness.SensorsApi.add(
            mClient,
            new SensorRequest.Builder()
                    .setDataSource(dataSource) // Optional but recommended for custom data sets.
                    .setDataType(dataType) // Can't be omitted.
                    .setSamplingRate(10, TimeUnit.SECONDS)
                    .build(),
            mListener)
            .setResultCallback(new ResultCallback<Status>() {
                @Override
                public void onResult(Status status) {
                    if (status.isSuccess()) {
                        Log.i(TAG, "Listener registered!");
                    } else {
                        Log.i(TAG, "Listener not registered.");
                    }
                }
            });
    // [END register_data_listener]
}
4

2 回答 2

1

如果您在前台跟踪步数,那么这是正确的行为,因为您在 onstop() 中断开了 google api 客户端。一旦 GoogleApiClient 断开连接,所有侦听器将从 GoogleApiClient 中删除。但是,如果您希望在后台跟踪步数,那么您可能必须将您的实现移至服务并确定您想要断开与 GoogleApiclient 的确切时间。

于 2015-06-15T06:41:30.557 回答
0

与文档相反,您必须在 onDestroy 而不是 onStop 中断开连接。在 onCreate 中连接,在 onStop/onStart 中什么也不做。

为什么?

因为等待调用 onConnect 的应用程序不会阻止调用 onStop。发生的情况是在您的应用接收事件之前调用 onStop 。然后,当然,它会断开连接并且永远不会得到它。

于 2015-11-22T19:08:45.283 回答