Google Fit API- Can't make it works - android

After a lot of research, mostly because I can't understand google documentation, I came up with this example:
public class MainActivity extends Activity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private static final String TAG = "FitActivity";
//[START Auth_Variable_References]
private static final int REQUEST_OAUTH = 1;
// [END auth_variable_references]
private GoogleApiClient mClient = null;
int mInitialNumberOfSteps = 0;
private TextView mStepsTextView;
private boolean mFirstCount = true;
// Create Builder View
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
mStepsTextView = (TextView) findViewById(R.id.steps);
}
private void connectFitness() {
Toast.makeText(this, "connecting", Toast.LENGTH_LONG);
Log.i(TAG, "Connecting...");
// Create the Google API Client
mClient = new GoogleApiClient.Builder(this)
// select the Fitness API
.addApi(Fitness.SENSORS_API)
.addApi(Fitness.RECORDING_API)
.addApi(Fitness.SESSIONS_API)
.addApi(Fitness.HISTORY_API)
// specify the scopes of access
.addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ))
.addScope(new Scope(Scopes.FITNESS_LOCATION_READ))
.addScope(new Scope(Scopes.FITNESS_BODY_READ_WRITE))
// provide callbacks
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
// Connect the Google API client
mClient.connect();
}
// Manage OAuth authentication
#Override
public void onConnectionFailed(ConnectionResult result) {
Toast.makeText(this, "failed", Toast.LENGTH_LONG);
// Error while connecting. Try to resolve using the pending intent returned.
if (result.getErrorCode() == ConnectionResult.SIGN_IN_REQUIRED ||
result.getErrorCode() == FitnessStatusCodes.NEEDS_OAUTH_PERMISSIONS) {
try {
// Request authentication
result.startResolutionForResult(this, REQUEST_OAUTH);
} catch (IntentSender.SendIntentException e) {
Log.e(TAG, "Exception connecting to the fitness service", e);
}
} else {
Log.e(TAG, "Unknown connection issue. Code = " + result.getErrorCode());
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_OAUTH) {
if (resultCode == RESULT_OK) {
// If the user authenticated, try to connect again
mClient.connect();
}
}
}
#Override
public void onConnectionSuspended(int i) {
// If your connection gets lost at some point,
// you'll be able to determine the reason and react to it here.
Toast.makeText(this, "suspended", Toast.LENGTH_LONG);
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");
}
}
#Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "Connected!");
Toast.makeText(this, "connected", Toast.LENGTH_LONG);
// Now you can make calls to the Fitness APIs.
invokeFitnessAPIs();
}
private void invokeFitnessAPIs() {
getStepsToday();
}
private void getStepsToday() {
Calendar cal = Calendar.getInstance();
Date now = new Date();
cal.setTime(now);
long endTime = cal.getTimeInMillis();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
long startTime = cal.getTimeInMillis();
final DataReadRequest readRequest = new DataReadRequest.Builder()
.read(DataType.TYPE_STEP_COUNT_DELTA)
.setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS)
.build();
DataReadResult dataReadResult =
Fitness.HistoryApi.readData(mClient, readRequest).await(1, TimeUnit.MINUTES);
DataSet stepData = dataReadResult.getDataSet(DataType.TYPE_STEP_COUNT_DELTA);
int totalSteps = 0;
for (DataPoint dp : stepData.getDataPoints()) {
for(Field field : dp.getDataType().getFields()) {
int steps = dp.getValue(field).asInt();
totalSteps += steps;
}
}
TextView steps = (TextView)findViewById(R.id.steps);
steps.setText(totalSteps);
}
// Update the Text Viewer with Counter of Steps..
private void updateTextViewWithStepCounter(final int numberOfSteps) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getBaseContext(), "On Datapoint!", Toast.LENGTH_SHORT);
if(mFirstCount && (numberOfSteps != 0)) {
mInitialNumberOfSteps = numberOfSteps;
mFirstCount = false;
}
if(mStepsTextView != null){
mStepsTextView.setText(String.valueOf(numberOfSteps - mInitialNumberOfSteps));
}
}
});
}
//Start
#Override
protected void onStart() {
super.onStart();
mFirstCount = true;
mInitialNumberOfSteps = 0;
if (mClient == null || !mClient.isConnected()) {
connectFitness();
}
}
//Stop
#Override
protected void onStop() {
super.onStop();
if(mClient.isConnected() || mClient.isConnecting()) mClient.disconnect();
mInitialNumberOfSteps = 0;
mFirstCount = true;
}
I noticed by the logs is that this code don't call any of the google fitmethods. Can somebody help me? Also where do I put my OAuth 2.0 info? I'm really lost in this, even some explanations about the Google API itself would be helpful.

After a lot of research I came up with this recent tutorial and library.

Related

Android GPS - Submitting highscore to leaderboard

