问题
I am trying to get the data for number of steps walked using google fit. I am implementing the code from this tutorial. I am being asked for the account from which I want to connect google fit. After I select the account, it is not connecting. After I select the account, onActivityResult is called but mApiClient.isConnecting()
&& mApiClient.isConnected()
are both false
and resultCode == RESULT_CANCELED
. Hence, the next alert dialog for requesting permission to access fit data is not being called. I am not able to understand why mApiClient is not connecting. I have followed the steps as shown in the tutorial about creating oauth2, enabling Fitness Api and providing the 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();
}
});
}
}
}
回答1:
This answer helped me figure out how it was to be solved. Add these dependencies to the gradle file. Google has updated ApiClient Libraries and they require google sign in authentication to access the apis
compile 'com.google.android.gms:play-services-fitness:9.0.1'
compile 'com.google.android.gms:play-services-auth:9.0.1'
I am adding the entire code as different errors can give RESULT_CANCELED as the output.
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);
}
}
来源:https://stackoverflow.com/questions/37679476/googleapiclient-not-connecting-while-using-google-fit