使用 google fit 时 GoogleApiClient 未连接

GoogleApiClient not connecting while using google fit

我正在尝试使用 google 拟合获取步行步数的数据。我正在实现此 tutorial 中的代码。我被要求提供我想要连接的帐户 google 适合。我 select 帐户后,它连接不上。在我 select 帐户之后, onActivityResult 被调用但是 mApiClient.isConnecting() && mApiClient.isConnected() 都是 falseresultCode == RESULT_CANCELED 。因此,不会调用下一个请求访问拟合数据权限的警告对话框。我无法理解为什么 mApiClient 没有连接。我已按照有关创建 oauth2、启用 Fitness Api 并提供 keyStore.

的教程中所示的步骤进行操作
public class MainActivity extends AppCompatActivity implements OnDataPointListener,
    GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener {

private static final int REQUEST_OAUTH = 1;
private static final String AUTH_PENDING = "auth_state_pending";
private boolean authInProgress = false;
private GoogleApiClient mApiClient;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    if (savedInstanceState != null) {
        authInProgress = savedInstanceState.getBoolean(AUTH_PENDING);
    }

    mApiClient = new GoogleApiClient.Builder(this)
            .addApi(Fitness.SENSORS_API)
            .addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE))
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .build();
}

@Override
protected void onStart() {
    super.onStart();
    mApiClient.connect();
}

@Override
protected void onStop() {
    super.onStop();

    Fitness.SensorsApi.remove( mApiClient, this )
            .setResultCallback(new ResultCallback<Status>() {
                @Override
                public void onResult(Status status) {
                    if (status.isSuccess()) {
                        mApiClient.disconnect();
                    }
                }
            });
}

private void registerFitnessDataListener(DataSource dataSource, DataType dataType) {

    SensorRequest request = new SensorRequest.Builder()
            .setDataSource( dataSource )
            .setDataType( dataType )
            .setSamplingRate( 3, TimeUnit.SECONDS )
            .build();

    Fitness.SensorsApi.add(mApiClient, request, this)
            .setResultCallback(new ResultCallback<Status>() {
                @Override
                public void onResult(Status status) {
                    if (status.isSuccess()) {
                        Log.e("GoogleFit", "SensorApi successfully added");
                    } else {
                        Log.e("GoogleFit", "adding status: " + status.getStatusMessage());
                    }
                }
            });
}

@Override
public void onConnected(Bundle bundle) {
    DataSourcesRequest dataSourceRequest = new DataSourcesRequest.Builder()
            .setDataTypes( DataType.TYPE_STEP_COUNT_CUMULATIVE )
            .setDataSourceTypes( DataSource.TYPE_RAW )
            .build();

    ResultCallback<DataSourcesResult> dataSourcesResultCallback = new ResultCallback<DataSourcesResult>() {
        @Override
        public void onResult(DataSourcesResult dataSourcesResult) {
            for( DataSource dataSource : dataSourcesResult.getDataSources() ) {
                if( DataType.TYPE_STEP_COUNT_CUMULATIVE.equals( dataSource.getDataType() ) ) {
                    registerFitnessDataListener(dataSource, DataType.TYPE_STEP_COUNT_CUMULATIVE);
                }
            }
        }
    };

    Fitness.SensorsApi.findDataSources(mApiClient, dataSourceRequest)
            .setResultCallback(dataSourcesResultCallback);
}

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
    if( !authInProgress ) {
        try {
            authInProgress = true;
            connectionResult.startResolutionForResult( MainActivity.this, REQUEST_OAUTH );
        } catch(IntentSender.SendIntentException e ) {
            Log.e( "GoogleFit", "sendingIntentException " + e.getMessage() );
        }
    } else {
        Log.e( "GoogleFit", "authInProgress" );
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if( requestCode == REQUEST_OAUTH ) {
        authInProgress = false;
        if( resultCode == RESULT_OK ) {
            if( !mApiClient.isConnecting() && !mApiClient.isConnected() ) {
                mApiClient.connect();
            }
        } else if( resultCode == RESULT_CANCELED ) {
            Log.e( "GoogleFit", "RESULT_CANCELED" );
        }
    } else {
        Log.e("GoogleFit", "requestCode NOT request_oauth");
    }
}

@Override
public void onConnectionSuspended(int i) {
}

@Override
public void onDataPoint(DataPoint dataPoint) {
    for( final Field field : dataPoint.getDataType().getFields() ) {
        final Value value = dataPoint.getValue( field );
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(getApplicationContext(), "Field: " + field.getName() + " Value: " + value, Toast.LENGTH_SHORT).show();
            }
        });
    }
  }
}

回答帮助我弄清楚了它是如何解决的。将这些依赖项添加到 gradle 文件中。 Google 已更新 ApiClient 库,它们需要 google 登录身份验证才能访问 API

compile 'com.google.android.gms:play-services-fitness:9.0.1'
compile 'com.google.android.gms:play-services-auth:9.0.1'

我添加了整个代码,因为不同的错误可能会给出 RESULT_CANCELED 作为输出。

public class MainActivity extends Activity implements GoogleApiClient.OnConnectionFailedListener,
GoogleApiClient.ConnectionCallbacks, OnDataPointListener {
private static final String TAG = "CCC";
private static final String AUTH_PENDING = "isAuthPending";
GoogleApiClient googleApiClient;
private boolean authInProgress = false;

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

    //authInProgress code is useful because the onStop may be called while authentication is not complete.
    //In such case this tells it to complete it
    if (savedInstanceState != null) {
        authInProgress = savedInstanceState.getBoolean(AUTH_PENDING);
    }
}

