public class Health
- Object
- Health
Entry point for the Codename One health API – reading and writing health data, watching it for changes, recording workouts, and streaming from Bluetooth health sensors.
Obtain the platform implementation via getInstance(); the returned
object is owned by the active port and is never null.
The API is split by role:
getStore()– the platform health store: samples, aggregates, writes and change subscriptions.getWorkouts()– live and recorded workout sessions.getSensors()– standard Bluetooth GATT health sensors: heart-rate straps, power meters, scales, blood-pressure cuffs, glucose meters.
Quick start
Health health = Health.getInstance();
if (health.getAvailability() != HealthAvailability.AVAILABLE) {
health.openProviderSetup();
return;
}
HealthStore store = health.getStore();
store.requestAuthorization(HealthAccess.read(HealthDataType.STEPS))
.onResult((asked, err) -> {
if (err == null) {
readTodaysSteps(store);
}
});
Two things that will surprise you
You cannot ask whether you may read. HealthKit deliberately refuses
to disclose read authorization – a denied read looks exactly like an
empty result. So requestAuthorization resolving true means the user
was asked, not that they agreed, and an empty query result means
“denied or no data” with no way to tell which. Never render that to a
user as “you denied access”; say “no data available”. See
HealthStore.getReadAuthorizationStatus(HealthDataType).
Android never wakes your app for new data. Health Connect has no
push mechanism, so subscriptions there are drained when your app runs.
Check HealthSubscription.isPushDelivery() rather than assuming.
Threading
Every method may be called from the EDT and returns immediately.
Change deliveries – HealthChangeListener and
HealthBackgroundListener – always arrive on the EDT. A background
delivery may run with no visible UI, after the OS relaunched your app.
Results of the operations you start arrive on the EDT, on every platform. Both mobile ports marshal every platform answer onto it, the shared post-processing of a large read hands back to it when it is done, and the local-backed stores – desktop, the simulator, JavaScript – do the same rather than answering on whichever thread happened to ask.
So a read started from a worker thread calls you back on the EDT everywhere, and a callback may touch components directly. This was once true only on iOS and Android, with the local stores answering inline; code written against the mobile behaviour then glitched on the desktop. It is one contract now.
Platform support
- iOS / watchOS – HealthKit. Requires the HealthKit entitlement and privacy usage strings; the build fails with an actionable message if they are missing.
- Android – Health Connect. Requires the provider app, a privacy-policy declaration and per-type permissions declared through build hints.
Two capabilities are deliberately not claimed by either mobile
store in this release, and both stores answer false rather than
pretending:
- Background delivery. Nothing relaunches or wakes your app for
new data on either platform, so subscriptions deliver when you call
HealthStore.drainChanges()and at no other time. Wire that into your foreground path, or intoBackgroundFetch. AskHealthStore.isBackgroundDeliverySupported()rather than assuming; HealthKit’sHKObserverQuerywould change this answer on iOS, and nothing here registers one yet. - Live workout sessions. Workouts are recorded rather than
OS-owned everywhere: your app feeds samples in and the session is
written on
end(). This is what Google documents for Android phones, and it is what iOS does here too even thoughHKWorkoutSessionexists on watchOS and iOS 26. CheckWorkoutManager.isLiveSessionSupported()andWorkoutManager.isSensorCollectionSupported()before designing around either. - JavaSE simulator – a scriptable virtual health store (Simulate -> Health Simulation) with synthetic data, permission scripting and fault injection.
- Desktop and JavaScript – no platform store exists, so these
report
HealthAvailability.LOCAL_ONLYand keep data locally. The sensor API works fully wherever Bluetooth LE does. - tvOS and all other ports – this base class is returned as-is and
reports health as unsupported; operations fail fast with
HealthError.NOT_SUPPORTED.
Constructors
protected Health() | Ports construct subclasses. |
Methods
public static Health getInstance() | Returns the platform-specific singleton owned by the current port. |
public boolean isSupported() | true when this port exposes health data in any form. |
public HealthAvailability getAvailability() | Whether a health store is usable right now, and if not, why. |
public HealthStore getStore() | The platform health store. |
public WorkoutManager getWorkouts() | Workout recording. |
public HealthSensors getSensors() | Bluetooth health sensors. |
public AsyncResource<Boolean> openHealthSettings() | Opens the operating system screen where the user can change health permissions – Settings on iOS, the Health Connect permission screen on Android. |
public AsyncResource<Boolean> openProviderSetup() | Sends the user to install or update the Health Connect provider. |
public List<String> getConfigurationProblems() | Build-configuration problems detected at runtime – a missing ios.NSHealthShareUsageDescription build hint, an absent Health Connect privacy-policy declaration. |
Inherited methods
Constructor details
Health
protected Health()getInstance().Method details
getInstance
public static Health getInstance()Health
instance that reports the feature as unsupported, so calling code
never needs a null check or a platform-specific if.isSupported
public boolean isSupported()true when this port exposes health data in any form. false on
the fallback base class.getAvailability
public HealthAvailability getAvailability()getStore
public HealthStore getStore()HealthError.NOT_SUPPORTED. Branch on
HealthStore.isSupported().getWorkouts
public WorkoutManager getWorkouts()getSensors
public HealthSensors getSensors()com.codename1.bluetooth.le, so it works
anywhere Bluetooth LE does, including the desktop and JavaScript
ports.openHealthSettings
public AsyncResource<Boolean> openHealthSettings()Opens the operating system screen where the user can change health
permissions – Settings on iOS, the Health Connect permission
screen on Android. Resolves false where no such screen exists.
This is the right response to a query that came back empty when you expected data, since on iOS you cannot tell denial from absence.
openProviderSetup
public AsyncResource<Boolean> openProviderSetup()getAvailability() is
HealthAvailability.PROVIDER_NOT_INSTALLED or
HealthAvailability.PROVIDER_UPDATE_REQUIRED; resolves false
elsewhere.getConfigurationProblems
public List<String> getConfigurationProblems()Build-configuration problems detected at runtime – a missing
ios.NSHealthShareUsageDescription build hint, an absent Health
Connect privacy-policy declaration. Empty when the app is
configured correctly.
Operations that need a missing entry throw
HealthConfigurationException carrying the same text. This method
reports the same diagnostics without throwing, so a diagnostics
screen or a test can assert on them.