I'm trying to submit a highscore to my leaderboards, but for some reason it doesn't work. The app doesn't crash and there is no error in the logcat.
When the user isn't logged in there will be a pop-up of Google Play Games. Currently when a user gets a new highscore the app automatically shows the toast. So it seems my Asynctask is not correctly coded?
public class result extends AppCompatActivity implements GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks{
public GoogleApiClient mGoogleApiClient;
private static int RC_SIGN_IN = 9001;
private boolean mResolvingConnectionFailure = false;
private boolean mAutoStartSignInFlow = true;
private boolean mSignInClicked = false;
public int HighScore;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_result);
// Create the Google Api Client with access to the Play Games services
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Games.API).addScope(Games.SCOPE_GAMES)
// add other APIs and scopes here as needed
.build();
TextView scoreLabel = (TextView) findViewById(R.id.scoreLabel);
TextView highScoreLabel = (TextView) findViewById(R.id.highScoreLabel);
int score = getIntent().getIntExtra("SCORE", 0);
scoreLabel.setText(score + "");
SharedPreferences settings = getSharedPreferences("HIGH_SCORE", Context.MODE_PRIVATE);
HighScore = settings.getInt("HIGH_SCORE", 0);
if (score > HighScore) {
highScoreLabel.setText("High Score : " + score);
submitScore(score);
// Update High Score
SharedPreferences.Editor editor = settings.edit();
editor.putInt("HIGH_SCORE", score);
editor.commit();
} else {
highScoreLabel.setText("High Score : " + HighScore);
}
}
public void tryAgain(View view) {
startActivity(new Intent(getApplicationContext(), start.class));
}
// Disable Return Button
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_BACK:
return true;
}
}
return super.dispatchKeyEvent(event);
}
public class LoadData extends AsyncTask<Void, Void, Void> {
ProgressDialog pdLoading = new ProgressDialog(result.this);
//declare other objects as per your need
#Override
protected void onPreExecute()
{
pdLoading.setMessage("\tSending highscore to leaderboard...");
pdLoading.show();
//do initialization of required objects objects here
};
#Override
protected Void doInBackground(Void... params)
{
Games.Leaderboards.submitScoreImmediate(mGoogleApiClient, getString(R.string.leaderboard_top_players), HighScore);
//do loading operation here
return null;
}
#Override
protected void onPostExecute(Void result)
{
super.onPostExecute(result);
pdLoading.dismiss();
};
}
//Start GPS
#Override
public void onConnected(#Nullable Bundle bundle) {
}
#Override
public void onConnectionSuspended(int i) {
// Attempt to reconnect
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
if (mResolvingConnectionFailure) {
// Already resolving
return;
}
// If the sign in button was clicked or if auto sign-in is enabled,
// launch the sign-in flow
if (mSignInClicked || mAutoStartSignInFlow) {
mAutoStartSignInFlow = false;
mSignInClicked = false;
mResolvingConnectionFailure = true;
// Attempt to resolve the connection failure using BaseGameUtils.
// The R.string.signin_other_error value should reference a generic
// error string in your strings.xml file, such as "There was
// an issue with sign in, please try again later."
if (!BaseGameUtils.resolveConnectionFailure(this,
mGoogleApiClient, connectionResult,
RC_SIGN_IN, getString(R.string.signin_other_error))) {
mResolvingConnectionFailure = false;
}
}
// Put code here to display the sign-in button
}
public void submitScore(long highscore){
if (mGoogleApiClient.isConnected()){
LoadData task = new LoadData();
task.execute();
//Games.Leaderboards.submitScoreImmediate(mGoogleApiClient, getString(R.string.leaderboard_top_players), highscore);
}else{
Toast.makeText(this, "Unable to submit highscore", Toast.LENGTH_SHORT).show();
}
}
#Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
#Override
protected void onStop() {
super.onStop();
mGoogleApiClient.disconnect();
}
protected void onActivityResult(int requestCode, int resultCode,
Intent intent) {
if (requestCode == RC_SIGN_IN) {
mSignInClicked = false;
mResolvingConnectionFailure = false;
if (resultCode == RESULT_OK) {
mGoogleApiClient.connect();
} else {
// Bring up an error dialog to alert the user that sign-in
// failed. The R.string.signin_failure should reference an error
// string in your strings.xml file that tells the user they
// could not be signed in, such as "Unable to sign in."
BaseGameUtils.showActivityResultError(this,
requestCode, resultCode, R.string.signin_failure);
}
}
}
}
You seem to be declaring mGoogleAPIClient but not actually creating an instance of it, hence your 'NullPointerException'
Before you try to use mGoogleAPIClient, add the following to create it.....
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Games.API).addScope(Games.SCOPE_GAMES)
// add other APIs and scopes here as needed
.build();
See Here for more details
Hope this helps

creating geofences in background service

