How do I calculate the distance covered by the user using the google fit API? Currently I am using google Fit History Api like this :
DataReadRequest readRequest
You have to add the scope as below:
.addScope(new Scope(Scopes.FITNESS_LOCATION_READ))
The answers are deprecated. With the newest api you do it like this:
Your request is fine however, you need those permissions mentioned above. You don't specify scope anymore tho.
Asking for connection:
val FITNESS_OPTIONS: FitnessOptions = FitnessOptions.builder()
.addDataType(//any other you might need)
.addDataType(DataType.AGGREGATE_DISTANCE_DELTA, FitnessOptions.ACCESS_READ)
.build()
GoogleSignIn.requestPermissions(
activity,
YOUR_INT_AUTH_CODE_FOR_ON_ACTIVITY_RESULT,
GoogleSignIn.getLastSignedInAccount(context),
GoogleFit.FITNESS_OPTIONS)
To get distance covered by user, use below code and let me know if any further assistance required. The below code will get current day distance. To get distance for more days we can get list of activities from where we can get distance of more days.
private double getTodayDistance() {
PendingResult<DailyTotalResult> result = Fitness.HistoryApi.readDailyTotal(mClient, DataType.TYPE_DISTANCE_DELTA);
DailyTotalResult totalResult = result.await(1, TimeUnit.DAYS);
if (totalResult.getStatus().isSuccess()) {
DataSet totalSet = totalResult.getTotal();
if (totalSet != null && !totalSet.isEmpty()) {
return baseActivity.getMiles((totalSet.getDataPoints().get(0).getValue(Field.FIELD_DISTANCE)).asFloat());
} else {
android.util.Log.w(TAG, "There was a problem getting the calories.");
return 0;
}
} else {
return 0;
}
}
Try to check the How to Record a Workout guide. After, recording your fitness data, try reading the Working with Datasets guide in order to access the com.google.distance.delta
data type which is the distance covered.
Here's the Google Fit repo for actual code samples.
You need to add one more scope when you instantiate GoogleApiClient.Builder:
".addScope(new Scope(Scopes.FITNESS_LOCATION_READ))"
And you also need to gain Location permission by adding this permission in manifest file:
<manifet>
...
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<aplication/>
</manifest>
and in your activity, add this method:
public void request_location_permission() {
// If location permission was not granted yet, request it. Otherwise, request nothing and
// just do what you want.
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) !=
PackageManager.PERMISSION_GRANTED) {
PermissionUtils.requestPermission(this, LOCATION_PERMISSION_REQUEST_CODE,
Manifest.permission.ACCESS_FINE_LOCATION, false);
} else {
process();
}
}
PermissionUtils is my own class, you can use it to have a prompt look if you want to see a result first:
public abstract class PermissionUtils {
/**
* Requests the fine location permission. If a rationale with an additional explanation should
* be shown to the user, displays a dialog that triggers the request.
*/
public static void requestPermission(AppCompatActivity activity, int requestId,
String permission, boolean finishActivity) {
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)) {
// Display a dialog with rationale, this dialog wil request permission by itself.
PermissionUtils.RationaleDialog.newInstance(requestId, finishActivity)
.show(activity.getSupportFragmentManager(), "dialog");
} else {
// Location permission has not been granted yet, request it.
ActivityCompat.requestPermissions(activity, new String[]{permission}, requestId);
}
}
/**
* Checks if the result contains a {@link PackageManager#PERMISSION_GRANTED} result for a
* permission from a runtime permissions request.
*
* @see android.support.v4.app.ActivityCompat.OnRequestPermissionsResultCallback
*/
public static boolean isPermissionGranted(String[] grantPermissions, int[] grantResults,
String permission) {
for (int i = 0; i < grantPermissions.length; i++) {
if (permission.equals(grantPermissions[i])) {
return grantResults[i] == PackageManager.PERMISSION_GRANTED;
}
}
return false;
}
/**
* A dialog that displays a permission denied message.
*/
public static class PermissionDeniedDialog extends DialogFragment {
private static final String ARGUMENT_FINISH_ACTIVITY = "finish";
private boolean mFinishActivity = false;
/**
* Creates a new instance of this dialog and optionally finishes the calling Activity
* when the 'Ok' button is clicked.
*/
public static PermissionDeniedDialog newInstance(boolean finishActivity) {
Bundle arguments = new Bundle();
arguments.putBoolean(ARGUMENT_FINISH_ACTIVITY, finishActivity);
PermissionDeniedDialog dialog = new PermissionDeniedDialog();
dialog.setArguments(arguments);
return dialog;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
mFinishActivity = getArguments().getBoolean(ARGUMENT_FINISH_ACTIVITY);
return new AlertDialog.Builder(getActivity())
.setMessage(R.string.location_permission_denied)
.setPositiveButton(android.R.string.ok, null)
.create();
}
@Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
if (mFinishActivity) {
Toast.makeText(getActivity(), R.string.permission_required_toast,
Toast.LENGTH_SHORT).show();
getActivity().finish();
}
}
}
/**
* A dialog that explains the use of the location permission and requests the necessary
* permission.
* <p>
* The activity should implement
* {@link android.support.v4.app.ActivityCompat.OnRequestPermissionsResultCallback}
* to handle permit or denial of this permission request.
*/
public static class RationaleDialog extends DialogFragment {
private static final String ARGUMENT_PERMISSION_REQUEST_CODE = "requestCode";
private static final String ARGUMENT_FINISH_ACTIVITY = "finish";
private boolean mFinishActivity = false;
/**
* Creates a new instance of a dialog displaying the rationale for the use of the location
* permission.
* <p>
* The permission is requested after clicking 'ok'.
*
* @param requestCode Id of the request that is used to request the permission. It is
* returned to the
* {@link android.support.v4.app.ActivityCompat.OnRequestPermissionsResultCallback}.
* @param finishActivity Whether the calling Activity should be finished if the dialog is
* cancelled.
*/
public static RationaleDialog newInstance(int requestCode, boolean finishActivity) {
Bundle arguments = new Bundle();
arguments.putInt(ARGUMENT_PERMISSION_REQUEST_CODE, requestCode);
arguments.putBoolean(ARGUMENT_FINISH_ACTIVITY, finishActivity);
RationaleDialog dialog = new RationaleDialog();
dialog.setArguments(arguments);
return dialog;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Bundle arguments = getArguments();
final int requestCode = arguments.getInt(ARGUMENT_PERMISSION_REQUEST_CODE);
mFinishActivity = arguments.getBoolean(ARGUMENT_FINISH_ACTIVITY);
return new AlertDialog.Builder(getActivity())
.setMessage(R.string.permission_rationale_location)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// After click on Ok, request the permission.
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
requestCode);
// Do not finish the Activity while requesting permission.
mFinishActivity = false;
}
})
.setNegativeButton(android.R.string.cancel, null)
.create();
}
@Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
if (mFinishActivity) {
Toast.makeText(getActivity(),
R.string.permission_required_toast,
Toast.LENGTH_SHORT)
.show();
getActivity().finish();
}
}
}
This is my way to get granted Location permission from user by creating my own Rational dialog, you can do in a different way by searching how to get location permission on google.
Hope this will help,
Mttdat.