ECG Monitor

In this blog post we are going to show how to track on-demand data, using ECG as an example. Make sure you are acquainted with the general overview on using the Samsung Health Sensor SDK, by reading Samsung Health Sensor SDK Introduction. We created a sample application called ECG Monitor which allows you to track ECG using functionality covered in the article. You can download it and try it yourself.

ECG Monitor v1.3.0
(142.7 KB) Nov 21, 2025

How to Prepare for a Measurement

On successful connection to the Health Tracking Service, but before starting a measurement, we have to check if the device is able to track ECG data. We can do this by calling checkCapabilities():

List<HealthTrackerType> availableTrackers = 
healthTrackingService.getTrackingCapability().getSupportHealthTrackerTypes();

Make sure the returned list contains HealthTrackerType.ECG_ON_DEMAND:

if (!availableTrackers.contains(HealthTrackerType.ECG_ON_DEMAND)) {
    Toast.makeText(
    getApplicationContext(), getString(R.string.NoECGSupport), Toast.LENGTH_LONG)
    .show();
    Log.e(APP_TAG, "Device does not support ECG tracking");
    finish();
}

After that, we can set up the ECG Tracker object:

ecgTracker = healthTrackingService.getHealthTracker(HealthTrackerType.ECG_ON_DEMAND);

The next step is to prepare an event listener – an object to process incoming data. We create one at the start of the application and implement its functionality.

In this blog, we focus on the onDataReceived() event. It contains data gathered by the Samsung Health Sensor SDK as a list of data points. A full description of all elements of the list can be found in the API Reference document for ValueKey.EcgSet, so here we only focus on the necessary parts, which are LEAD_OFF and, of course, the ECG values.

Checking if Watch Electrodes Are In Contact

In order to track ECG values correctly, the watch electrodes must be in contact – meaning the watch must be worn tightly on the wrist and the user has to hold their index finger on the “Home” key. To track electrode contact, the LEAD_OFF flag is used. If its value is 0 – it means that electrodes are in contact. Otherwise – if it's 5 – it means the electrodes are not in contact. The ECG readings are valid only if the flag is set, otherwise they should be ignored.

The flag can be read in ValueKey.EcgSet:

final int isLeadOff = list.get(0).getValue(ValueKey.EcgSet.LEAD_OFF);

In the sample application we set a variable, which holds the current status of electrodes contact:

final int NO_CONTACT = 5;
if (isLeadOff == NO_CONTACT) {
	leadOff.set(true);
    return;
} else
	leadOff.set(false);

How to Read ECG Values

When the onDataReceived event is called, it provides a list of data points. The list has either 5 or 10 elements and each of them contains an ECG value. Since ECG has a 500 Hz sample rate, we are going to use last value from received list to show the most recent value on the UI. The following example shows how to receive last value obtained in a sample:

private final HealthTracker.TrackerEventListener ecgListener = 
new HealthTracker.TrackerEventListener() {
    @Override
    public void onDataReceived(@NonNull List<DataPoint> list) {
        if (list.size() == 0)
            return;
        curEcg.set(list.get(list.size() - 1).getValue(ValueKey.EcgSet.ECG_MV));

How to Track Incoming ECG Data

With the prerequisites in the previous steps done, we are now ready to measure ECG. First, we set up a listener:

ecgHandler.post(() -> ecgTracker.setEventListener(ecgListener));

We can now start receiving ECG data. Since the sampling frequency is 500 Hz, we cannot update the UI with each sample. Instead, we create a timer which updates ECG values every second for 30 seconds – the time required to make a successful measurement. In the timer, we analyze ECG data and act accordingly.

First, we check if both electrodes are in contact. If they are not, we show a warning to the user:

if (leadOff.get()) {
	runOnUiThread(() -> binding.txtOutput.setText(R.string.outputWarning));
}

If the data received is valid, we read the current average ECG value. After that, we update the UI with the result. For convenience, we also provide information on how much time is left until the end of the measurement:

else {
	final String measureValue = getString(R.string.MeasurementUpdate, timeLeft / 1000, 
    	String.format(Locale.ENGLISH, "%.2f", curEcg.get()));
    runOnUiThread(() -> binding.txtOutput.setText(measureValue));
}

After 30 seconds, the timer reaches its end, and we stop the measurement by unsetting the listener:

ecgTracker.unsetEventListener();

Finally, we update the UI for the last time – with either the last measured ECG value or an error if electrodes were not in contact.

These steps show how we can use on-demand sensors to perform an ECG measurement. We encourage you to try doing it yourself and explore the other available features provided by the Samsung Health Sensor SDK.