设定健身目标

目标是指 Google 健身中的目标 应用 用户可自行设置的键值对它们有助于激励用户 。用户可以在个人资料中调整步数和 他们希望达到的心肺强化分数 。Google 健身平台可以记录他们的目标,并跟踪每日目标 针对这些内容进行的活动。

利用目标打造更好的用户体验

您的应用可以读取用户的目标,以跟踪其个人目标。这个 有助于打造更具吸引力的体验。首先,请使用 GoalsClient 客户端读取用户的步数和心肺强化分数目标。然后使用 HistoryClient 客户需要了解他们离这些目标还有多远。

使用这些数据帮助用户在 Google 健身和您的应用之间切换 并在这两个应用中获得一致的进度信息 实现其健身目标。

向用户提供更新和数据分析,激励他们实现每日目标 与他们的进步息息相关

读取目标

以下示例展示了如何创建新的 Fitness 客户端并获取 用户的心肺强化分数目标,或 null(如果他们未设置目标)。

Kotlin

private val fitnessOptions: FitnessOptions by lazy {
    FitnessOptions.builder()
        .addDataType(DataType.TYPE_HEART_POINTS, FitnessOptions.ACCESS_READ)
        .build()
}

private val goalsReadRequest: GoalsReadRequest by lazy {
    GoalsReadRequest.Builder()
        .addDataType(DataType.TYPE_HEART_POINTS)
        .build()
}

private fun getGoogleAccount(): GoogleSignInAccount =
    GoogleSignIn.getAccountForExtension(requireContext(), fitnessOptions)


private fun readGoals() {
    Fitness.getGoalsClient(requireContext(), getGoogleAccount())
        .readCurrentGoals(goalsReadRequest)
        .addOnSuccessListener { goals ->
            // There should be at most one heart points goal currently.
            goals.firstOrNull()?.apply {
                // What is the value of the goal
                val goalValue = metricObjective.value
                Log.i(TAG, "Goal value: $goalValue")

                // How is the goal measured?
                Log.i(TAG, "Objective: $objective")

                // How often does the goal repeat?
                Log.i(TAG, "Recurrence: $recurrenceDetails")
            }
        }
}

private val Goal.objective: String
    get() = when (objectiveType) {
        OBJECTIVE_TYPE_DURATION ->
            "Duration (s): ${durationObjective.getDuration(TimeUnit.SECONDS)}"
        OBJECTIVE_TYPE_FREQUENCY ->
            "Frequency : ${frequencyObjective.frequency}"
        OBJECTIVE_TYPE_METRIC ->
            "Metric : ${metricObjective.dataTypeName} - ${metricObjective.value}"
        else -> "Unknown objective"
    }

private val Goal.recurrenceDetails: String
    get() = recurrence?.let {
        val period = when (it.unit) {
            Recurrence.UNIT_DAY -> "days"
            Recurrence.UNIT_WEEK -> "weeks"
            Recurrence.UNIT_MONTH -> "months"
            else -> "Unknown"
        }
        "Every ${recurrence!!.count} $period"
    } ?: "Does not repeat"

Java

private final FitnessOptions fitnessOptions = FitnessOptions.builder()
            .addDataType(DataType.TYPE_HEART_POINTS, FitnessOptions.ACCESS_READ)
            .build();


private final GoalsReadRequest goalsReadRequest = new GoalsReadRequest.Builder()
            .addDataType(DataType.TYPE_HEART_POINTS)
            .build();

private GoogleSignInAccount getGoogleAccount() {
    GoogleSignIn.getAccountForExtension(getApplicationContext(), fitnessOptions);
}


private void readGoals() {
    Fitness.getGoalsClient(getApplicationContext(), getGoogleAccount())
            .readCurrentGoals(goalsReadRequest)
            .addOnSuccessListener(goals -> {
                // There should be at most one heart points goal currently.
                Optional<Goal> optionalGoal = goals.stream().findFirst();
                if (optionalGoal.isPresent()) {
                    // What is the value of the goal
                    double goalValue = optionalGoal.get().getMetricObjective().getValue();
                    Log.i(TAG, "Goal value: $goalValue");

                    // How is the goal measured?
                    Log.i(TAG, "Objective: ${getObjective(optionalGoal.get())}");

                    // How often does the goal repeat?
                    Log.i(TAG, "Recurrence: ${getRecurrenceDetails(optionalGoal.get())}");
                }

    });
}