I'm making an android application in which want to create a Geofence at LatLong coordinates specified at my server.
The coordinates are getting updated periodically in background from within a service. I'm reading these coordinates and wish to create a Geofence for it in background without user intervention. I tried doing so within a service but it's not working. I can get the coordinates from the server at regular intervals but I'm not able to create Geofence for it, getting a nullPointerException.
However, I'm able to create Geofences in an Activity on click of a button(hardcoding LatLong coordinates) but its not working in a service.
My service:
public class GPSPollingService extends Service implements ResultCallback<Status>, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
private GoogleApiClient mGoogleApiClient;
private PowerManager.WakeLock mWakeLock;
private LocationRequest mLocationRequest;
// Flag that indicates if a request is underway.
private boolean mInProgress;
private final String TAG = "GPSPollingService";
private PendingIntent mGeofencePendingIntent;
String url = "http://shielded.coolpage.biz/status_read.php";
private static final int REQUEST_CODE_LOCATION = 2;
private Boolean servicesAvailable = false;
private Activity mActivity;
ArrayList<Geofence> mCurrentGeofences = new ArrayList<Geofence>();;
RequestQueue requestQueue;
Location mLocation;
public GPSPollingService(){}
public GPSPollingService(Activity mActivity){
super();
this.mActivity = mActivity;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
mInProgress = false;
requestQueue = Volley.newRequestQueue(this);
// Instantiate the current List of geofences
mCurrentGeofences = new ArrayList<Geofence>();
mGeofencePendingIntent = null;
setUpLocationClientIfNeeded();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
mGoogleApiClient.connect();
Log.d(TAG,"onStartCommand: ");
PowerManager mgr = (PowerManager)getSystemService(Context.POWER_SERVICE);
/*
WakeLock is reference counted so we don't want to create multiple WakeLocks. So do a check before initializing and acquiring.
This will fix the "java.lang.Exception: WakeLock finalized while still held: MyWakeLock" error that you may find.
*/
if (this.mWakeLock == null) { //**Added this
this.mWakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakeLock");
}
if (!this.mWakeLock.isHeld()) { //**Added this
this.mWakeLock.acquire();
}
if(!servicesAvailable || mGoogleApiClient.isConnected() || mInProgress)
return START_STICKY;
setUpLocationClientIfNeeded();
if(!mGoogleApiClient.isConnected() || !mGoogleApiClient.isConnecting() && !mInProgress)
{
//appendLog(DateFormat.getDateTimeInstance().format(new Date()) + ": Started", Constants.LOG_FILE);
mInProgress = true;
mGoogleApiClient.connect();
}
return START_STICKY;
}
private void setUpLocationClientIfNeeded()
{
if(mGoogleApiClient == null)
googleApiClientBuild();
}
protected synchronized void googleApiClientBuild(){
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
#Override
public void onConnected(#Nullable Bundle bundle) {
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(120000); // Update location every 60 seconds
Log.d(TAG,"in onConnected: ");
if ( ContextCompat.checkSelfPermission( this, android.Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED ) {
ActivityCompat.requestPermissions( mActivity, new String[] { android.Manifest.permission.ACCESS_COARSE_LOCATION },
REQUEST_CODE_LOCATION );
}else {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
//Location mLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
//txtOutput.setText(mLocation.toString());
Log.d(TAG, "calling fusedLocationApi");
}
continueAddGeofences();
}
#Override
public void onConnectionSuspended(int i) {
// Turn off the request flag
mInProgress = false;
// Destroy the current location client
mGoogleApiClient = null;
Log.d(TAG, "onConnectionSuspended ");
}
#Override
public void onLocationChanged(Location location) {
mLocation = location;
Log.d(TAG,"in onLocationChanged: ");
Log.d(TAG, mLocation.toString());
// save new location to db
connectToDb(); // checking for status 1
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
mInProgress = false;
Log.d(TAG, "onConnectionFailed");
/*
* Google Play services can resolve some errors it detects.
* If the error has a resolution, try sending an Intent to
* start a Google Play services activity that can resolve
* error.
*/
if (connectionResult.hasResolution()) {
Log.d(TAG, "google play services has solution");
// If no resolution is available, display an error dialog
} else {
Log.d(TAG, "no solution for connection failure");
}
}
#Override
public void onDestroy() {
// Turn off the request flag
this.mInProgress = false;
if (this.servicesAvailable && this.mGoogleApiClient != null) {
this.mGoogleApiClient.unregisterConnectionCallbacks(this);
this.mGoogleApiClient.unregisterConnectionFailedListener(this);
this.mGoogleApiClient.disconnect();
// Destroy the current location client
this.mGoogleApiClient = null;
}
// Display the connection status
// Toast.makeText(this, DateFormat.getDateTimeInstance().format(new Date()) + ":
// Disconnected. Please re-connect.", Toast.LENGTH_SHORT).show();
if (this.mWakeLock != null) {
this.mWakeLock.release();
this.mWakeLock = null;
}
super.onDestroy();
}
public void connectToDb(){
StringRequest stringRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
#Override
public void onResponse(String s) {
Toast.makeText(getApplicationContext() , ""+s,Toast.LENGTH_LONG).show();
Log.d(TAG, ""+s);
try {
JSONObject jsonObject = new JSONObject(s);
JSONArray jsonArray = jsonObject.getJSONArray("result");
if(jsonArray.length()!=0){
Log.d(TAG,"array length not 0");
JSONObject personInDanger = jsonArray.getJSONObject(0);
setGeofence(Double.valueOf(personInDanger.getString("latitude")), Double.valueOf(personInDanger.getString("longitude")));
}
}catch (JSONException je) {
// do something with it
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
Toast.makeText(getApplicationContext(), ""+volleyError, Toast.LENGTH_LONG).show();
}
});
requestQueue.add(stringRequest);
}
/**
* Verify that Google Play services is available before making a request.
*
* #return true if Google Play services is available, otherwise false
*/
private boolean servicesConnected() {
// Check that Google Play services is available
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
// If Google Play services is available
if (ConnectionResult.SUCCESS == resultCode) {
// In debug mode, log the status
Log.d(GeofenceUtils.APPTAG, getString(R.string.play_services_available));
// Continue
return true;
// Google Play services was not available for some reason
} else {
// Display an error dialog
Toast.makeText(getApplicationContext(), "Google play services not available", Toast.LENGTH_SHORT).show();
//Dialog dialog = GooglePlayServicesUtil.getErrorDialog(resultCode, (Activity) getApplicationContext(), 0);
//if (dialog != null) {
// ErrorDialogFragment errorFragment = new ErrorDialogFragment();
// errorFragment.setDialog(dialog);
// errorFragment.show(getSupportFragmentManager(), GeofenceUtils.APPTAG);
}
return false;
}
public void setGeofence(Double latitude , Double longitude){
Log.d(TAG, "in setGeofence");
if (!servicesConnected()) {
return;
}
SimpleGeofence newGeofence = new SimpleGeofence(
"1",
// Get latitude, longitude, and radius from the db
latitude,
longitude,
Float.valueOf("50.0"),
// Set the expiration time
Geofence.NEVER_EXPIRE,
// Detect both entry and exit transitions
Geofence.GEOFENCE_TRANSITION_ENTER
);
mCurrentGeofences.add(newGeofence.toGeofence());
// Start the request. Fail if there's already a request in progress
try {
// Try to add geofences
addGeofences(mCurrentGeofences);
} catch (UnsupportedOperationException e) {
// Notify user that previous request hasn't finished.
Toast.makeText(this, R.string.add_geofences_already_requested_error,
Toast.LENGTH_LONG).show();
}
}
public void addGeofences(ArrayList<Geofence> geofences) throws UnsupportedOperationException {
if (!mInProgress) {
// Toggle the flag and continue
mInProgress = true;
// Request a connection to Location Services
requestConnection();
// If a request is in progress
} else {
// Throw an exception and stop the request
throw new UnsupportedOperationException();
}
}
private void requestConnection() {
getLocationClient().connect();
}
private GoogleApiClient getLocationClient() {
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(mActivity)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
return mGoogleApiClient;
}
private void continueAddGeofences() {
// Get a PendingIntent that Location Services issues when a geofence transition occurs
mGeofencePendingIntent = createRequestPendingIntent();
if (!mGoogleApiClient.isConnected()) {
Toast.makeText(mActivity, "not connected", Toast.LENGTH_SHORT).show();
return;
}
try {
LocationServices.GeofencingApi.addGeofences(
mGoogleApiClient,
// The GeofenceRequest object.
mCurrentGeofences,
// A pending intent that that is reused when calling removeGeofences(). This
// pending intent is used to generate an intent when a matched geofence
// transition is observed.
mGeofencePendingIntent
).setResultCallback(this); // Result processed in onResult().
} catch (SecurityException securityException) {
// Catch exception generated if the app does not use ACCESS_FINE_LOCATION permission.
logSecurityException(securityException);
}
}
private void logSecurityException(SecurityException securityException) {
Log.e(GeofenceUtils.APPTAG , "Invalid location permission. " +
"You need to use ACCESS_FINE_LOCATION with geofences", securityException);
}
public void onResult(Status status) {
Intent broadcastIntent = new Intent();
// Temp storage for messages
String msg;
if (status.isSuccess()) {
Toast.makeText(
mActivity, "Geofences added",
Toast.LENGTH_SHORT
).show();
msg = mActivity.getString(R.string.add_geofences_result_success, status);
// In debug mode, log the result
Log.d(GeofenceUtils.APPTAG, msg);
// Create an Intent to broadcast to the app
broadcastIntent.setAction(GeofenceUtils.ACTION_GEOFENCES_ADDED)
.addCategory(GeofenceUtils.CATEGORY_LOCATION_SERVICES)
.putExtra(GeofenceUtils.EXTRA_GEOFENCE_STATUS, msg);
// If adding the geofences failed
} else {
/*
* Create a message containing the error code and the list
* of geofence IDs you tried to add
*/
msg = mActivity.getString(
R.string.add_geofences_result_failure,
status.getStatusCode(), status.getStatusMessage());
// Log an error
Log.e(GeofenceUtils.APPTAG, msg);
}
}
private PendingIntent createRequestPendingIntent() {
// If the PendingIntent already exists
if (null != mGeofencePendingIntent) {
// Return the existing intent
return mGeofencePendingIntent;
// If no PendingIntent exists
} else {
Intent intent = new Intent("com.example.android.geofence.ACTION_RECEIVE_GEOFENCE");
return PendingIntent.getBroadcast(
mActivity,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT);
}
}
}
My logs:
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
at android.app.PendingIntent.getBroadcastAsUser(PendingIntent.java:506)
at android.app.PendingIntent.getBroadcast(PendingIntent.java:495)
at com.example.android.safetyalert.GPSPollingService.createRequestPendingIntent(GPSPollingService.java:449)
at com.example.android.safetyalert.GPSPollingService.continueAddGeofences(GPSPollingService.java:369)
at com.example.android.safetyalert.GPSPollingService.onConnected(GPSPollingService.java:163)
at com.google.android.gms.common.internal.zzl.zzm(Unknown Source)
at com.google.android.gms.internal.zzof.zzk(Unknown Source)
at com.google.android.gms.internal.zzod.zzsb(Unknown Source)
at com.google.android.gms.internal.zzod.onConnected(Unknown Source)
at com.google.android.gms.internal.zzoh.onConnected(Unknown Source)
at com.google.android.gms.internal.zznw.onConnected(Unknown Source)
at com.google.android.gms.common.internal.zzk$1.onConnected(Unknown Source)
at com.google.android.gms.common.internal.zzd$zzj.zztp(Unknown Source)
at com.google.android.gms.common.internal.zzd$zza.zzc(Unknown Source)
at com.google.android.gms.common.internal.zzd$zza.zzw(Unknown Source)
at com.google.android.gms.common.internal.zzd$zze.zztr(Unknown Source)
at com.google.android.gms.common.internal.zzd$zzd.handleMessage(Unknown Source)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5312)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:901)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:696)
I have tried everything I could think of.
I'm polling the GPS in order to provide accurate location to the OS to increase the accuracy of geofencing. I know it will drain my battery but for now that's not a problem.
Service already has Context. You shouldn't use Context from the Activity because if your Activity is killed mActivity will be null causing all sort of issues. Replace else block in createRequestPendingIntent with this
} else {
Intent intent = new Intent("com.example.android.geofence.ACTION_RECEIVE_GEOFENCE");
return PendingIntent.getBroadcast(
this,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT);
}

