עבודה עם יעדי כושר

יעדים הם יעדים באפליקציית Google Fit שהמשתמשים יכולים להגדיר בעצמם. הן מעודדות מוטיבציה של המשתמשים להיות פעילים כל יום. מתוך הפרופיל, המשתמשים יכולים להתאים את מספר הצעדים ונקודות הלב שהם רוצים להשיג בכל יום. פלטפורמת Fit מתעדת את היעדים ועוקבת אחר הפעילות היומית שלה ביחס ליעדים האלה.

חוויית משתמש טובה יותר עם יעדים

האפליקציה שלך יכולה לקרוא את היעדים של המשתמש, כדי לעקוב אחר היעדים האישיים שלו. כך תוכלו ליצור חוויה מושכת יותר. כדי להתחיל, משתמשים בלקוח GoalsClient כדי לקרוא את יעדי הצעדים ונקודות הלב של המשתמש. לאחר מכן משתמשים בלקוח HistoryClient כדי לבדוק עד כמה הוא קרוב ליעדים האלה.

הנתונים האלה יאפשרו למשתמשים לעבור בין אפליקציית Google Fit לבין האפליקציה שלהם בצורה חלקה, ולקבל מידע עקבי על שתי האפליקציות לגבי ההתקדמות שלהם לקראת יעדי הכושר שלהם.

תנו למשתמשים מוטיבציה להגיע ליעדים היומיים שלהם על ידי מתן עדכונים ותובנות הקשורים להתקדמות שלהם.

קריאת יעד

הדוגמה הבאה מראה איך ליצור לקוח כושר חדש ולקבל את היעד של דק' אימון קרדיו של המשתמש, או את 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;
}