Pracuj z celami fitnessowymi

Cele to cele w Google Fit które użytkownicy mogą samodzielnie ustawić. Pomagają motywować użytkowników do aktywności dzień. W profilu użytkownicy mogą ustawić liczbę kroków i liczby kroków Punkty kardio, które chcą osiągnąć na każdy dzień. Platforma Fit rejestruje swoje cele i śledzi ich codzienne w odniesieniu do tych kategorii.

Zadbaj o wrażenia użytkowników dzięki celom

Aplikacja może odczytywać cele użytkownika, aby śledzić jego osobiste cele. Pomoże to zwiększyć zaangażowanie użytkowników. Aby rozpocząć, użyj GoalsClient odczytanie celów użytkownika dotyczących kroków i punktów kardio. Następnie użyj HistoryClient aby sprawdzić, czy zbliżają się do osiągnięcia tych celów.

Użyj tych danych, aby ułatwić użytkownikom przełączanie się między Google Fit a Twoją aplikacją płynnie i bezproblemowo, uzyskując w obu aplikacjach spójne informacje o postępach w realizacji celów fitnessowych.

Zmotywuj użytkowników do osiągania codziennych celów, udostępniając im informacje i statystyki dotyczące ich postępów.

Czytanie celu

Poniższy przykład pokazuje, jak utworzyć nowego klienta Fitness i pobrać cel związany z punktami kardio, a jeśli użytkownik nie ma takiego celu, null.

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

Sprawdzanie postępów

Gdy ustalisz cel dotyczący punktów kardio dla użytkownika, możesz użyć strony HistoryClient, aby sprawdzić jego postępy. Poniżej przykład pokazuje, jak sprawdzić liczbę punktów kardio użytkownika.

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

Oblicz postęp w procentach

Jeśli podzielisz sumę z przykładu dotyczącego sprawdzania postępu według celu z przykładu odczytania celu, możesz obliczyć postęp w drodze do celu wyrażony w procentach.

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