private String getObjective(Goal goal) {
    switch (goal.getObjectiveType()) {
        case OBJECTIVE_TYPE_DURATION:
            return "Duration (s): ${goal.getDurationObjective().getDuration(TimeUnit.SECONDS)}";
        case OBJECTIVE_TYPE_FREQUENCY:
            return "Frequency : ${goal.getFrequencyObjective().getFrequency()}";
        case OBJECTIVE_TYPE_METRIC:
            return "Metric : ${goal.getMetricObjective().getDataTypeName()} - ${goal.getMetricObjective().getValue()}";
        default:
            return "Unknown objective";
    }
}

private String getRecurrenceDetails(Goal goal) {
    Goal.Recurrence recurrence = goal.getRecurrence();
    if (recurrence == null) {
        return "Does not repeat";
    }

    StringBuilder recurrenceMessage = new StringBuilder("Every ${recurrence.getCount()}");

    switch (recurrence.getUnit()) {
        case UNIT_DAY:
            recurrenceMessage.append("days");
            break;
        case UNIT_WEEK:
            recurrenceMessage.append("weeks");
            break;
        case UNIT_MONTH:
            recurrenceMessage.append("months");
            break;
        default:
            recurrenceMessage.delete(0, recurrenceMessage.length());
            recurrenceMessage.append("Unknown");
            break;
    }

    return recurrenceMessage.toString();
}

查看进度

在达成用户的心肺强化分数目标后,您可以使用 HistoryClient 可查看进度。以下 示例展示了如何查看用户的心肺强化分数。

Kotlin

val current = Calendar.getInstance()
val request = DataReadRequest.Builder()
    .read(DataType.TYPE_HEART_POINTS)
    .setTimeRange(
        goal.getStartTime(current, TimeUnit.NANOSECONDS),
        goal.getEndTime(current, TimeUnit.NANOSECONDS),
        TimeUnit.NANOSECONDS
    )
    .build()

Fitness.getHistoryClient(requireContext(), getGoogleAccount())
    .readData(request)
    .addOnSuccessListener { response ->
        val heartPointsSet = response.dataSets.first()
        val totalHeartPoints = heartPointsSet.dataPoints.sumBy {
            it.getValue(Field.FIELD_INTENSITY).asFloat().toInt()
        }
        Log.i(TAG, "Total heart points: $totalHeartPoints")
    }

Java

Calendar current = Calendar.getInstance();
DataReadRequest request = new DataReadRequest.Builder()
        .read(DataType.TYPE_HEART_POINTS)
        .setTimeRange(
                goal.getStartTime(current, TimeUnit.NANOSECONDS),
                goal.getEndTime(current, TimeUnit.NANOSECONDS),
                TimeUnit.NANOSECONDS
        )
        .build();


Fitness.getHistoryClient(getApplicationContext(), getGoogleAccount())
        .readData(request)
        .addOnSuccessListener(response -> {
            Optional<DataSet> heartPointsSet = response.getDataSets().stream().findFirst();
            if (heartPointsSet.isPresent()) {
                int totalHeartPoints = 0;
                for (DataPoint dp : heartPointsSet.get().getDataPoints()) {
                    totalHeartPoints += (int) dp.getValue(Field.FIELD_INTENSITY).asFloat();
                }

                Log.i(TAG, "Total heart points: $totalHeartPoints");
            }
        });

以百分比计算进度

如果您将总数除以检查进度示例 阅读目标示例中的目标,您可以计算 以百分比表示目标的完成进度

Kotlin

private fun calculateProgressPercentage(goal: Goal, response: DataReadResponse): Double {
    val goalValue = goal.metricObjective.value
    val currentTotal = response.dataSets.first().dataPoints.sumBy {
        it.getValue(Field.FIELD_INTENSITY).asFloat().toInt()
    }

    return (currentTotal.div(goalValue)).times(100.0)
}

Java

private double calculateProgressPercentage(Goal goal, DataReadResponse response) {
    double goalValue = goal.getMetricObjective().getValue();
    Optional<DataSet> firstDataSet = response.getDataSets().stream().findFirst();
    if (!(firstDataSet.isPresent())) {
        return NaN;
    }
    double currentTotal = 0;
    for (DataPoint dp : firstDataSet.get().getDataPoints()) {
        currentTotal += (int)dp.getValue(Field.FIELD_INTENSITY).asFloat();
    }

    return (currentTotal / goalValue) * 100.0;
}