GoogleFit wasn't able to connect, so the request failed-Android

I have the following code where it does two main things.
It connects to google play services.
Inside the onConnected() method a service is started, by calling the startService(...) method.
When I run the program I get the following log message.
Connected!!!
Fit wasn't able to connect, so the request failed.
GoogleFitService destroyed.
Here is my code:
public class MainActivity extends ActionBarActivity {
public final static String TAG = "GoogleFitService";
private static final int REQUEST_OAUTH = 1;
private static final String AUTH_PENDING = "auth_state_pending";
private boolean authInProgress = false;
private GoogleApiClient mClient = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buildFitnessClient();
}
private void buildFitnessClient() {
// Create the Google API Client
mClient = new GoogleApiClient.Builder(this)
.addApi(Fitness.API)
.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.
Intent service = new Intent(MainActivity.this,
GoogleFitService.class);
service.putExtra(GoogleFitService.SERVICE_REQUEST_TYPE,
GoogleFitService.TYPE_REQUEST_CONNECTION);
startService(service);
}
#Override
public void onConnectionSuspended(int i) {
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;
}
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();
Intent service = new Intent(this, GoogleFitService.class);
service.putExtra(GoogleFitService.SERVICE_REQUEST_TYPE, GoogleFitService.TYPE_REQUEST_CONNECTION);
startService(service);
}
#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);
}
}
And the second class is basically an Intent service. Maybe the mistake is here.
public class GoogleFitService extends IntentService {
public static final String TAG = "GoogleFitService";
private GoogleApiClient mGoogleApiFitnessClient;
private boolean mTryingToConnect = false;
public static final String SERVICE_REQUEST_TYPE = "requestType";
public static final int TYPE_GET_STEP_TODAY_DATA = 1;
public static final int TYPE_REQUEST_CONNECTION = 2;
public static final String HISTORY_INTENT = "fitHistory";
public static final String HISTORY_EXTRA_STEPS_TODAY = "stepsToday";
public static final String FIT_NOTIFY_INTENT = "fitStatusUpdateIntent";
public static final String FIT_EXTRA_CONNECTION_MESSAGE =
"fitFirstConnection";
public static final String FIT_EXTRA_NOTIFY_FAILED_STATUS_CODE =
"fitExtraFailedStatusCode";
public static final String FIT_EXTRA_NOTIFY_FAILED_INTENT =
"fitExtraFailedIntent";
#Override
public void onDestroy() {
Log.d(TAG, "GoogleFitService destroyed");
if (mGoogleApiFitnessClient.isConnected()) {
Log.d(TAG, "Disconecting Google Fit.");
mGoogleApiFitnessClient.disconnect();
}
super.onDestroy();
}
#Override
public void onCreate() {
super.onCreate();
buildFitnessClient();
Log.d(TAG, "GoogleFitService created");
}
public GoogleFitService() {
super("GoogleFitService");
}
#Override
protected void onHandleIntent(Intent intent) {
//Get the request type
int type = intent.getIntExtra(SERVICE_REQUEST_TYPE, 1);
//block until google fit connects. Give up after 10 seconds.
if (!mGoogleApiFitnessClient.isConnected()) {
mTryingToConnect = true;
mGoogleApiFitnessClient.connect();
//Wait until the service either connects or fails to connect
while (mTryingToConnect) {
try {
Thread.sleep(100, 0);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
if (mGoogleApiFitnessClient.isConnected()) {
if (type == TYPE_GET_STEP_TODAY_DATA) {
Log.d(TAG, "Requesting steps from Google Fit");
getStepsToday();
Log.d(TAG, "Fit update complete. Allowing Android to destroy
the service.");
} else if (type == TYPE_REQUEST_CONNECTION) {
}
} else {
//Not connected
Log.w(TAG, "Fit wasn't able to connect, so the request failed.");
}
}
private void getStepsToday() {
Calendar cal = Calendar.getInstance();
Date now = new Date();
cal.setTime(now);
long endTime = cal.getTimeInMillis();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
long startTime = cal.getTimeInMillis();
final DataReadRequest readRequest = new DataReadRequest.Builder()
.read(DataType.TYPE_STEP_COUNT_DELTA)
.setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS)
.build();
DataReadResult dataReadResult =
Fitness.HistoryApi.readData(mGoogleApiFitnessClient,
readRequest).await(1, TimeUnit.MINUTES);
DataSet stepData =
dataReadResult.getDataSet(DataType.TYPE_STEP_COUNT_DELTA);
int totalSteps = 0;
for (DataPoint dp : stepData.getDataPoints()) {
for (Field field : dp.getDataType().getFields()) {
int steps = dp.getValue(field).asInt();
totalSteps += steps;
}
}
publishTodaysStepData(totalSteps);
}
private void publishTodaysStepData(int totalSteps) {
Intent intent = new Intent(HISTORY_INTENT);
// You can also include some extra data.
intent.putExtra(HISTORY_EXTRA_STEPS_TODAY, totalSteps);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
private void buildFitnessClient() {
// Create the Google API Client
mGoogleApiFitnessClient = new GoogleApiClient.Builder(this)
.addApi(Fitness.API)
.addScope(new Scope(Scopes.FITNESS_BODY_READ_WRITE))
.addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE))
.addScope(new Scope(Scopes.FITNESS_LOCATION_READ_WRITE))
.addConnectionCallbacks(
new GoogleApiClient.ConnectionCallbacks() {
#Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "Google Fit connected.");
mTryingToConnect = false;
Log.d(TAG, "Notifying the UI that we're
connected.");
notifyUiFitConnected();
}
#Override
public void onConnectionSuspended(int i) {
// If your connection to the sensor gets lost at
some point,
mTryingToConnect = false;
if (i ==
GoogleApiClient.ConnectionCallbacks.CAUSE_NETWORK_LOST) {
Log.i(TAG, "Google Fit Connection lost.
Cause:Network Lost.");
} else if (i ==
GoogleApiClient.ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED) {
Log.i(TAG, "Google Fit Connection lost.
Reason:Service Disconnected ");
}
}
}
)
.addOnConnectionFailedListener(
new GoogleApiClient.OnConnectionFailedListener() {
// Called whenever the API client fails to connect.
#Override
public void onConnectionFailed(ConnectionResult
result) {
mTryingToConnect = false;
notifyUiFailedConnection(result);
}
}
)
.build();
}
private void notifyUiFitConnected() {
Intent intent = new Intent(FIT_NOTIFY_INTENT);
intent.putExtra(FIT_EXTRA_CONNECTION_MESSAGE,
FIT_EXTRA_CONNECTION_MESSAGE);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
private void notifyUiFailedConnection(ConnectionResult result) {
Intent intent = new Intent(FIT_NOTIFY_INTENT);
intent.putExtra(FIT_EXTRA_NOTIFY_FAILED_STATUS_CODE,
result.getErrorCode());
intent.putExtra(FIT_EXTRA_NOTIFY_FAILED_INTENT, result.getResolution());
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
}
Any ideas what might went wrong? Thanks, Theo.
You need to access those detail from fit only when it connected .And Try this
public void buildFitnessClient() {
fitnessClient = new GoogleApiClient.Builder(context)
.addApi(Fitness.HISTORY_API)
.addApi(Fitness.SESSIONS_API)
.addApi(Fitness.RECORDING_API)
.addScope(new Scope(Scopes.FITNESS_BODY_READ_WRITE))
.addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE))
.addScope(new Scope(Scopes.FITNESS_LOCATION_READ_WRITE))
.addScope(new Scope(Scopes.FITNESS_NUTRITION_READ_WRITE))
.addConnectionCallbacks(
new GoogleApiClient.ConnectionCallbacks() {
#Override
public void onConnected(Bundle bundle) {
ReferenceWrapper.getInstance(context).setApiClient(fitnessClient);
((OnClientConnectListener) context).onclientConnected();
}
#Override
public void onConnectionSuspended(int i) {
}
})
.addOnConnectionFailedListener(
new GoogleApiClient.OnConnectionFailedListener() {
#Override
public void onConnectionFailed(
ConnectionResult result) {
if (!result.hasResolution()) {
GooglePlayServicesUtil.getErrorDialog(
result.getErrorCode(), context, 0)
.show();
return;
}
if (!authInProgress) {
try {
authInProgress = true;
result.startResolutionForResult(
context,
KeyConstant.REQUEST_OAUTH);
} catch (IntentSender.SendIntentException e) {
}
}
}
}).build();
}
And at first you need to register your application on google api console . Generate an outh2 client id from there and enable fitness api . Search for fitness Api in api Dashboard , and enable it.. And override OnActivityresult
in your Activity .
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == KeyConstant.REQUEST_OAUTH) {
fitnessHelper.setAuthInProgress(false);
if (resultCode == Activity.RESULT_OK) {
if (!fitnessHelper.isConnecting() && !fitnessHelper.isConnected()) {
fitnessHelper.connect();
}
}
}
}

Google Plus Connection always returns SIGN_IN_FAILED

I'm trying to carry out the Google Plus login within my app but no matter what I do, if the Scope is set to Plus.SCOPE_PLUS_LOGIN, I always get a ConnectionResult whose ErrorCode is 17 (SIGN_IN_FAILED). On the other hand, if I pick Plus.SCOPE_PLUS_PROFILE the app gets connected but when I retrieve the Person object, this one is always null.
I have created a new project in the developer console, enable the Google+ API and created a Cliend ID that includes the proper SHA1 fingerprint for the debug version of the app and its package. I have also picked an email and product name.
I have also tried to rename the package of the app and update the project in the developer console, but I still get the same error.
The thing is that I have downloaded the Google example, created a project in my developer console for it and it works... but when I try to use the same class that does the job in my app, it always fails... really weird. I have also checked the Google + API usage section and it never handles any request sent by my app... whereas it does it for the Google example...
This is the code of the class that carries out the whole process.. as you can see it looks practically the same as the one in the Google example...
public class MainActivity extends FragmentActivity implements
GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener,
ResultCallback<People.LoadPeopleResult>, View.OnClickListener {
private static final int STATE_DEFAULT = 0;
private static final int STATE_SIGN_IN = 1;
private static final int STATE_IN_PROGRESS = 2;
private static final int RC_SIGN_IN = 0;
private static final int DIALOG_PLAY_SERVICES_ERROR = 0;
private static final String SAVED_PROGRESS = "sign_in_progress";
private int mSignInError;
private SignInButton mSignInButton;
private Button mSignOutButton;
private Button mRevokeButton;
private TextView mStatus;
private ListView mCirclesListView;
private ArrayAdapter<String> mCirclesAdapter;
private ArrayList<String> mCirclesList;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSignInButton = (SignInButton) findViewById(R.id.sign_in_button);
mSignOutButton = (Button) findViewById(R.id.sign_out_button);
mRevokeButton = (Button) findViewById(R.id.revoke_access_button);
mStatus = (TextView) findViewById(R.id.sign_in_status);
mCirclesListView = (ListView) findViewById(R.id.circles_list);
mSignInButton.setOnClickListener(this);
mSignOutButton.setOnClickListener(this);
mRevokeButton.setOnClickListener(this);
mCirclesList = new ArrayList<String>();
mCirclesAdapter = new ArrayAdapter<String>(
this, R.layout.circle_member, mCirclesList);
mCirclesListView.setAdapter(mCirclesAdapter);
if (savedInstanceState != null) {
mSignInProgress = savedInstanceState
.getInt(SAVED_PROGRESS, STATE_DEFAULT);
}
mGoogleApiClient = buildGoogleApiClient();
}
private GoogleApiClient buildGoogleApiClient() {
return new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Plus.API, Plus.PlusOptions.builder().build())
//.addScope(Plus.SCOPE_PLUS_PROFILE)
.addScope(Plus.SCOPE_PLUS_LOGIN)
.build();
}
#Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
#Override
protected void onStop() {
super.onStop();
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(SAVED_PROGRESS, mSignInProgress);
}
#Override
public void onClick(View v) {
if (!mGoogleApiClient.isConnecting()) {
switch (v.getId()) {
case R.id.sign_in_button:
mStatus.setText("Sign in");
resolveSignInError();
break;
case R.id.sign_out_button:
Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
mGoogleApiClient.disconnect();
mGoogleApiClient.connect();
break;
case R.id.revoke_access_button:
Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
Plus.AccountApi.revokeAccessAndDisconnect(mGoogleApiClient);
mGoogleApiClient = buildGoogleApiClient();
mGoogleApiClient.connect();
break;
}
}
}
#Override
public void onConnected(Bundle connectionHint) {
Log.i(TAG, "onConnected");
mSignInButton.setEnabled(false);
mSignOutButton.setEnabled(true);
mRevokeButton.setEnabled(true);
Person currentUser = Plus.PeopleApi.getCurrentPerson(mGoogleApiClient);
Log.d("profile", "profile, name: " + currentUser.getName() + ", id: " + currentUser.getId());
String email = Plus.AccountApi.getAccountName(mGoogleApiClient);
mStatus.setText(String.format("Sign in",
email));
Plus.PeopleApi.loadVisible(mGoogleApiClient, null)
.setResultCallback(this);
mSignInProgress = STATE_DEFAULT;
}
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "onConnectionFailed: ConnectionResult.getErrorCode() = "
+ result.getErrorCode());
if (result.getErrorCode() == ConnectionResult.API_UNAVAILABLE) {
} else if (mSignInProgress != STATE_IN_PROGRESS) {
mSignInIntent = result.getResolution();
mSignInError = result.getErrorCode();
if (mSignInProgress == STATE_SIGN_IN) {
resolveSignInError();
}
}
onSignedOut();
}
private void resolveSignInError() {
if (mSignInIntent != null) {
try {
mSignInProgress = STATE_IN_PROGRESS;
startIntentSenderForResult(mSignInIntent.getIntentSender(),
RC_SIGN_IN, null, 0, 0, 0);
} catch (IntentSender.SendIntentException e) {
Log.i(TAG, "Sign in intent could not be sent: "
+ e.getLocalizedMessage());
mSignInProgress = STATE_SIGN_IN;
mGoogleApiClient.connect();
}
} else {
showDialog(DIALOG_PLAY_SERVICES_ERROR);
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
switch (requestCode) {
case RC_SIGN_IN:
if (resultCode == RESULT_OK) {
mSignInProgress = STATE_SIGN_IN;
} else {
mSignInProgress = STATE_DEFAULT;
}
if (!mGoogleApiClient.isConnecting()) {
mGoogleApiClient.connect();
}
break;
}
}
#Override
public void onResult(People.LoadPeopleResult peopleData) {
if (peopleData.getStatus().getStatusCode() == CommonStatusCodes.SUCCESS) {
mCirclesList.clear();
PersonBuffer personBuffer = peopleData.getPersonBuffer();
try {
int count = personBuffer.getCount();
for (int i = 0; i < count; i++) {
mCirclesList.add(personBuffer.get(i).getDisplayName());
}
} finally {
personBuffer.close();
}
mCirclesAdapter.notifyDataSetChanged();
} else {
Log.e(TAG, "Error requesting visible circles: " + peopleData.getStatus());
}
}
private void onSignedOut() {
mSignInButton.setEnabled(true);
mSignOutButton.setEnabled(false);
mRevokeButton.setEnabled(false);
mStatus.setText("Sign out");
mCirclesList.clear();
mCirclesAdapter.notifyDataSetChanged();
}
#Override
public void onConnectionSuspended(int cause) {
ConnectionResult that we can attempt to resolve.
mGoogleApiClient.connect();
}

Step Counter Google FIT API

I am currently trying to work with Google Fit API.This is my first App using the API, and I have been mainly by following Google's documentation.
Below is the code that I have which seems to have a problem
The problem I have is that it doesn't seem to be updating the step counter.
public class MainActivity extends Activity
implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private static final String TAG = "FitActivity";
//[START Auth_Variable_References]
private static final int REQUEST_OAUTH = 1;
// [END auth_variable_references]
private GoogleApiClient mClient = null;
int mInitialNumberOfSteps = 0;
private TextView mStepsTextView;
private boolean mFirstCount = true;
// Create Builder View
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mStepsTextView = (TextView) findViewById(R.id.textview_number_of_steps);
}
private void connectFitness() {
Log.i(TAG, "Connecting...");
// Create the Google API Client
mClient = new GoogleApiClient.Builder(this)
// select the Fitness API
.addApi(Fitness.API)
// specify the scopes of access
.addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ))
.addScope(new Scope(Scopes.FITNESS_LOCATION_READ))
.addScope(new Scope(Scopes.FITNESS_BODY_READ_WRITE))
// provide callbacks
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
// Connect the Google API client
mClient.connect();
}
// Manage OAuth authentication
#Override
public void onConnectionFailed(ConnectionResult result) {
// Error while connecting. Try to resolve using the pending intent returned.
if (result.getErrorCode() == ConnectionResult.SIGN_IN_REQUIRED ||
result.getErrorCode() == FitnessStatusCodes.NEEDS_OAUTH_PERMISSIONS) {
try {
// Request authentication
result.startResolutionForResult(this, REQUEST_OAUTH);
} catch (IntentSender.SendIntentException e) {
Log.e(TAG, "Exception connecting to the fitness service", e);
}
} else {
Log.e(TAG, "Unknown connection issue. Code = " + result.getErrorCode());
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_OAUTH) {
if (resultCode == RESULT_OK) {
// If the user authenticated, try to connect again
mClient.connect();
}
}
}
#Override
public void onConnectionSuspended(int i) {
// If your connection 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");
}
}
#Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "Connected!");
// Now you can make calls to the Fitness APIs.
invokeFitnessAPIs();
}
private void invokeFitnessAPIs() {
// Create a listener object to be called when new data is available
OnDataPointListener listener = new OnDataPointListener() {
#Override
public void onDataPoint(DataPoint dataPoint) {
for (Field field : dataPoint.getDataType().getFields()) {
Value val = dataPoint.getValue(field);
updateTextViewWithStepCounter(val.asInt());
}
}
};
//Specify what data sources to return
DataSourcesRequest req = new DataSourcesRequest.Builder()
.setDataSourceTypes(DataSource.TYPE_DERIVED)
.setDataTypes(DataType.TYPE_STEP_COUNT_DELTA)
.build();
// Invoke the Sensors API with:
// - The Google API client object
// - The data sources request object
PendingResult<DataSourcesResult> pendingResult =
Fitness.SensorsApi.findDataSources(mClient, req);
// Build a sensor registration request object
SensorRequest sensorRequest = new SensorRequest.Builder()
.setDataType(DataType.TYPE_STEP_COUNT_CUMULATIVE)
.setSamplingRate(1, TimeUnit.SECONDS)
.build();
// Invoke the Sensors API with:
// - The Google API client object
// - The sensor registration request object
// - The listener object
PendingResult<Status> regResult =
Fitness.SensorsApi.add(mClient,
new SensorRequest.Builder()
.setDataType(DataType.TYPE_STEP_COUNT_DELTA)
.build(),
listener);
// 4. Check the result asynchronously
regResult.setResultCallback(new ResultCallback<Status>()
{
#Override
public void onResult(Status status) {
if (status.isSuccess()) {
Log.d(TAG, "listener registered");
// listener registered
} else {
Log.d(TAG, "listener not registered");
// listener not registered
}
}
});
}
// Update the Text Viewer with Counter of Steps..
private void updateTextViewWithStepCounter(final int numberOfSteps) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getBaseContext(), "On Datapoint!", Toast.LENGTH_SHORT);
if(mFirstCount && (numberOfSteps != 0)) {
mInitialNumberOfSteps = numberOfSteps;
mFirstCount = false;
}
if(mStepsTextView != null){
mStepsTextView.setText(String.valueOf(numberOfSteps - mInitialNumberOfSteps));
}
}
});
}
//Start
#Override
protected void onStart() {
super.onStart();
mFirstCount = true;
mInitialNumberOfSteps = 0;
if (mClient == null || !mClient.isConnected()) {
connectFitness();
}
}
//Stop
#Override
protected void onStop() {
super.onStop();
if(mClient.isConnected() || mClient.isConnecting()) mClient.disconnect();
mInitialNumberOfSteps = 0;
mFirstCount = true;
}
}
First of all,
Follow these steps to enable the Fitness API in the Google API Console and get an OAuth 2.0 client ID.
1. Go to the Google API Console.
2. Select a project, or create a new one. Use the same project for the Android and REST versions of your app.
3. Click Continue to enable the Fitness API.
4. Click Go to credentials.
5. Click New credentials, then select OAuth Client ID.
6. Under Application type select Android.
7. In the resulting dialog, enter your app's SHA-1 fingerprint and package name. For example:
BB:0D:AC:74:D3:21:E1:43:67:71:9B:62:91:AF:A1:66:6E:44:5D:75
com.example.android.fit-example
8. Click Create. Your new Android OAuth 2.0 Client ID and secret appear in the list of IDs for your project. An OAuth 2.0 Client ID is a string of characters, something like this:
780816631155-gbvyo1o7r2pn95qc4ei9d61io4uh48hl.apps.googleusercontent.com
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.Scopes;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Scope;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.fitness.Fitness;
import com.google.android.gms.fitness.data.DataPoint;
import com.google.android.gms.fitness.data.DataSource;
import com.google.android.gms.fitness.data.DataType;
import com.google.android.gms.fitness.data.Field;
import com.google.android.gms.fitness.data.Value;
import com.google.android.gms.fitness.request.DataSourcesRequest;
import com.google.android.gms.fitness.request.OnDataPointListener;
import com.google.android.gms.fitness.request.SensorRequest;
import com.google.android.gms.fitness.result.DataSourcesResult;
import java.util.concurrent.TimeUnit;
/**
* Created by Admin on Dec/8/2016.
* <p/>
* <p/>
* http://stackoverflow.com/questions/28476809/step-counter-google-fit-api?rq=1
*/
public class StackOverflowActivity extends AppCompatActivity
{
private static final String TAG = "FitActivity";
private GoogleApiClient mClient = null;
private OnDataPointListener mListener;
// Create Builder View
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onResume() {
super.onResume();
connectFitness();
}
private void connectFitness() {
if (mClient == null){
mClient = new GoogleApiClient.Builder(this)
.addApi(Fitness.SENSORS_API)
.addScope(new Scope(Scopes.FITNESS_LOCATION_READ)) // GET STEP VALUES
.addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
#Override
public void onConnected(Bundle bundle) {
Log.e(TAG, "Connected!!!");
// Now you can make calls to the Fitness APIs.
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");
}
}
}
)
.enableAutoManage(this, 0, new GoogleApiClient.OnConnectionFailedListener() {
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.e(TAG, "!_##ERROR :: Google Play services connection failed. Cause: " + result.toString());
}
})
.build();
}
}
private void findFitnessDataSources() {
Fitness.SensorsApi.findDataSources(
mClient,
new DataSourcesRequest.Builder()
.setDataTypes(DataType.TYPE_STEP_COUNT_DELTA)
.setDataSourceTypes(DataSource.TYPE_DERIVED)
.build())
.setResultCallback(new ResultCallback<DataSourcesResult>() {
#Override
public void onResult(DataSourcesResult dataSourcesResult) {
Log.e(TAG, "Result: " + dataSourcesResult.getStatus().toString());
for (DataSource dataSource : dataSourcesResult.getDataSources()) {
Log.e(TAG, "Data source found: " + dataSource.toString());
Log.e(TAG, "Data Source type: " + dataSource.getDataType().getName());
//Let's register a listener to receive Activity data!
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);
}
}
}
});
}
private void registerFitnessDataListener(final 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.e(TAG, "Detected DataPoint field: " + field.getName());
Log.e(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(1, 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.");
}
}
});
}
}
NOTE : :: Sometimes in some device it doestn't detect Step values so whenever you are developing and workling with this code Always Uninstall app and then re-install app. then this works fine.
**Don't forget to add this permission**
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
You can try the StepSensor library from OrangeGangster's.
It contains a custom Service allowing to collect data from the Sensor.TYPE_STEP_COUNTER introduced with Android 4.4 (available only for devices that supports this hardware feature).
This code works for me !
Building the client :
mClient = new GoogleApiClient.Builder(this)
.addApi(Fitness.SENSORS_API)
.addScope(new Scope(Scopes.FITNESS_BODY_READ_WRITE))
.addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE))
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
Invoking Sensors API :
private void invokeSensorsAPI() {
Fitness.SensorsApi.add(
mClient,
new SensorRequest.Builder()
.setDataType(DataType.TYPE_STEP_COUNT_DELTA)
.setSamplingRate(1, TimeUnit.SECONDS)
.build(),
this)
.setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
if (status.isSuccess()) {
Log.i(TAG, "Sensor Listener registered!");
} else {
Log.i(TAG, "Sensor Listener not registered.");
}
}
});
}
Recieving data :
#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);
final int value = val.asInt();
if (field.getName().compareToIgnoreCase("steps") == 0) {
runOnUiThread(new Runnable() {
#Override
public void run() {
tv.setText("Value" + value)
}
});
}
}
}
I hope it helps
I think you are making a mistake here
if (resultCode == RESULT_OK) {
// If the user authenticated, try to connect again
mClient.connect()
}
instead it should be
if (resultCode != RESULT_OK) {
// If the user is not authenticated, try to connect again/ resultcode = RESULT_CANCEL
mClient.connect()
} else {
onConnected(null);
}
By your code invokeFitnessApis would never be called because you are reconnecting with googleapiclient after successfull connection.

Categories

Resources