Google 피트니스 REST API를 비롯한 Google 피트니스 API는 2026년에 지원 중단될 예정입니다. 2024년 5월 1일부터 개발자는 이러한 API를 사용하도록 가입할 수 없습니다.
이전할 API 또는 플랫폼에 관한 안내는 헬스 커넥트 이전 가이드를 참고하세요. 헬스 커넥트와 Google Fit API 및 Fitbit Web API를 비교하려면 헬스 커넥트 비교 가이드를 참고하세요.
헬스 커넥트 및 API와 통합하는 방법을 자세히 알아보세요.
피트니스 목표 사용
컬렉션을 사용해 정리하기
내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요.
Google 피트니스에서는 목표가 목표임
앱
사용자가 직접 설정할 수 있습니다 사용자가 콘텐츠를 이용할 때마다
있습니다. 사용자는 프로필 내에서 걸음 수와
목표로 하는 심장 강화 점수
확인할 수 있습니다 피트니스 플랫폼에서 사용자의 목표를 기록하고 매일 추적합니다.
방지할 수 있습니다.
목표를 설정하여 사용자 환경 개선
앱은 사용자의 목표를 읽고 개인 목표를 추적할 수 있습니다. 이
몰입도 높은 경험을 만드는 데 도움이 됩니다. 시작하려면
GoalsClient
드림
클라이언트가 사용자의 걸음 수 및 심장 강화 점수 목표를 읽을 수 있습니다. 그런 다음
HistoryClient
목표에 얼마나 근접했는지 확인할 수 있습니다.
이 데이터를 사용하여 사용자가 Google 피트니스와 앱 간에 전환하도록 지원
두 앱에서 모두 앱의 진행 상황에 대해 일관된 정보를 얻을 수 있습니다.
피트니스 목표를 달성할 수 있습니다.
업데이트와 유용한 정보를 제공하여 사용자가 일일 목표를 달성하도록 동기를 부여합니다.
도움이 될 수 있습니다
목표 읽기
다음 예는 새 피트니스 클라이언트를 만들고
사용자의 심장 강화 점수 목표, 또는 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"
자바
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")
}
자바
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;
}
달리 명시되지 않는 한 이 페이지의 콘텐츠에는 Creative Commons Attribution 4.0 라이선스에 따라 라이선스가 부여되며, 코드 샘플에는 Apache 2.0 라이선스에 따라 라이선스가 부여됩니다. 자세한 내용은 Google Developers 사이트 정책을 참조하세요. 자바는 Oracle 및/또는 Oracle 계열사의 등록 상표입니다.
최종 업데이트: 2025-08-31(UTC)
[null,null,["최종 업데이트: 2025-08-31(UTC)"],[[["\u003cp\u003eGoogle Fit goals, encompassing Steps and Heart Points, motivate users to maintain daily activity.\u003c/p\u003e\n"],["\u003cp\u003eYour app can utilize the \u003ccode\u003eGoalsClient\u003c/code\u003e and \u003ccode\u003eHistoryClient\u003c/code\u003e to access user goals and activity history, fostering a more personalized user experience.\u003c/p\u003e\n"],["\u003cp\u003eBy integrating with Google Fit goals, your app can seamlessly provide users with consistent progress updates and encourage them to achieve their fitness objectives.\u003c/p\u003e\n"],["\u003cp\u003eCode examples in Kotlin and Java demonstrate how to read user goals, track progress, and calculate the percentage of goal completion.\u003c/p\u003e\n"]]],[],null,["# Work with fitness goals\n\nGoals are targets in the [Google Fit\napp](https://play.google.com/store/apps/details?id=com.google.android.apps.fitness)\nthat users can set for themselves. They help motivate users to stay active every\nday. From within their profile, users can adjust how many Steps and\n[Heart Points](https://support.google.com/fit/answer/7619539) they want to aim\nfor each day. The Fit platform records their goals and tracks their daily\nactivity against these.\n\nCreate a better user experience with goals\n------------------------------------------\n\nYour app can read a user's goals to keep track of their personal targets. This\ncan help create a more engaging experience. To start, use the\n[`GoalsClient`](/android/reference/com/google/android/gms/fitness/GoalsClient)\nclient to read a user's Steps and Heart Points goals. Then use the\n[`HistoryClient`](/android/reference/com/google/android/gms/fitness/HistoryClient)\nclient to check how close they are to those goals.\n\nUse this data to help users switch between Google Fit and your app\nseamlessly, and get consistent information across both apps about their progress\ntowards their fitness goals.\n\nMotivate users to reach their daily goals by giving them updates and insights\nrelated to their progress.\n\nRead a goal\n-----------\n\nThe following example shows how to create a new Fitness client and get the\nuser's Heart Points goal, or `null` if they don't have a goal set. \n\n### Kotlin\n\n```kotlin\nprivate val fitnessOptions: FitnessOptions by lazy {\n FitnessOptions.builder()\n .addDataType(DataType.TYPE_HEART_POINTS, FitnessOptions.ACCESS_READ)\n .build()\n}\n\nprivate val goalsReadRequest: GoalsReadRequest by lazy {\n GoalsReadRequest.Builder()\n .addDataType(DataType.TYPE_HEART_POINTS)\n .build()\n}\n\nprivate fun getGoogleAccount(): GoogleSignInAccount =\n GoogleSignIn.getAccountForExtension(requireContext(), fitnessOptions)\n\n\nprivate fun readGoals() {\n Fitness.getGoalsClient(requireContext(), getGoogleAccount())\n .readCurrentGoals(goalsReadRequest)\n .addOnSuccessListener { goals -\u003e\n // There should be at most one heart points goal currently.\n goals.firstOrNull()?.apply {\n // What is the value of the goal\n val goalValue = metricObjective.value\n Log.i(TAG, \"Goal value: $goalValue\")\n\n // How is the goal measured?\n Log.i(TAG, \"Objective: $objective\")\n\n // How often does the goal repeat?\n Log.i(TAG, \"Recurrence: $recurrenceDetails\")\n }\n }\n}\n\nprivate val Goal.objective: String\n get() = when (objectiveType) {\n OBJECTIVE_TYPE_DURATION -\u003e\n \"Duration (s): ${durationObjective.getDuration(TimeUnit.SECONDS)}\"\n OBJECTIVE_TYPE_FREQUENCY -\u003e\n \"Frequency : ${frequencyObjective.frequency}\"\n OBJECTIVE_TYPE_METRIC -\u003e\n \"Metric : ${metricObjective.dataTypeName} - ${metricObjective.value}\"\n else -\u003e \"Unknown objective\"\n }\n\nprivate val Goal.recurrenceDetails: String\n get() = recurrence?.let {\n val period = when (it.unit) {\n Recurrence.UNIT_DAY -\u003e \"days\"\n Recurrence.UNIT_WEEK -\u003e \"weeks\"\n Recurrence.UNIT_MONTH -\u003e \"months\"\n else -\u003e \"Unknown\"\n }\n \"Every ${recurrence!!.count} $period\"\n } ?: \"Does not repeat\"\n```\n\n### Java\n\n```java\nprivate final FitnessOptions fitnessOptions = FitnessOptions.builder()\n .addDataType(DataType.TYPE_HEART_POINTS, FitnessOptions.ACCESS_READ)\n .build();\n\n\nprivate final GoalsReadRequest goalsReadRequest = new GoalsReadRequest.Builder()\n .addDataType(DataType.TYPE_HEART_POINTS)\n .build();\n\nprivate GoogleSignInAccount getGoogleAccount() {\n GoogleSignIn.getAccountForExtension(getApplicationContext(), fitnessOptions);\n}\n\n\nprivate void readGoals() {\n Fitness.getGoalsClient(getApplicationContext(), getGoogleAccount())\n .readCurrentGoals(goalsReadRequest)\n .addOnSuccessListener(goals -\u003e {\n // There should be at most one heart points goal currently.\n Optional\u003cGoal\u003e optionalGoal = goals.stream().findFirst();\n if (optionalGoal.isPresent()) {\n // What is the value of the goal\n double goalValue = optionalGoal.get().getMetricObjective().getValue();\n Log.i(TAG, \"Goal value: $goalValue\");\n\n // How is the goal measured?\n Log.i(TAG, \"Objective: ${getObjective(optionalGoal.get())}\");\n\n // How often does the goal repeat?\n Log.i(TAG, \"Recurrence: ${getRecurrenceDetails(optionalGoal.get())}\");\n }\n\n });\n}\n\nprivate String getObjective(Goal goal) {\n switch (goal.getObjectiveType()) {\n case OBJECTIVE_TYPE_DURATION:\n return \"Duration (s): ${goal.getDurationObjective().getDuration(TimeUnit.SECONDS)}\";\n case OBJECTIVE_TYPE_FREQUENCY:\n return \"Frequency : ${goal.getFrequencyObjective().getFrequency()}\";\n case OBJECTIVE_TYPE_METRIC:\n return \"Metric : ${goal.getMetricObjective().getDataTypeName()} - ${goal.getMetricObjective().getValue()}\";\n default:\n return \"Unknown objective\";\n }\n}\n\nprivate String getRecurrenceDetails(Goal goal) {\n Goal.Recurrence recurrence = goal.getRecurrence();\n if (recurrence == null) {\n return \"Does not repeat\";\n }\n\n StringBuilder recurrenceMessage = new StringBuilder(\"Every ${recurrence.getCount()}\");\n\n switch (recurrence.getUnit()) {\n case UNIT_DAY:\n recurrenceMessage.append(\"days\");\n break;\n case UNIT_WEEK:\n recurrenceMessage.append(\"weeks\");\n break;\n case UNIT_MONTH:\n recurrenceMessage.append(\"months\");\n break;\n default:\n recurrenceMessage.delete(0, recurrenceMessage.length());\n recurrenceMessage.append(\"Unknown\");\n break;\n }\n\n return recurrenceMessage.toString();\n}\n```\n\nCheck progress\n--------------\n\nAfter you have the user's Heart Points goal, you can use the\n[`HistoryClient`](/fit/android/history) to check their progress. The following\nexample shows how to check how many Heart Points the user has.\n**Note:** The time range for a goal is calculated based on its frequency. For example, for a daily goal, the current time is used to calculate when the day starts and ends. Where the goal is a daily goal, the code can be simplified by using [`HistoryClient.readDailyTotal()`](/android/reference/com/google/android/gms/fitness/HistoryClient#public-taskdataset-readdailytotal-datatype-datatype) instead of [`HistoryClient.readData()`](/android/reference/com/google/android/gms/fitness/HistoryClient#public-taskdatareadresponse-readdata-datareadrequest-request). This example only uses `HistoryClient.readData()` to show how Goal objects can be used to identify the start and end times of the current recurrence when you query for progress. \n\n### Kotlin\n\n```kotlin\nval current = Calendar.getInstance()\nval request = DataReadRequest.Builder()\n .read(DataType.TYPE_HEART_POINTS)\n .setTimeRange(\n goal.getStartTime(current, TimeUnit.NANOSECONDS),\n goal.getEndTime(current, TimeUnit.NANOSECONDS),\n TimeUnit.NANOSECONDS\n )\n .build()\n\nFitness.getHistoryClient(requireContext(), getGoogleAccount())\n .readData(request)\n .addOnSuccessListener { response -\u003e\n val heartPointsSet = response.dataSets.first()\n val totalHeartPoints = heartPointsSet.dataPoints.sumBy {\n it.getValue(Field.FIELD_INTENSITY).asFloat().toInt()\n }\n Log.i(TAG, \"Total heart points: $totalHeartPoints\")\n }\n```\n\n### Java\n\n```java\nCalendar current = Calendar.getInstance();\nDataReadRequest request = new DataReadRequest.Builder()\n .read(DataType.TYPE_HEART_POINTS)\n .setTimeRange(\n goal.getStartTime(current, TimeUnit.NANOSECONDS),\n goal.getEndTime(current, TimeUnit.NANOSECONDS),\n TimeUnit.NANOSECONDS\n )\n .build();\n\n\nFitness.getHistoryClient(getApplicationContext(), getGoogleAccount())\n .readData(request)\n .addOnSuccessListener(response -\u003e {\n Optional\u003cDataSet\u003e heartPointsSet = response.getDataSets().stream().findFirst();\n if (heartPointsSet.isPresent()) {\n int totalHeartPoints = 0;\n for (DataPoint dp : heartPointsSet.get().getDataPoints()) {\n totalHeartPoints += (int) dp.getValue(Field.FIELD_INTENSITY).asFloat();\n }\n\n Log.i(TAG, \"Total heart points: $totalHeartPoints\");\n }\n });\n```\n\nCalculate progress as a percentage\n----------------------------------\n\nIf you divide the total from the [check progress](#check-progress) example\nby the target in the [read a goal](#read-a-goal) example, you can calculate the\nprogress towards the goal as a percentage. \n\n### Kotlin\n\n```kotlin\nprivate fun calculateProgressPercentage(goal: Goal, response: DataReadResponse): Double {\n val goalValue = goal.metricObjective.value\n val currentTotal = response.dataSets.first().dataPoints.sumBy {\n it.getValue(Field.FIELD_INTENSITY).asFloat().toInt()\n }\n\n return (currentTotal.div(goalValue)).times(100.0)\n}\n```\n\n### Java\n\n```java\nprivate double calculateProgressPercentage(Goal goal, DataReadResponse response) {\n double goalValue = goal.getMetricObjective().getValue();\n Optional\u003cDataSet\u003e firstDataSet = response.getDataSets().stream().findFirst();\n if (!(firstDataSet.isPresent())) {\n return NaN;\n }\n double currentTotal = 0;\n for (DataPoint dp : firstDataSet.get().getDataPoints()) {\n currentTotal += (int)dp.getValue(Field.FIELD_INTENSITY).asFloat();\n }\n\n return (currentTotal / goalValue) * 100.0;\n}\n```"]]