【问题标题】:Google Fit API : Get distance from google fitGoogle Fit API:获取与 google fit 的距离
【发布时间】:2016-09-30 04:43:16
【问题描述】:

如何使用 google fit API 计算用户走过的距离? 目前我正在使用这样的 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);

但这并没有返回任何值 有人知道吗?

【问题讨论】:

  • 你找到解决办法了吗?面临同样的问题。
  • no.. 仍然面临同样的问题

标签: google-fit google-fit-sdk


【解决方案1】:

您需要在实例化 GoogleApiClient.Builder 时再添加一个范围:

".addScope(new Scope(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 上搜索如何获得位置权限来以不同的方式进行。

希望这会有所帮助,

时间。

【讨论】:

    【解决方案2】:

    您必须添加以下范围:

    .addScope(new Scope(Scopes.FITNESS_LOCATION_READ))

    【讨论】:

    • 在哪里添加范围?
    【解决方案3】:

    尝试查看如何使用Record a Workout 指南。之后,记录您的健身数据,尝试阅读Working with Datasets 指南以访问com.google.distance.delta 数据类型,即所覆盖的距离。

    这是实际代码示例的Google Fit repo

    【讨论】:

    • 在阅读文档数小时并尝试解决方案后,我在尝试访问 new GoogleApiClient.Builder(this).addApi(Fitness.HISTORY_API).addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE)) 时遇到了类似的问题;发现要求访问 Google Play 服务的唯一方法是当您从 签名的应用程序 运行时,使用与 Google 的 OAuth2 生成 SHA1 密钥相同的密钥库。安装一个调试签名的 apk,为我解决了这个问题。
    【解决方案4】:

    要获得用户覆盖的距离,请使用下面的代码,如果需要任何进一步的帮助,请告诉我。下面的代码将获得当天的距离。为了获得更多天的距离,我们可以获取活动列表,从中我们可以获得更多天的距离。

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

    【讨论】:

      【解决方案5】:

      答案已弃用。使用最新的 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)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多