API Google Fit: отдалитесь от Google Fit

Как рассчитать расстояние, пройденное пользователем, с помощью API Google Fit? В настоящее время я использую Google Fit History Api следующим образом:

DataReadRequest readRequest = new DataReadRequest.Builder()
                  .aggregate(DataType.TYPE_DISTANCE_DELTA, DataType.AGGREGATE_DISTANCE_DELTA)
                  .bucketByTime(1, TimeUnit.DAYS)
                  .setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS)
                  .build();

          DataReadResult dataReadResult =
                  Fitness.HistoryApi.readData(mGoogleApiClient, readRequest).await(1, TimeUnit.MINUTES);

Но это не возвращает никакого значения. Кто-нибудь знает?


person Ankita Chopra    schedule 30.09.2016    source источник
comment
вы нашли какое-нибудь решение? Столкнулся с той же проблемой.   -  person Smeet    schedule 27.11.2016
comment
нет.. все еще сталкиваюсь с той же проблемой   -  person Ankita Chopra    schedule 27.11.2016


Ответы (5)


Вам нужно добавить еще одну область при создании экземпляра GoogleApiClient.Builder:

".addScope (новый объем (Scopes.FITNESS_LOCATION_READ))"

И вам также необходимо получить разрешение на местоположение, добавив это разрешение в файл манифеста:

<manifet>

  ...

  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

  <aplication/>

 </manifest>

и в своей деятельности добавьте этот метод:

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 — это мой собственный класс, вы можете использовать его для быстрого просмотра, если хотите сначала увидеть результат:

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();
        }
    }
}

Это мой способ получить от пользователя разрешение на определение местоположения путем создания моего собственного диалогового окна Rational. Вы можете сделать это по-другому, выполнив поиск в Google, как получить разрешение на определение местоположения.

Надеюсь, это поможет,

Мттдат.

person Nguyen Tan Dat    schedule 27.04.2017

Вы должны добавить область, как показано ниже:

.addScope (новая область (области. FITNESS_LOCATION_READ))

person Smeet    schedule 28.11.2016
comment
где добавить объем? - person abdul khan; 12.04.2017

Попробуйте ознакомиться с руководством по записать тренировку. После того, как вы запишете свои данные о физической подготовке, попробуйте прочитать руководство по работе с наборами данных, чтобы получить доступ к типу данных com.google.distance.delta, который представляет собой пройденное расстояние.

Вот репозиторий Google Fit с реальными примерами кода.

person noogui    schedule 03.10.2016
comment
У меня была аналогичная проблема, когда я пытался получить доступ к new GoogleApiClient.Builder(this).addApi(Fitness.HISTORY_API).addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE)) после нескольких часов чтения документов и поиска решений; выяснил, что единственным способом запроса разрешений на доступ к сервисам Google Play является запуск из подписанного приложения с тем же хранилищем ключей, в котором вы сгенерировали ключ SHA1 для Google OAuth2. Установка отладочного подписанного apk решила проблему для меня. - person Awi; 12.09.2017

Чтобы получить расстояние, пройденное пользователем, используйте приведенный ниже код и дайте мне знать, если потребуется дополнительная помощь. Приведенный ниже код получит текущую дневную дистанцию. Чтобы получить расстояние на большее количество дней, мы можем получить список мероприятий, откуда мы можем получить расстояние на большее количество дней.

 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;
        }
    }
person Jyot    schedule 16.04.2018

Ответы устарели. С новейшим API вы делаете это так:

Однако ваш запрос в порядке, вам нужны упомянутые выше разрешения. Вы больше не указываете область действия.

Запрашиваю подключение:

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)
person Jacek Kwiecień    schedule 16.10.2019