@Override
protected void onStart() {
    super.onStart();
    //very important that the following lines are called in onStart
    //when they are called in onCreate, when the permission fragment opens up, onStop gets called which disconnects the api client.
    //after which it needs to be reConnected which does not happen as the apiClient is built in onCreate
    //Hence these should be called in onStart or probably onResume.
    googleApiClient = googleFitBuild(this, this, this);
    googleFitConnect(this, googleApiClient);
}

public static GoogleApiClient googleFitBuild(Activity activity, GoogleApiClient.ConnectionCallbacks connectionCallbacks, GoogleApiClient.OnConnectionFailedListener failedListener){
    GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestEmail()
            .requestScopes(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE))
            .build();

    return new GoogleApiClient.Builder(activity)
//without GOOGLE_SIGN_IN_API, RESULT_CANCELED is always the output
//The new version of google Fit requires that the user authenticates with gmail account
            .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
            .addConnectionCallbacks(connectionCallbacks)
            .addOnConnectionFailedListener(failedListener)
            .addApi(Fitness.HISTORY_API)
            .addApi(Fitness.SESSIONS_API)
            .addApi(Fitness.RECORDING_API)
            .addApi(Fitness.SENSORS_API)
            .build();
}

//runs an automated Google Fit connect sequence
public static void googleFitConnect(final Activity activity, final GoogleApiClient mGoogleApiClient){
    Log.d(TAG, "google fit connect called");
    if(!mGoogleApiClient.isConnected() && !mGoogleApiClient.isConnecting()) {
        mGoogleApiClient.registerConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
            @Override
            public void onConnected(Bundle bundle) {
                Log.d(TAG, "Google API connected");
                Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
                activity.startActivityForResult(signInIntent, 1);
            }
            @Override
            public void onConnectionSuspended(int i) {

            }
        });
        mGoogleApiClient.connect(GoogleApiClient.SIGN_IN_MODE_OPTIONAL);
    }
}

@Override
public void onConnected(@Nullable Bundle bundle) {
    Log.d(TAG, "onConnected called");
    DataSourcesRequest dataSourceRequest = new DataSourcesRequest.Builder()
            .setDataTypes(DataType.TYPE_STEP_COUNT_CUMULATIVE)
            .setDataSourceTypes(DataSource.TYPE_RAW)
            .build();
    Log.d(TAG, "DataSourcetype: " + dataSourceRequest.getDataTypes().toString());

    ResultCallback<DataSourcesResult> dataSourcesResultCallback = new ResultCallback<DataSourcesResult>() {
        @Override
        public void onResult(DataSourcesResult dataSourcesResult) {
            Log.d(TAG, "onResult in Result Callback called");
            for( DataSource dataSource : dataSourcesResult.getDataSources() ) {
                if(DataType.TYPE_STEP_COUNT_CUMULATIVE.equals(dataSource.getDataType())) {
                    Log.d(TAG, "type step");
                    registerStepsDataListener(dataSource, DataType.TYPE_STEP_COUNT_CUMULATIVE);
                }
            }
        }
    };

    Fitness.SensorsApi.findDataSources(googleApiClient, dataSourceRequest)
            .setResultCallback(dataSourcesResultCallback);
}

@Override
public void onConnectionSuspended(int i) {
    Log.d(TAG, "Connection suspended i= " + i);
}

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
    if( !authInProgress ) {
        Log.d(TAG, "!AUTHINPROG");
        try {
            authInProgress = true;
            connectionResult.startResolutionForResult(this, 1);
        } catch(IntentSender.SendIntentException e ) {
            Log.d(TAG, "SendIntentExc: " + e.toString());
        }
    } else {
        Log.d(TAG, "authInProgress" );
    }
}

private void registerStepsDataListener(DataSource dataSource, DataType dataType) {

    SensorRequest request = new SensorRequest.Builder()
            .setDataSource(dataSource)
            .setDataType(dataType)
            .setSamplingRate(3, TimeUnit.SECONDS )
            .build();

    Fitness.SensorsApi.add(googleApiClient, request, this)
            .setResultCallback(new ResultCallback<Status>() {
                @Override
                public void onResult(Status status) {
                    if (status.isSuccess()) {
                        Log.d(TAG, "SensorApi successfully added" );
                    }
                }
            });
}

@Override
public void onDataPoint(DataPoint dataPoint) {
    for( final Field field : dataPoint.getDataType().getFields() ) {
        final Value value = dataPoint.getValue( field );
        Log.d(TAG, "Field Name: " + field.getName() + " Value: " + value.toString());
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(MainActivity.this, "Field: " + field.getName() + " Value: " + value, Toast.LENGTH_SHORT).show();
            }
        });
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    Log.d(TAG, "OnActivityResult called");
    if( requestCode == 1) {
        authInProgress = false;
        if( resultCode == RESULT_OK ) {
            Log.d(TAG, "Result_OK");
            if( !googleApiClient.isConnecting() && !googleApiClient.isConnected() ) {
                Log.d(TAG, "Calling googleApiClient.connect again");
                googleApiClient.connect(GoogleApiClient.SIGN_IN_MODE_OPTIONAL);
            } else {
                onConnected(null);
            }
        } else if( resultCode == RESULT_CANCELED ) {
            Log.d( TAG, "RESULT_CANCELED" );
        }
    } else {
        Log.d(TAG, "requestCode NOT request_oauth");
    }
}

@Override
protected void onStop() {
    Log.d(TAG, "Onstop called");
    super.onStop();

    Fitness.SensorsApi.remove( googleApiClient, this )
            .setResultCallback(new ResultCallback<Status>() {
                @Override
                public void onResult(Status status) {
                    if (status.isSuccess()) {
                        googleApiClient.disconnect();
                    }
                }
            });
}

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    Log.d(TAG, "Onsaveinstance called");
    outState.putBoolean(AUTH_PENDING, authInProgress);
}
}