Trabalhar com objetivos de condicionamento físico

As metas são metas no app Google Fit que os usuários podem definir por conta própria. Os objetivos ajudam a motivar os usuários a se manterem ativos todos os dias. No perfil, os usuários podem ajustar quantos passos e pontos cardio querem atingir por dia. A plataforma Fit registra os objetivos e monitora a atividade diária deles em relação a eles.

Criar uma experiência melhor do usuário com metas

Seu app pode ler as metas do usuário para acompanhar as metas pessoais dele. Isso pode ajudar a criar uma experiência mais envolvente. Para começar, use o cliente GoalsClient para ler as metas de passos e Pontos cardio de um usuário. Em seguida, use o cliente HistoryClient para verificar quanto falta para essas metas.

Use esses dados para ajudar os usuários a alternar entre o Google Fit e seu app com facilidade e receber informações consistentes em ambos os apps sobre o progresso em relação às metas de condicionamento físico.

Motive os usuários a atingir as metas diárias, oferecendo atualizações e insights relacionados ao progresso deles.

Ler um objetivo

O exemplo a seguir mostra como criar um novo cliente de condicionamento físico e conseguir a meta de Pontos cardio dos usuários, ou null se eles não tiverem um objetivo definido.

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

Verificar progresso

Depois de ter a meta de Pontos cardio dos usuários, você pode usar o HistoryClient para verificar o progresso deles. O exemplo abaixo mostra como verificar quantos Pontos cardio o usuário tem.

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

Calcular o progresso como uma porcentagem

Se você dividir o total do exemplo de progresso de verificação pelo objetivo no exemplo Ler uma meta, poderá calcular o progresso em relação à meta como uma porcentagem.

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