Skip to content

Body Metrics

github-actions[bot] edited this page Nov 9, 2026 · 1 revision

Status: Current implemented behavior. Audience: Users and contributors. Implementation: features/body, features/manualentry/body, data/repository/BodyRepository.kt. Navigation: Screen.Metric, body entry routes; widgets WEIGHT, HEIGHT, BMI, FFMI, BODY_FAT, LEAN_MASS, BMR, BONE_MASS, BODY_WATER_MASS. Related: Feature map, Manual entry of metrics, Statistics.

The body feature owns period-based detail screens for body measurement and composition metrics read from Health Connect.

Each body dashboard tile opens its own focused metric screen directly - tapping Weight opens the weight detail, not an intermediate Body overview.

Implemented Metrics

Body metric detail screens currently cover:

  • Weight.
  • Height.
  • BMI.
  • FFMI.
  • Body fat.
  • Lean mass.
  • Basal metabolic rate.
  • Bone mass.
  • Body water mass.

BMI and FFMI-style context are derived from available measurements. Derived values should explain missing prerequisites instead of pretending the calculation is complete.

FFMI

FFMI is derived, not read. The screen's headline is the dashboard tile's value: adjusted FFMI from the latest weight, body fat and height on record.

Its history (chart, statistics, entries) has one reading per body-fat measurement in the period, paired with the weight nearest it in time, which may sit just across the period's edge. A weigh-in with no body-fat reading adds no point: carrying an old body-fat percentage onto later weights would show fat lost as lean mass lost. Height is the latest on record, as BMI uses it. The readings are calculated, so their rows edit nothing.

Body Profile Weight And Height

Settings, Body profile holds a weight and a height alongside birth year and heart-rate values, and they are the same numbers the body metrics use.

  • When Health Connect has a recorded measurement, the field shows that value and is labelled as measured.
  • Changing the weight or the height also writes it to Health Connect as a real measurement, so the app does not hold a second private copy of a number it already has. Saving an unchanged card writes nothing, so opening the section repeatedly does not litter the body history.
  • When nothing has been recorded, or the app cannot write body measurements, the typed value is kept as a local preference and used the same way.

Either way there is one weight and one height, so BMI, FFMI context, Body Energy, and caffeine estimates all agree. See Settings and preferences.

Basal Metabolic Rate Estimate

Off by default. Settings, Body profile has a "Basal metabolic rate" switch. On, OpenVitals estimates the resting daily burn with Mifflin-St Jeor from the profile's sex, birth year, weight and height, and writes one BasalMetabolicRateRecord per day to Health Connect.

  • It is a writer like the step-distance backfill (data/sync/BmrEstimateService.kt, healthconnect/BmrEstimateHealthReader.kt): it runs as the last history drain after app open, and at once when the switch or the profile changes.
  • It covers the last 90 days. Each day uses the weight measured on or before it, falling back to the declared profile weight, so an old day is not rewritten with today's weight.
  • A day that already has a rate from any other source, a watch import or a CSV row included, is left alone, and a rate that arrives later evicts the estimate for that day.
  • Its records carry the openvitals_bmr_<date> client record id; nothing else is ever deleted. Switching off removes them all, and a purge that could not finish is retried by the next pass.
  • The card names which profile inputs are still missing; until they are all there nothing is written. The sex field exists only for this formula.

Detail Pattern

Body metrics follow the canonical period-detail pattern:

  • Day, week, month, and year ranges.
  • Previous/next period navigation capped at the current period.
  • Calendar selection and pull to refresh.
  • Period charts, selected-day entries, statistics, comparisons, personal baselines, and data confidence.
  • Week, month and year draw a trend line over a fitted scale; only Day uses the intraday chart.
  • Entry lists that allow edit/delete only for OpenVitals-created records.
  • Reorderable metric detail sections.

Manual body entry lives under features/manualentry/body and writes explicit user-entered records to Health Connect. The dashboard and body detail screens remain read-oriented.

Why A Line, Not A Calendar

Month and year used to hand these metrics to the calendar heatmap, which colours each day by how big its number is. That reads well for a quantity that can be zero and can be huge — steps, minutes — and reads as nothing at all for one that spends its life inside a two-kilo band. Forty dots of near-identical colour answered "did you weigh yourself on the 14th" while hiding the only thing the screen is opened for, which is which way the line is going.

Body measurements are levels, not accumulations, so they now draw the same trend line the heart and vitals screens have always drawn for the same shape of data. The y axis is fitted to the values rather than anchored at zero, because a kilogram of drift is invisible on a scale that starts at nothing.

Day keeps its own intraday chart, where the x axis is hours rather than dates.

Data Boundaries

The body feature reads through BodyRepository. New body metric work should keep feature-specific formatting, cards, charts, and rows in features/body; shared components should only move out when another feature really reuses them.


Generated from docs/features/body-metrics.md. Edit it there; changes made here are overwritten.

Home

Features

How-to

App

Reference

Engineering

Proposals

Releases

Project

Clone this wiki locally