android / fit-samples Goto Github PK
View Code? Open in Web Editor NEWMultiple samples showing the best practices using the Fit APIs on Android.
License: Apache License 2.0
Multiple samples showing the best practices using the Fit APIs on Android.
License: Apache License 2.0
Hi,
I am getting an error where i am not recieving any data from the google fit api, I have copied the same code that is used in this github and still arent getting any data. Also, When i click the update steps button on the menu my app crashes and says " java.lang.IllegalArgumentException: steps not set
at com.google.android.gms.fitness.data.DataSet.zzb(com.google.android.gms:play-services-fitness@@18.0.0:115)
at com.google.android.gms.fitness.data.DataSet.add(com.google.android.gms:play-services-fitness@@18.0.0:43)
at lirik.myapplication.ShowActivityData.updateFitnessData(ShowActivityData.java:424)
at lirik.myapplication.ShowActivityData.updateData(ShowActivityData.java:351)
at lirik.myapplication.ShowActivityData.updateAndReadData(ShowActivityData.java:335)"
here is my code:
``
/**
This sample demonstrates how to use the History API of the Google Fit platform to insert data,
query against existing data, and remove data. It also demonstrates how to authenticate a user
with Google Play Services and how to properly represent data in a {@link DataSet}.
*/
public class ShowActivityData extends AppCompatActivity {
private ArrayList personalStepData = new ArrayList<>();
public static final String TAG = "BasicHistoryApi";
// Identifier to identify the sign in activity.
private static final int REQUEST_OAUTH_REQUEST_CODE = 1;
@OverRide
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_data);
// This method sets up our custom logger, which will print all log messages to the device
// screen, as well as to adb logcat.
initializeLogging();
FitnessOptions fitnessOptions =
FitnessOptions.builder()
.addDataType(DataType.TYPE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_WRITE)
.addDataType(DataType.AGGREGATE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_WRITE)
.build();
if (!GoogleSignIn.hasPermissions(GoogleSignIn.getLastSignedInAccount(this), fitnessOptions)) {
GoogleSignIn.requestPermissions(
this,
REQUEST_OAUTH_REQUEST_CODE,
GoogleSignIn.getLastSignedInAccount(this),
fitnessOptions);
} else {
insertAndReadData();
}
}
@OverRide
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
if (requestCode == REQUEST_OAUTH_REQUEST_CODE) {
insertAndReadData();
}
}
}
/**
/** Creates a {@link DataSet} and inserts it into user's Google Fit history. */
private Task insertData() {
// Create a new dataset and insertion request.
DataSet dataSet = insertFitnessData();
// Then, invoke the History API to insert the data.
Log.i(TAG, "Inserting the dataset in the History API.");
return Fitness.getHistoryClient(this, GoogleSignIn.getLastSignedInAccount(this))
.insertData(dataSet)
.addOnCompleteListener(
new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
// At this point, the data has been inserted and can be read.
Log.i(TAG, "Data insert was successful!");
} else {
Log.e(TAG, "There was a problem inserting the dataset.", task.getException());
}
}
});
}
/**
Asynchronous task to read the history data. When the task succeeds, it will print out the data.
*/
private Task readHistoryData() {
// Begin by creating the query.
DataReadRequest readRequest = queryFitnessData();
// Invoke the History API to fetch the data with the query
return Fitness.getHistoryClient(this, GoogleSignIn.getLastSignedInAccount(this))
.readData(readRequest)
.addOnSuccessListener(
new OnSuccessListener() {
@OverRide
public void onSuccess(DataReadResponse dataReadResponse) {
// For the sake of the sample, we'll print the data so we can see what we just
// added. In general, logging fitness information should be avoided for privacy
// reasons.
printData(dataReadResponse);
}
})
.addOnFailureListener(
new OnFailureListener() {
@OverRide
public void onFailure(@nonnull Exception e) {
Log.e(TAG, "There was a problem reading the data.", e);
}
});
}
/**
Creates and returns a {@link DataSet} of step count data for insertion using the History API.
*/
private DataSet insertFitnessData() {
Log.i(TAG, "Creating a new data insert request.");
// [START build_insert_data_request]
// Set a start and end time for our data, using a start time of 1 hour before this moment.
Calendar cal = Calendar.getInstance();
Date now = new Date();
cal.setTime(now);
long endTime = cal.getTimeInMillis();
cal.add(Calendar.HOUR_OF_DAY, -1);
long startTime = cal.getTimeInMillis();
// Create a data source
DataSource dataSource =
new DataSource.Builder()
.setAppPackageName(this)
.setDataType(DataType.TYPE_STEP_COUNT_DELTA)
.setStreamName(TAG + " - step count")
.setType(DataSource.TYPE_RAW)
.build();
// Create a data set
int stepCountDelta = 950;
DataSet dataSet = DataSet.create(dataSource);
// For each data point, specify a start time, end time, and the data value -- in this case,
// the number of new steps.
DataPoint dataPoint =
dataSet.createDataPoint().setTimeInterval(startTime, endTime, TimeUnit.MILLISECONDS);
dataPoint.getValue(Field.FIELD_STEPS).setInt(stepCountDelta);
dataSet.add(dataPoint);
// [END build_insert_data_request]
return dataSet;
}
/** Returns a {@link DataReadRequest} for all step count changes in the past week. */
public static DataReadRequest queryFitnessData() {
// [START build_read_data_request]
// Setting a start and end date using a range of 1 week before this moment.
Calendar cal = Calendar.getInstance();
Date now = new Date();
cal.setTime(now);
long endTime = cal.getTimeInMillis();
cal.add(Calendar.WEEK_OF_YEAR, -1);
long startTime = cal.getTimeInMillis();
java.text.DateFormat dateFormat = getDateInstance();
Log.i(TAG, "Range Start: " + dateFormat.format(startTime));
Log.i(TAG, "Range End: " + dateFormat.format(endTime));
DataReadRequest readRequest =
new DataReadRequest.Builder()
// The data request can specify multiple data types to return, effectively
// combining multiple data queries into one call.
// In this example, it's very unlikely that the request is for several hundred
// datapoints each consisting of a few steps and a timestamp. The more likely
// scenario is wanting to see how many steps were walked per day, for 7 days.
.aggregate(DataType.TYPE_STEP_COUNT_DELTA, DataType.AGGREGATE_STEP_COUNT_DELTA)
// Analogous to a "Group By" in SQL, defines how data should be aggregated.
// bucketByTime allows for a time span, whereas bucketBySession would allow
// bucketing by "sessions", which would need to be defined in code.
.bucketByTime(1, TimeUnit.DAYS)
.setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS)
.build();
// [END build_read_data_request]
return readRequest;
}
/**
// [START parse_dataset]
private static void dumpDataSet(DataSet dataSet) {
//Log.i(TAG, "Data returned for Data type: " + dataSet.getDataType().getName());
DateFormat dateFormat = getTimeInstance();
for (DataPoint dp : dataSet.getDataPoints()) {
Log.i(TAG, "Data point:");
Log.i(TAG, "\tType: " + dp.getDataType().getName());
Log.i(TAG, "\tStart: " + dateFormat.format(dp.getStartTime(TimeUnit.MILLISECONDS)));
Log.i(TAG, "\tEnd: " + dateFormat.format(dp.getEndTime(TimeUnit.MILLISECONDS)));
for (Field field : dp.getDataType().getFields()) {
Log.i(TAG, "\tField: " + field.getName() + " Value: " + dp.getValue(field));
}
}
}
// [END parse_dataset]
/**
Deletes a {@link DataSet} from the History API. In this example, we delete all step count data
for the past 24 hours.
*/
private void deleteData() {
Log.i(TAG, "Deleting today's step count data.");
// [START delete_dataset]
// Set a start and end time for our data, using a start time of 1 day before this moment.
Calendar cal = Calendar.getInstance();
Date now = new Date();
cal.setTime(now);
long endTime = cal.getTimeInMillis();
cal.add(Calendar.DAY_OF_YEAR, -1);
long startTime = cal.getTimeInMillis();
// Create a delete request object, providing a data type and a time interval
DataDeleteRequest request =
new DataDeleteRequest.Builder()
.setTimeInterval(startTime, endTime, TimeUnit.MILLISECONDS)
.addDataType(DataType.TYPE_STEP_COUNT_DELTA)
.build();
// Invoke the History API with the HistoryClient object and delete request, and then
// specify a callback that will check the result.
Fitness.getHistoryClient(this, GoogleSignIn.getLastSignedInAccount(this))
.deleteData(request)
.addOnCompleteListener(
new OnCompleteListener() {
@OverRide
public void onComplete(@nonnull Task task) {
if (task.isSuccessful()) {
Log.i(TAG, "Successfully deleted today's step count data.");
} else {
Log.e(TAG, "Failed to delete today's step count data.", task.getException());
}
}
});
}
/**
/**
Creates a {@link DataSet},then makes a {@link DataUpdateRequest} to update step data. Then
invokes the History API with the HistoryClient object and update request.
*/
private Task updateData() {
// Create a new dataset and update request.
DataSet dataSet = updateFitnessData();
long startTime = 0;
long endTime = 0;
// Get the start and end times from the dataset.
for (DataPoint dataPoint : dataSet.getDataPoints()) {
startTime = dataPoint.getStartTime(TimeUnit.MILLISECONDS);
endTime = dataPoint.getEndTime(TimeUnit.MILLISECONDS);
}
// [START update_data_request]
Log.i(TAG, "Updating the dataset in the History API.");
DataUpdateRequest request =
new DataUpdateRequest.Builder()
.setDataSet(dataSet)
.setTimeInterval(startTime, endTime, TimeUnit.MILLISECONDS)
.build();
// Invoke the History API to update data.
return Fitness.getHistoryClient(this, GoogleSignIn.getLastSignedInAccount(this))
.updateData(request)
.addOnCompleteListener(
new OnCompleteListener() {
@OverRide
public void onComplete(@nonnull Task task) {
if (task.isSuccessful()) {
// At this point the data has been updated and can be read.
Log.i(TAG, "Data update was successful.");
} else {
Log.e(TAG, "There was a problem updating the dataset.", task.getException());
}
}
});
}
/** Creates and returns a {@link DataSet} of step count data to update. */
private DataSet updateFitnessData() {
Log.i(TAG, "Creating a new data update request.");
// [START build_update_data_request]
// Set a start and end time for the data that fits within the time range
// of the original insertion.
Calendar cal = Calendar.getInstance();
Date now = new Date();
cal.setTime(now);
cal.add(Calendar.MILLISECOND, 0);
long endTime = cal.getTimeInMillis();
cal.add(Calendar.MILLISECOND, -50);
long startTime = cal.getTimeInMillis();
// Create a data source
DataSource dataSource =
new DataSource.Builder()
.setDataType(DataType.TYPE_STEP_COUNT_DELTA)
.setType(DataSource.TYPE_DERIVED)
.setStreamName("estimated_steps")
.setAppPackageName("com.google.android.gms")
.build();
// Create a data set
DataSet dataSet = DataSet.create(dataSource);
int stepCountDelta = 1000;
// For each data point, specify a start time, end time, and the data value -- in this case,
// the number of new steps.
DataPoint d = DataPoint.builder(dataSource).setTimeInterval(startTime,endTime,TimeUnit.MILLISECONDS).build();
DataPoint dataPoint = dataSet.createDataPoint().setTimeInterval(startTime, endTime, TimeUnit.MILLISECONDS);
dataPoint.getValue(Field.FIELD_STEPS).setInt(stepCountDelta);
d.getValue(Field.FIELD_STEPS);
personalStepData.add((d.getValue(Field.FIELD_STEPS).asInt()));
dataSet.add(d);
// [END build_update_data_request]
return dataSet;
}
}
Hello Everyone
i want to use google fir api after using step counter i am getting result code 0 so how can i fix this issue.
Thanks in advance
Issue by atkyritsis
Tuesday Dec 06, 2016 at 11:49 GMT
Originally opened as googlearchive/android-fit#20
Does not work without it.
atkyritsis included the following code: https://github.com/googlesamples/android-fit/pull/20/commits
does anyone have an idea how I can get the step count for a certain day? and for each day of last week?
Issue by jaag12
Thursday Nov 16, 2017 at 09:09 GMT
Originally opened as googlearchive/android-fit#28
Error when trying new versions of Google Fit samples,
E/AndroidRuntime: FATAL EXCEPTION: GoogleApiHandler Process: com.google.android.gms.fit.samples.basicrecordingapi, PID: 22949 java.lang.NullPointerException: Attempt to invoke virtual method 'android.accounts.Account com.google.android.gms.auth.api.signin.GoogleSignInAccount.getAccount()' on a null object reference at com.google.android.gms.common.api.GoogleApi.zzagd(Unknown Source) at com.google.android.gms.common.api.GoogleApi.zza(Unknown Source) at com.google.android.gms.common.api.internal.zzbr.<init>(Unknown Source) at com.google.android.gms.common.api.internal.zzbp.zzb(Unknown Source) at com.google.android.gms.common.api.internal.zzbp.handleMessage(Unknown Source) at android.os.Handler.dispatchMessage(Handler.java:98) at android.os.Looper.loop(Looper.java:158) at android.os.HandlerThread.run(HandlerThread.java:61)
have changed the methods and I have noticed that since then my application using the old methods does not record data for DataType TYPE_ACTIVITY_SEGMENT, TYPE_STEP_COUNT_DELTA and sometimes TYPE_HEART_RATE_BPM. What is the solution?
My app is trying to connect to Google Fit. The user is prompted to pick a Google Account and once picked, the "Consent Screen" shows up requiring users to accept or deny each permission. There are separate screens for each permission. Once the user has gone through each permission pop up to accept or deny, a main screen appears that shows a list of all the permissions with check marks next to the ones that the user had allowed. If the user denies one or more of the permissions, it usually closes the pop up, shows a spinner, and then restarts the consent screen pop ups to force the user to go through each permission pop up and then continues to the main pop up of the whole list of permissions.
Issue by casman51
Tuesday May 21, 2019 at 10:04 GMT
Originally opened as googlearchive/android-fit#51
When I try to use SessionReadRequest to parse data from 1 month it does not return anything. In the beginning this worked, but as newer sessions now include TYPE_HEART_RATE_BPM dataType it doesn't work anymore. When I don't read this dataType or lower the time to only 3 days back in time it works.. Could anyone help me with this issue. Is there some sort on limit on a SessionReadRequest? Below is my code for reading the sessions. Once a session is read is goes to the populateList where they are added to a list and when completed notify a RecyclerView.
private SessionReadRequest readFitnessSession() {
// [START build_read_session_request]
// Set a start and end time for query, using a start time of 1 month before this moment.
Calendar cal = Calendar.getInstance();
Date now = new Date();
cal.setTime(now);
long endTime = cal.getTimeInMillis();
cal.add(Calendar.MONTH, -1);
long startTime = cal.getTimeInMillis();
// Build a session read request
SessionReadRequest readRequest = new SessionReadRequest.Builder()
.setTimeInterval(startTime, endTime, TimeUnit.MILLISECONDS)
.read(DataType.TYPE_HEART_RATE_BPM)
.read(DataType.AGGREGATE_DISTANCE_DELTA)
.readSessionsFromAllApps()
//.enableServerQueries()
.build();
// [END build_read_session_request]
return readRequest;
}
private Task<SessionReadResponse> readSession() {
// Begin by creating the query.
SessionReadRequest readRequest = readFitnessSession();
// [START read_session]
// Invoke the Sessions API to fetch the session with the query and wait for the result
// of the read request. Note: Fitness.SessionsApi.readSession() requires the
// ACCESS_FINE_LOCATION permission.
return Fitness.getSessionsClient(this, GoogleSignIn.getLastSignedInAccount(this))
.readSession(readRequest)
.addOnSuccessListener(new OnSuccessListener<SessionReadResponse>() {
@Override
public void onSuccess(SessionReadResponse sessionReadResponse) {
// Get a list of the sessions that match the criteria to check the result.
Log.i(TAG, "Session read was successful");
populateList(sessionReadResponse);
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.i(TAG, "Failed to read session");
}
});
// [END read_session]
}
Hi I want to know if theres any method to differenctiate BMR calories with Calories Expended in the API. If I change any personal data (in google Fit) I can get It using TYPE_BASAL_METABOLIC_RATE. But If i don't do any thing this doesnt work
Issue by ilyasdirin
Tuesday May 14, 2019 at 08:11 GMT
Originally opened as googlearchive/android-fit#50
I'm developing a step counter with Google Fit.
I tried to implement as it is defined in Google Fit docs. But the problem is that when I query step count it always returns empty dataset but when I query with readDailyTotal function it returns a dataset.
I am not able to find what is the cause.
val fitnessOptions = FitnessOptions.builder()
.addDataType(DataType.TYPE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)
.addDataType(DataType.TYPE_STEP_COUNT_CUMULATIVE, FitnessOptions.ACCESS_READ)
.addDataType(DataType.AGGREGATE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)
.build()
if (! GoogleSignIn.hasPermissions(GoogleSignIn.getLastSignedInAccount(activity),
fitnessOptions)) {
GoogleSignIn.requestPermissions(
activity, // your activity
REQUEST_CODE_GOOGLE_FIT_PERMISSIONS,
GoogleSignIn.getLastSignedInAccount(activity),
fitnessOptions
)
} else {
onSuccess.invoke()
}
Fitness.getRecordingClient(context, client!!)
.subscribe(DataType.TYPE_STEP_COUNT_DELTA)
.addOnSuccessListener {
onSuccess.invoke()
}
.addOnFailureListener { e ->
onFail.invoke(e)
}
// Setting a start and end date using a range of 1 week before this moment.
val cal = Calendar.getInstance()
val now = Date()
cal.time = now
val endTime = cal.timeInMillis
cal.add(Calendar.WEEK_OF_YEAR, -1)
val startTime = cal.timeInMillis
val dateFormat = DateFormat.getDateInstance()
Log.i(TAG, "Range Start: " + dateFormat.format(startTime))
Log.i(TAG, "Range End: " + dateFormat.format(endTime))
val readRequest = DataReadRequest.Builder()
// The data request can specify multiple data types to return, effectively
// combining multiple data queries into one call.
// In this example, it's very unlikely that the request is for several hundred
// datapoints each consisting of a few steps and a timestamp. The more likely
// scenario is wanting to see how many steps were walked per day, for 7 days.
.aggregate(DataType.TYPE_STEP_COUNT_DELTA, DataType.AGGREGATE_STEP_COUNT_DELTA)
// Analogous to a "Group By" in SQL, defines how data should be aggregated.
// bucketByTime allows for a time span, whereas bucketBySession would allow
// bucketing by "sessions", which would need to be defined in code.
.bucketByTime(1, TimeUnit.DAYS)
.setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS)
.enableServerQueries()
.build()
Fitness.getHistoryClient(context, client)
.readData(readRequest)
.addOnSuccessListener { dataReadResponse ->
dumpDataSets(dataReadResponse.dataSets)
onSuccess.invoke(dataReadResponse)
}
.addOnFailureListener { e ->
onFail.invoke(e)
}
.addOnCompleteListener { task ->
dumpDataSets(task.result!!.dataSets)
onComplete.invoke(task)
}
Issue by saravanan72
Friday May 18, 2018 at 10:30 GMT
Originally opened as googlearchive/android-fit#35
Hi,
I have tried this google fitness API as a sample one. When i am getting apk in debug format, it run perfectly .When i run this , initially it subscribe by using gmail account and provides step count value as i expect. But when i try with signed APK, its doesn't work. It doesn't show the subscription dialog and also the count doesn't show without subscription. Please give solution regarding that. Thanks.
Hi,
I ran the the sample to get steps using history Api as mentioned in the link: https://developers.google.com/fit/android/get-started
But I am getting empty [ ] response from the Api regardless of the interval time.
Here is my code:
private fun accessGoogleFit() {
val cal = Calendar.getInstance()
cal.setTime(Date())
val endTime = cal.getTimeInMillis()
cal.add(Calendar.MONTH, -1)
val startTime = cal.getTimeInMillis()
val readRequest = DataReadRequest.Builder()
.aggregate(TYPE_STEP_COUNT_DELTA, AGGREGATE_STEP_COUNT_DELTA)
.setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS)
.enableServerQueries()
.bucketByTime(1, TimeUnit.DAYS)
.build()
Fitness.getHistoryClient(this, GoogleSignIn.getLastSignedInAccount(this)!!)
.readData(readRequest)
.addOnSuccessListener(OnSuccessListener<DataReadResponse> {
Log.i("DATASET",it.dataSets.toString())
textView35.text = it.dataSets.toString()
Log.d(
"SUCCESS_TAG",
"onSuccess()"
)
})
.addOnFailureListener(OnFailureListener { e -> Log.e("FAILED_TAG", "onFailure()", e) })
.addOnCompleteListener(OnCompleteListener<DataReadResponse> {
Log.d(
"COMPLETE TAG",
"onComplete()"
)
})
}
Any help would be appreciated.
Hi there, I got some problems with real-time display data in my application. I use SensorClient to listen to calorie data change. When my calories data change on Google Fit, the onDataPoint function was not invoked. When I use sensor client for listening to the Step Count data change, it works properly. Please explains to me why I cannot use SensorClient for listening to TYPE_CALORIES_EXPENDED data type.
Here is my code:
Fitness.getSensorsClient(context, account)
.add(SensorRequest.Builder().setDataType(dataType)
.build(), dataPointListener)
.addOnSuccessListener {
Log.e("registerDataPointUpdateListener: ", "Success for $dataType")
}.addOnFailureListener {
Log.e("registerDataPointUpdateListener: ", "Fail ${it.message}")
}
I saw this one in my logcat:
W/Fitness: No live data sources available for SensorRegistrationRequest{type DataType{com.google.activity.segment[activity(i)]} source null interval -1 fastest 0 latency 0}. Returning success. Will start recording once data source is live [CONTEXT service_id=17 ]
Issue by khushboojainOffbeat
Monday Aug 13, 2018 at 11:40 GMT
Originally opened as googlearchive/android-fit#38
I m using GoogleFit Sdk step to step from this project but i m not able to logout session of google account, Please give me suggestion. What should i do ?
Issue by lifeLessCoder
Friday Jun 22, 2018 at 13:21 GMT
Originally opened as googlearchive/android-fit#36
I'm not able to remove the listener from SensorsApi. After the remove(mListener) method is called, task.getResult() returns false in the OnComplete method.
Issue by ykorshev
Monday Jan 07, 2019 at 04:41 GMT
Originally opened as googlearchive/android-fit#44
I have an app which uses Google Fit. The integration code has been copied from google documentation:
if (!GoogleSignIn.hasPermissions(GoogleSignIn.getLastSignedInAccount(this), fitnessOptions)) { GoogleSignIn.requestPermissions( this, // your activity GOOGLE_FIT_PERMISSIONS_REQUEST_CODE, GoogleSignIn.getLastSignedInAccount(this), fitnessOptions); } else { accessGoogleFit(); }
In the debug mode, everything works fine, but when my app downloaded from Google Play, it ALWAYS display a prompt for selecting the google account to use:
The problem appears only when app downloaded from google play. When app installed with adb, everything works fine.
It seems like, Google Play Services does not cache last selected account.
Please help me, where is the issue here?
I'm trying to use Fitness API services on my app and it was running well so far. I can obtain any data that I need from Fit App until it wont work anymore when I'm using corporate account outside gmail on the authorisation pop up, for example [email protected]
.
[email protected]
and [email protected]
through permission dialog)[email protected]
account, fitness data should be retrieve-able.[email protected]
account, fitness data is not retrieve-able. For example, if you get step count it always return 0 value.So what I want to know is, does Fitness API only works with gmail account? They do not mention anything about that on the authorization pages:
It would be nice if someone can point me out to a relevant article or something similar. Thank you.
Issue by vitovalov
Thursday Jul 28, 2016 at 11:22 GMT
Originally opened as googlearchive/android-fit#18
I made a fork from android-fit google's github project and added a couple of commits.
The problem comes with play-services-fitness version upgrade. It works as expected in 8.4.0 but if you upgrade to 9.0.2 appears the issue of recreating googleApiClient.
I'm trying to solve the case when the googleApiClient has to be recreated because stopAutoManage has been automatically called due to some error (either user canceled the sign-in dialog, or other client was alive but was manually stopAutomanage called). See the gifs.
So to sum up, the question is how to properly recreate the GoogleApiClient with play services 9+?
There's also an issue in android bug tracker.
Issue by iakovosvo
Tuesday Dec 12, 2017 at 11:51 GMT
Originally opened as googlearchive/android-fit#29
I get the following error while trying to open the BasicSensorsApi project:
Error:Could not find com.googlecode.json-simple:json-simple:1.1.
Searched in the following locations:
file:/Applications/Android Studio 3.0 Preview.app/Contents/gradle/m2repository/com/googlecode/json-simple/json-simple/1.1/json-simple-1.1.pom
file:/Applications/Android Studio 3.0 Preview.app/Contents/gradle/m2repository/com/googlecode/json-simple/json-simple/1.1/json-simple-1.1.jar
https://dl.google.com/dl/android/maven2/com/googlecode/json-simple/json-simple/1.1/json-simple-1.1.pom
https://dl.google.com/dl/android/maven2/com/googlecode/json-simple/json-simple/1.1/json-simple-1.1.jar
Required by:
project : > com.android.tools.build:gradle:3.0.0 > com.android.tools.build:gradle-core:3.0.0 > com.android.tools.build:builder:3.0.0
Hi,
I have followed the all the steps to configure this app but every time i get this error and the same steps were followed for different sample apps it seems to work fine except for BasicHistoryApi
E/BasicHistoryApi: There was an error signing into Fit. Check the troubleshooting section of the README
for potential issues.
Request code was: 0
Result code was: 0
Issue by norio-agoop
Wednesday Mar 27, 2019 at 09:06 GMT
Originally opened as googlearchive/android-fit#48
Hi,
I'm trying to enable/disable google fit in my app with a Switch View.
When I turn off this switch, I call below code.
Fitness.getConfigClient(context, account).disableFit()
.addOnSuccessListener {
Timber.d("disconnectGoogleFit: onSuccess")
}
...
After onSuccess
, I turn on switch to connect google fit and call below.
if (GoogleSignIn.hasPermissions(GoogleSignIn.getLastSignedInAccount(this), fitnessOptions){
return
}
GoogleSignIn.requestPermissions(
this, // your activity
GOOGLE_FIT_PERMISSIONS_REQUEST_CODE,
GoogleSignIn.getLastSignedInAccount(this),
fitnessOptions);
Nothing happens because GoogleSignIn.hasPermissions
always return true
.
I'd like to check whether Google fit permission is granted or not before calling GoogleSignIn.requestPermissions
Please tell me how to do this.
Thank you
I think I have found a solution that disconnecting app through Google Fit App. After this, GoogleSignIn.hasPermissions
return false.
But I am curious how can do this programmatically.
GoogleSignInClient.revokeAccess
works. I don't know the reasons why.
val signInOptions = GoogleSignInOptions.Builder().addExtension(fitnessOptions).build()
val client = GoogleSignIn.getClient(context, signInOptions)
client.revokeAccess()
.addOnSuccessListener {
Timber.d("disconnectGoogleFit: onSuccess")
}
I'd like to ask you what is the diffrences between Fitness.getConfigClient(context, account).disableFit()
and GoogleSignInClient.revokeAccess
?
Thank you
I am using the below code to find data sources because I am interested in reading data specifically from the sensor on a wearable device but not from the same type of sensor on the phone.
private fun findDataSource(){
Fitness.getSensorsClient(this, getGoogleAccount()).findDataSources(
DataSourcesRequest.Builder()
.setDataTypes(DataType.TYPE_LOCATION_SAMPLE)
.setDataSourceTypes(DataSource.TYPE_RAW)
.build())
.addOnSuccessListener { dataSources ->
/**
* Only my mobile phone was found as a data source
* Missing android watch
*/
for (dataSource in dataSources) {
Log.i(TAG,"Data source found: $dataSource")
Log.i(TAG,"Data Source type: ${dataSource.dataType.name}")
if (dataSource.dataType == DataType.TYPE_HEART_RATE_BPM && dataPointListener == null) {
Log.i(TAG,"Data source for TYPE_HEART_RATE_BPM found!")
registerFitnessDataListener(dataSource, dataSource.dataType)
}
}
if (dataSources != null && dataSources.size == 0){
Log.i(TAG,"No data source found")
}
}
.addOnFailureListener { e -> Log.e(TAG,"failed",e) }
}
But from the above code
* Only my mobile phone was found as a data source
* Missing android watch
NOTE: Using Polar Unite Fitness Watch
Issue by panjiyudasetya
Wednesday Oct 31, 2018 at 05:00 GMT
Originally opened as googlearchive/android-fit#42
Step count value that I've been received from History API was different with step count values that has been displayed in Fit App. Even problem solving for different values between Fit History Api and Google Fit App has been mentioned here, sometimes this problem still occurred in certain device.
In my case, I was using :
Fit API Prober | Fit App |
---|---|
As you can see that in Fit API prober, I got 3300 datapoint for today step count, meanwhile in Fit App, 2433 datapoint has been displayed. The margin is quite huge in this case.
History API return same value with Google Fit App.
As for addition, both approach are returning 3300 datapoint rather than 2433 datapoint.
Fitness.getHistoryClient(mContext, GoogleSignIn.getLastSignedInAccount(mContext))
.readDailyTotal(DataType.TYPE_STEP_COUNT_DELTA)
.addOnSuccessListener(new OnSuccessListener<DataSet>() {
@Override
public void onSuccess(DataSet dataSet) {
int totalStepCount = extractHistoryFromDataSet(dataSet);
callback.onResult(totalStepCount);
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
callback.onError(e.getMessage());
}
});
DataSource getFitStepCountDataSource() {
return new DataSource.Builder()
.setDataType(DataType.TYPE_STEP_COUNT_DELTA)
.setType(DataSource.TYPE_DERIVED)
.setStreamName("estimated_steps")
.setAppPackageName("com.google.android.gms")
.build();
}
Task<DataReadResponse> readHistory(long startTime, long endTime) {
DataReadRequest request = new DataReadRequest.Builder()
.aggregate(getFitStepCountDataSource(), DataType.AGGREGATE_STEP_COUNT_DELTA)
.bucketByTime(1, TimeUnit.DAYS)
.setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS)
.enableServerQueries()
.build();
return Fitness.getHistoryClient(mContext, GoogleSignIn.getLastSignedInAccount(mContext))
.readData(request);
}
Issue by hienttVFJ
Wednesday Aug 21, 2019 at 08:40 GMT
Originally opened as googlearchive/android-fit#53
I made small test app which shows daily steps using Google Fit API. During testing, I was not getting any steps count. But later I realised that my Samsung device doesn't come's with Google Fit app so I downloaded it and after feeding some data then I tested my app again and Now I can see my steps count on my test app.
So Does this means that in order to use Google Fit API all my app users must have installed Google Fit App?
Issue by TahaNaqvi
Thursday Apr 11, 2019 at 06:51 GMT
Originally opened as googlearchive/android-fit#49
Here is my code :
Fitness.getHistoryClient(this, GoogleSignIn.getLastSignedInAccount(this))
.readDailyTotalFromLocalDevice(DataType.TYPE_HEART_POINTS)
.addOnSuccessListener(new OnSuccessListener() {
@OverRide
public void onSuccess(DataSet dataSet) {
showDataSet(dataSet);
}
})
.addOnFailureListener(new OnFailureListener() {
@OverRide
public void onFailure(@nonnull Exception e) {
Log.d(LOG_TAG, "onFailure: " + e.getMessage());
}
});
FitnessOptions fitnessOptions = FitnessOptions.builder()
.addDataType(DataType.TYPE_HEART_POINTS, FitnessOptions.ACCESS_READ)
.addDataType(DataType.AGGREGATE_HEART_POINTS, FitnessOptions.ACCESS_READ)
.addDataType(DataType.TYPE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)
.addDataType(DataType.AGGREGATE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)
.addDataType(DataType.TYPE_DISTANCE_DELTA, FitnessOptions.ACCESS_READ)
.addDataType(DataType.AGGREGATE_DISTANCE_DELTA, FitnessOptions.ACCESS_READ)
.addDataType(DataType.TYPE_CALORIES_EXPENDED, FitnessOptions.ACCESS_READ)
.build();
if (!GoogleSignIn.hasPermissions(GoogleSignIn.getLastSignedInAccount(this), fitnessOptions)) {
GoogleSignIn.requestPermissions(
this, // your activity
GOOGLE_FIT_PERMISSIONS_REQUEST_CODE,
GoogleSignIn.getLastSignedInAccount(this),
fitnessOptions);
} else {
accessGoogleFit();
}
I am getting this error (5000: Application needs OAuth consent from the user) while I have given permission as mentioned above.
Issue by BestMafen
Wednesday Jun 12, 2019 at 10:26 GMT
Originally opened as googlearchive/android-fit#52
I ran the History API demo inserted step data, but the data dit not showed at Google Fit APP, what's
wrong?
Issue by ankitaturani573
Saturday Mar 31, 2018 at 20:15 GMT
Originally opened as googlearchive/android-fit#32
I am trying to run the BasicSensorsApi code but getting this error after choosing the gmail account.
I am using an Android Oreo One PLus5.
This is the error I am getting.
04-01 01:30:26.680 26997-26997/com.google.android.gms.fit.samples.basicsensorsapi D/AppTracker: App Event: stop
04-01 01:30:26.717 26997-27076/com.google.android.gms.fit.samples.basicsensorsapi I/Adreno: QUALCOMM build : d52c199, I26dffed9a4
Build Date : 01/09/18
OpenGL ES Shader Compiler Version: EV031.22.00.01
Local Branch :
Remote Branch : refs/tags/AU_LINUX_ANDROID_LA.UM.6.4.R1.08.00.00.309.052
Remote Branch : NONE
Reconstruct Branch : NOTHING
04-01 01:30:26.717 26997-27076/com.google.android.gms.fit.samples.basicsensorsapi I/vndksupport: sphal namespace is not configured for this process. Loading /vendor/lib64/hw/gralloc.msm8998.so from the current namespace instead.
Issue by Zaszczyk
Thursday Nov 22, 2018 at 09:13 GMT
Originally opened as googlearchive/android-fit#43
I use Google Fit REST API for over 2 years and everything was fine already. However since 20th November I am occuring the only reply on route:
/me/dataSources/derived:com.google.location.sample:com.google.android.gms:merge_high_fidelity/datasets/
( 'domain' => 'global',
'reason' => 'forbidden',
'message' => 'No permission to read data for this private data source.', )
I had not changed anything in my code, did Google change something?
Hello,
I try to run StepCounterKotlin sample.
After selecting a Google Account, an empty white popup is shown, just with a loader at the top. And it stuck in this place.
No errors are visible in logcat . I tested in the emulator and on Redmi Note 8 phone.
Package name match credentials for my Cloud project, package name matches the applicationId in the app/build.gradle file, and Signing-certificate fingerprint from debug.keystore is entered correctly.
Should I make some additional setup on Google API Console?
Best
Issue by saravanan72
Thursday Mar 08, 2018 at 06:03 GMT
Originally opened as googlearchive/android-fit#31
java.lang.NullPointerException: Attempt to invoke virtual method 'android.accounts.Account com.google.android.gms.auth.api.signin.GoogleSignInAccount.getAccount()' on a null object reference
error caught in step counter
Issue by hrsalehi
Friday May 04, 2018 at 03:07 GMT
Originally opened as googlearchive/android-fit#34
I configured Google fit api and followed "Getting Started" section of google docs. But when I trying to read "Steps" data I face "Google Fit API: ApiException 17 (Fitness.CLIENT is not available on this device)" exception in Task
object callback from getRecordingClient
Fitness.getRecordingClient(context, GoogleSignIn.getLastSignedInAccount(context))
.subscribe(DataType.TYPE_STEP_COUNT_CUMULATIVE)
.addOnCompleteListener(
new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.i(LOG_TAG, "Successfully subscribed!");
} else {
Log.w(LOG_TAG, "There was a problem subscribing.", task.getException());
}
}
});
Issue by tntkhang
Friday Jun 16, 2017 at 03:18 GMT
Originally opened as googlearchive/android-fit#23
When I run app the pop-up select email to authen to Google, I select the email but the app always throw StatusCode = CANCEL. Does the authen funtion out of date ? Do we need to switch to this authen guide: https://developer.android.com/training/wearables/apps/auth-wear.html#configure-google-sign-in
Issue by ramonmluz
Sunday Sep 30, 2018 at 22:43 GMT
Originally opened as googlearchive/android-fit#40
Are you creating or thinking about create this project in Kotlin?
Issue by sushantgiri
Thursday Aug 24, 2017 at 09:01 GMT
Originally opened as googlearchive/android-fit#25
I am building a fitness application where I pull certain data (Steps and Calories) from google fit. I am fetching a week data. The output of the google fit api doesn't match with the google fit data. The output is so random and doesn't have a definite pattern.
Steps From Google Fit API:
Code Used:
private DataReadRequest queryFitnessData()
{
Calendar cal = Calendar.getInstance();
Date now = new Date();
cal.setTime(now);
long endTime = cal.getTimeInMillis();
cal.add(Calendar.WEEK_OF_YEAR, -1);
long startTime = cal.getTimeInMillis();
java.text.DateFormat dateFormat = getDateInstance();
Timber.e("Range Start: " + dateFormat.format(startTime));
Timber.e("Range End: " + dateFormat.format(endTime));
return new DataReadRequest.Builder()
.aggregate(DataType.TYPE_STEP_COUNT_DELTA, DataType.AGGREGATE_STEP_COUNT_DELTA)
.bucketByTime(1, TimeUnit.DAYS)
.setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS)
.build();
}
public Observable getStepsCount(GoogleApiClient googleApiClient) {
return Observable.create(subscriber -> {
DataReadResult result =
Fitness.HistoryApi.readData(googleApiClient, queryFitnessData()).await(1, TimeUnit.MINUTES);
if (result.getStatus().isSuccess()) {
subscriber.onNext(result);
} else {
subscriber.onError(new Exception("Exception"));
}
});
}
Output
Start Date: 17th August 2017 End Date: 24th August 2017
17-18 -> 4080
18-19 -> 3837
19-19 -> 7
20-21 -> 2212
21-22 -> 4665
23-23 -> 2949
23-24 -> 6131
Any help would be greatly appreciated. If required, apk can also be shared.
Issue by AndyFrnk
Thursday Mar 14, 2019 at 09:48 GMT
Originally opened as googlearchive/android-fit#47
Tried to implement weight, but cannot get information on the weight
AndyFrnk included the following code: https://github.com/googlesamples/android-fit/pull/47/commits
Hello! My google fit app doesn't work for 2 months.
I started to debug the application and I was able to find these errors from adb logcat:
2020-11-22 17:04:48.804 16111-16143/? E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 1330200)
E/FitAndroidFutures: While reading data with request: DataReadRequest{bucket by intervals: active_minutes heart_minutes calories.expended distance.delta d:step_count.delta:gms:estimated_steps (2020-11-22 00:00:00 - 2020-11-22 17:04:41) +server}
him: java.lang.IllegalStateException: hrb: 8:
at hii.a(Unknown Source:4)
at qei.a(PG:2)
at rhf.e(Unknown Source:2)
at rhh.run(PG:11)
at rjp.execute(PG:1)
at rhv.r(PG:1)
at rhv.n(PG:11)
at rhv.l(PG:5)
at rlm.run(PG:10)
...
Please pay attention to the line "FAILED BINDER TRANSACTION !!! (parcel size = 1330200" - google fit can't get the data from the android service because the response is too large to be returned through IPC.
Also, I'm developing an application that uses the fitness api and also I noticed that gms Task api doesn't return anything and even doesn't call "onComplete" listener in similar cases when google fit service can't deliver the result to a requester.
I think a reading task should be completed anyways if Binder fails for some reason.
Hello,
I need to read weight of google fit app using fitness api. is this possible ?
If yes, how ?
Thank you.
Issue by RyanNewsom
Friday Jul 22, 2016 at 22:52 GMT
Originally opened as googlearchive/android-fit#17
All,
My team noticed this problem in our application which uses your Sensors API to show users their distance traveled. Every time we start a walk, eventually, the OnDataPointListener just stops giving updates that there's a new DataPoint available(even though user is moving). I've seen it take anywhere from 5 mins to 1.5 hours to stop working. We have log statements tracking when theres an update, when the client gets disconnected(if it ever does), when a client gets built, etc. There is no callback when this happens. I forked your sample app to try and see if this was an API issue, and it looks like it is.
https://github.com/RyanNewsom/android-fit/tree/master/BasicSensorsApi
Steps to reproduce:
🙏
Issue by ViTVetal
Tuesday Jun 13, 2017 at 15:33 GMT
Originally opened as googlearchive/android-fit#22
I want read HealthDataTypes (temperature, blood pressure and glucose). Which Scope I must set when create GoogleApiClient?
.addScope(new Scope(????))
I'm struggling getting this to work as expected. I need to enumerate all the activities I see in Google Fit app (e.g auto "morning walk" or manual added running). I've used the following query:
DataReadRequest readRequest = new DataReadRequest.Builder()
.aggregate(DataType.TYPE_ACTIVITY_SEGMENT, DataType.AGGREGATE_ACTIVITY_SUMMARY)
.enableServerQueries()
.setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS)
.bucketByTime(1, TimeUnit.DAYS)
.build();
Note: this kind of aggregation is deprecated, but I cannot find the "right" way to receive the same result with the non-deprecated method.
Now: in my example day on Fit, I've two activities. The first is auto-generated "afternoon walk" of 2.32km and 32 min, the second is a manual added running activity of 1h. The query above returns two rows with fields activity/duration/num_segments:
Running / 3600000 (1h) / 1
Walking / 2674044 (~44mins) / 10
As you can see I get 12 minutes added for walking, why? How can I get the exact thing I see in the app? Moreover the total sum of steps for that day is not the sum of the two activities I see on Fit. What a mess...
EDIT: about timezone I'm getting it this way:
Calendar calendar = Calendar.getInstance(Locale.getDefault());
long endTime = calendar.getTimeInMillis();
calendar.add(Calendar.MONTH, -1);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
long startTime = calendar.getTimeInMillis();
And these are the results for the specific day:
DATA TYPE: DataType{com.google.activity.summary[activity(i), duration(i), num_segments(i)]}
AS ACTIVITY: running FIELD: activity(i) START TIME: Fri Oct 16 12:10:00 GMT+02:00 2020 END TIME: Fri Oct 16 13:10:00 GMT+02:00 2020
DURATION: 3600000 FIELD: duration(i) START TIME: Fri Oct 16 12:10:00 GMT+02:00 2020 END TIME: Fri Oct 16 13:10:00 GMT+02:00 2020
N. SEGMENTS: 1 FIELD: num_segments(i) START TIME: Fri Oct 16 12:10:00 GMT+02:00 2020 END TIME: Fri Oct 16 13:10:00 GMT+02:00 2020
AS ACTIVITY: walking FIELD: activity(i) START TIME: Fri Oct 16 09:20:30 GMT+02:00 2020 END TIME: Fri Oct 16 23:15:17 GMT+02:00 2020
DURATION: 2674044 FIELD: duration(i) START TIME: Fri Oct 16 09:20:30 GMT+02:00 2020 END TIME: Fri Oct 16 23:15:17 GMT+02:00 2020
N. SEGMENTS: 10 2FIELD: num_segments(i) START TIME: Fri Oct 16 09:20:30 GMT+02:00 2020 END TIME: Fri Oct 16 23:15:17 GMT+02:00 2020
Issue by vsaranm
Wednesday Feb 01, 2017 at 09:18 GMT
Originally opened as googlearchive/android-fit#21
Issue by zjx
Wednesday Jan 16, 2019 at 02:15 GMT
Originally opened as googlearchive/android-fit#46
looks like the fit system will use the end time as the "timestamp" field which may not be the actual create time of a session. For example,
a running session may happened from 13:00 to 14:00 on a third party app but the actual sync to google fit happens on 18:00 triggered by user manually.
my app just want to retrieve the New Sessions since the last read but if can not get the actual create time in the google fit then there is no way to do this?
any suggestions? Thx.
Issue by krunal93
Monday Jul 02, 2018 at 13:53 GMT
Originally opened as googlearchive/android-fit#37
I am in need to show steps time line wise like below.
Time 10 am - 56 steps
Time 11 am - 156 steps
Time 4.30 pm - 236 steps
I don't want to aggregate by hour or anything , i just want the actual data that is currently google fit app is showing in timeline using steps filter.
However i am able to retrieve steps using bucketBySession that entered manually into google fit app but not able to retrieve those steps history which is generated automatically.
Please let me know how to overcome this.
Below is my sample code.
// Build a session read request
SessionReadRequest readRequest = new SessionReadRequest.Builder()
.setTimeInterval(times[0], times[1], TimeUnit.MILLISECONDS)
.readSessionsFromAllApps()
.read(DataType.TYPE_STEP_COUNT_DELTA)
.enableServerQueries()
.build();
Fitness.getSessionsClient(mContext, GoogleSignIn.getLastSignedInAccount(mContext))
.readSession(readRequest)
.addOnSuccessListener(new OnSuccessListener<SessionReadResponse>() {
@Override
public void onSuccess(SessionReadResponse sessionReadResponse) {
// Get a list of the sessions that match the criteria to check the result.
List<Session> sessions = sessionReadResponse.getSessions();
Log.i(TAG, "Session read was successful. Number of returned sessions is: "
+ sessions.size());
for (Session session : sessions) {
// Process the session
dumpSession(session);
// Process the data sets for this session
List<DataSet> dataSets = sessionReadResponse.getDataSet(session);
for (DataSet dataSet : dataSets) {
dumpDataSet(dataSet);
}
}
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.i(TAG, "Failed to read session");
}
});
final DataReadRequest req = new DataReadRequest.Builder()
.aggregate(DataType.TYPE_STEP_COUNT_DELTA, DataType.AGGREGATE_STEP_COUNT_DELTA)
.aggregate(DataType.TYPE_ACTIVITY_SEGMENT, DataType.AGGREGATE_ACTIVITY_SUMMARY)
.enableServerQueries()
.bucketBySession(1, TimeUnit.MINUTES)
.setTimeRange(times[0], times[1], TimeUnit.MILLISECONDS)
.build();
Fitness.getHistoryClient(mContext, GoogleSignIn.getLastSignedInAccount(mContext))
.readData(req)
.addOnSuccessListener(
dataReadResponse -> readData(dataReadResponse, MESSAGE_HEALTH_DATA_LIST_KEY))
.addOnFailureListener(
e -> {
});
I am trying with the both client , session as well as history but didn't get any suceess.
thanks,
Krunal
In my fork, I have added a WearOS module to BasicRecordingApiKotlin. I have the regular mobile module version working correctly and am able to push and pull data from Google Fit. The Google Fit specific code and OAuth settings on console.developer.google.com are exactly same as the mobile app version however only on WearOS versions am I receiving this error
error 17: Error resolution was canceled by the user, original error message: INVALID_ACCOUNT: null
when running Fitness.getRecordingClient(this, getGoogleAccount()).subscribe(DataType.TYPE_CALORIES_EXPENDED)
always entering onFailureListener
.
The main question I have is, is there something specifically different either in code or in app/project setup that needs to be done for WearOS that I'm not doing currently? Or can someone point to a repo that has a working up-to-date Google Fit WearOS Kotlin sample?
My Setup:
MacOS Catalina 10.15.7
Android Studio: 4.1.1
Kotlin Version: 1.3.61
com.google.android.gms:play-services-fitness: 20.0.0
com.google.android.gms:play-services-auth: 19.0.0
Physical Device:
TicWatch Pro
System Version: H
WearOS by Google: 2.19
Android security patch level: June 1, 2020
I have also opened a question on stackoverflow.com. It has many screenshots which might be relevant but I thought might not need to be duplicated here
Thanks and I appreciate any help and will add more information if requested or something is unclear.
P.S.: I also got BasicHistorySessionApiKotlin mobile module version working and the added WearOS module gets same error
Issue by pavelpoley
Tuesday Aug 21, 2018 at 10:03 GMT
Originally opened as googlearchive/android-fit#39
How to debug in real time sessions/activities (data insertion), it is take hours until the data shows in Google fit app, sometimes it does not show all, even when onSuccess and onComplete called, very hard to test with this delays.
Issue by puvi008
Monday Oct 01, 2018 at 11:33 GMT
Originally opened as googlearchive/android-fit#41
public class MainActivity extends AppCompatActivity {
public static final String TAG = "StepCounter";
private static final int REQUEST_OAUTH_REQUEST_CODE = 0x1001;
private static final int REQUEST_PERMISSIONS_REQUEST_CODE = 34;
private GoogleApiClient mClient = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// This method sets up our custom logger, which will print all log messages to the device
// screen, as well as to adb logcat.
initializeLogging();
if (!checkPermissions()) {
requestPermissions();
} else {
callGoogleClient();
}
}
private void callGoogleClient() {
FitnessOptions fitnessOptions =
FitnessOptions.builder()
.addDataType(DataType.TYPE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)
.addDataType(DataType.TYPE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_WRITE)
.addDataType(DataType.AGGREGATE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)
.addDataType(DataType.AGGREGATE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_WRITE)
.addDataType(DataType.TYPE_ACTIVITY_SEGMENT, FitnessOptions.ACCESS_READ)
.addDataType(DataType.TYPE_ACTIVITY_SEGMENT, FitnessOptions.ACCESS_WRITE)
.build();
if (!GoogleSignIn.hasPermissions(GoogleSignIn.getLastSignedInAccount(this), fitnessOptions)) {
GoogleSignIn.requestPermissions(
this,
REQUEST_OAUTH_REQUEST_CODE,
GoogleSignIn.getLastSignedInAccount(this),
fitnessOptions);
} else {
getFitData();
}
}
private boolean checkPermissions() {
int permissionState = ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION);
int permissionState1 = ActivityCompat.checkSelfPermission(this,
Manifest.permission.BODY_SENSORS);
return permissionState == PackageManager.PERMISSION_GRANTED && permissionState1 == PackageManager.PERMISSION_GRANTED;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
if (requestCode == REQUEST_OAUTH_REQUEST_CODE) {
getFitData();
}
}
}
private void getFitData() {
if (mClient == null && checkPermissions()) {
mClient = new GoogleApiClient.Builder(this)
.addScope(new Scope(Scopes.FITNESS_LOCATION_READ))
.addScope(new Scope(Scopes.FITNESS_BODY_READ))
.addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ))
.addApi(Fitness.HISTORY_API)
.addConnectionCallbacks(
new GoogleApiClient.ConnectionCallbacks() {
@Override
public void onConnected(Bundle bundle) {
android.util.Log.i(TAG, "Connected!!!");
subscribeToFetching();
}
@Override
public void onConnectionSuspended(int i) {
if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_NETWORK_LOST) {
} else if (i
== GoogleApiClient.ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED) {
}
}
}
)
.enableAutoManage(this, 4, new GoogleApiClient.OnConnectionFailedListener() {
@Override
public void onConnectionFailed(ConnectionResult result) {
android.util.Log.i("onConnectionFailed", result.getErrorMessage());
}
})
.build();
}
}
private void
subscribeToFetching() {
new BackgroundFetching().execute();
}
private void getData() {
try {
Calendar cal = Calendar.getInstance();
Date now = new Date();
cal.setTime(now);
long endTime = cal.getTimeInMillis();
cal.add(Calendar.HOUR, -cal.getInstance().get(Calendar.HOUR_OF_DAY));
cal.add(Calendar.MINUTE, -cal.getInstance().get(Calendar.MINUTE));
cal.add(Calendar.SECOND, -cal.getInstance().get(Calendar.SECOND));
long startTime = cal.getTimeInMillis();
//long startTime = Long.parseLong("1535602500000");
android.util.Log.i(TAG, "Start Time: " + android.text.format.DateFormat.format("yyyy-MM-dd hh:mm:ss a", startTime));
android.util.Log.i(TAG, "End Time: " + android.text.format.DateFormat.format("yyyy-MM-dd hh:mm:ss a", endTime));
DataReadRequest readRequest = new DataReadRequest.Builder()
.aggregate(DataType.AGGREGATE_STEP_COUNT_DELTA, DataType.TYPE_STEP_COUNT_DELTA)
// .aggregate(DataType.TYPE_HEART_RATE_BPM, DataType.AGGREGATE_HEART_RATE_SUMMARY)
/// .aggregate(DataType.TYPE_CALORIES_EXPENDED, DataType.AGGREGATE_CALORIES_EXPENDED)
.enableServerQueries()
.bucketByTime(24, TimeUnit.HOURS)
.setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS)
.build();
PendingResult<DataReadResult> result = Fitness.HistoryApi.readData(mClient, readRequest);
result.setResultCallback(new ResultCallback<DataReadResult>() {
@Override
public void onResult(@NonNull DataReadResult dataReadResult) {
int totalSteps = 0;
if (dataReadResult.getBuckets().size() > 0) {
for (Bucket bucket : dataReadResult.getBuckets()) {
for (DataSet set : bucket.getDataSets()) {
for (DataPoint dp : set.getDataPoints()) {
for (Field field : dp.getDataType().getFields()) {
int steps = dp.getValue(field).asInt();
totalSteps += steps;
Toast.makeText(MainActivity.this, totalSteps, Toast.LENGTH_LONG).show();
}
}
}
}
}
}
});
} catch (Exception e) {
android.util.Log.i(TAG, "Error msg: " + e.getMessage());
}
}
private class BackgroundFetching extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... params) {
getData();
return null;
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the main; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_read_data) {
readData();
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* Initializes a custom log class that outputs both to in-app targets and logcat.
*/
private void initializeLogging() {
// Wraps Android's native log framework.
LogWrapper logWrapper = new LogWrapper();
// Using Log, front-end to the logging chain, emulates android.util.log method signatures.
Log.setLogNode(logWrapper);
// Filter strips out everything except the message text.
MessageOnlyLogFilter msgFilter = new MessageOnlyLogFilter();
logWrapper.setNext(msgFilter);
// On screen logging via a customized TextView.
LogView logView = (LogView) findViewById(R.id.sample_logview);
// Fixing this lint error adds logic without benefit.
// noinspection AndroidLintDeprecation
logView.setTextAppearance(R.style.Log);
logView.setBackgroundColor(Color.WHITE);
msgFilter.setNext(logView);
Log.i(TAG, "Ready");
}
private void requestPermissions() {
boolean shouldProvideRationale =
ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_FINE_LOCATION);
if (shouldProvideRationale) {
Snackbar.make(
findViewById(R.id.main_activity_view),
"RequestPremission",
Snackbar.LENGTH_INDEFINITE)
.setAction(R.string.intro_text, new View.OnClickListener() {
@Override
public void onClick(View view) {
// Request permission
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.BODY_SENSORS},
REQUEST_PERMISSIONS_REQUEST_CODE);
}
})
.show();
} else {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.BODY_SENSORS},
REQUEST_PERMISSIONS_REQUEST_CODE);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
android.util.Log.i(TAG, "onRequestPermissionResult");
if (requestCode == REQUEST_PERMISSIONS_REQUEST_CODE) {
if (grantResults.length <= 0) {
android.util.Log.i(TAG, "User interaction was cancelled.");
} else if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
callGoogleClient();
} else {
Snackbar.make(
findViewById(R.id.main_activity_view),
"Premission not Granted",
Snackbar.LENGTH_INDEFINITE)
.setAction(R.string.intro_text, new View.OnClickListener() {
@Override
public void onClick(View view) {
// Build intent that displays the App settings screen.
Intent intent = new Intent();
intent.setAction(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package",
BuildConfig.APPLICATION_ID, null);
intent.setData(uri);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
})
.show();
}
}
}
}
Issue by rubinbasha
Monday Jan 22, 2018 at 12:21 GMT
Originally opened as googlearchive/android-fit#30
"Google Fit broadcasts intents when any app starts or stops recording a session on behalf of the user. Fitness apps can register a listener to receive these intents."
Can we please have a sample of that? I am trying to implement one myself but not being able to receive intents right now and having a sample would be very helpful.
Kind regards,
Rubin
Issue by cmunter
Monday Apr 18, 2016 at 12:24 GMT
Originally opened as googlearchive/android-fit#16
Shouldn't BasicHistorySessions manifest include:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
Otherwise Request Permissions isn't shown
Issue by yadneshcompumatrice
Monday Jul 17, 2017 at 11:34 GMT
Originally opened as googlearchive/android-fit#24
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.