Example App - Exercise
migrating exercise app to samsung health data sdk as of july 2025, samsung health sdk for android has been deprecated while existing functionality will continue to operate for now, developers are strongly encouraged to migrate to samsung health data sdk to ensure long-term compatibility and continued support both sdks provide access to health data, stored in samsung health app this data may originate directly from the app itself, as is the case for steps, or from connected wearable devices such as the ring, watch or dedicated medical equipment samsung health data sdk offers several advantages over its predecessor more user-friendly api support for more features such as suspend functions cleaner and more compact source code for more information and resources, refer to samsung health data sdk introduction the steps on this page help you easily understand the overall process of migrating your app that reads and inserts exercise data to use the samsung health data sdk prerequisites set up your environment before you begin the integration, make sure that you have the following installed and ready android studio java jdk 17 or higher android mobile device compatible with the latest version of samsung health set up your android device refer to the following resources to set up your android device turn on the phone’s developer options run apps on a hardware device download samsung health data sdk visit samsung health data sdk page to download samsung health data sdk enable samsung health data sdk’s developer mode previously, samsung health sdk for android required developers to submit a partner request to gain access, which needed to be applied for and approved before use now, with samsung health data sdk, you can download and use the sdk in developer mode without submitting a partner request to enhance convenience for developers, samsung health data sdk has improved its developer mode functionality if you only need to read data from samsung health app, you can activate developer mode and proceed with development and testing without requiring a partner request for more information on developer mode, please refer to developer mode if you want to test writing data to samsung health app using samsung health data sdk or distribute your app, you need to obtain a partnership for samsung health data sdk you can request it by following this process project setup import sdk library replace samsung health sdk for android aar file in your project navigate to app/libs in your project replace samsung-health-data-1 5 1 aar with samsung-health-data-api- version aar from the downloaded sdk package app manifest when using samsung health data sdk, your app’s manifest should no longer include any entries related to health data permissions gradle settings sdk dependency update your module-level build gradle to include the correct dependency replace dependencies { implementation files "/libs/samsung-health-data-1 5 1 aar" } with entry samsung health data sdk version independent dependencies { implementation filetree mapof "dir" to "libs", "include" to listof "* aar" } other configuration add gson library to the dependencies of module-level build gradle dependencies { implementation "com google code gson gson 2 13 2" } apply the kotlin-parcelize plugin to the module-level build gradle plugins { id "kotlin-parcelize" } additionally, check the module-level build gradle file and include any other dependencies required by your implementation connect with samsung health after completing the initial setup, you are ready to connect your app to samsung health to access exercise data in the following paragraphs, we are going to show you how to migrate specific elements of logic from samsung health sdk for android to samsung health data sdk samsung health sdk for android with samsung health sdk for android, establishing a connection requires the following import healthdatastore import com samsung android sdk healthdata healthdatastore declare healthdatastore instance with lateinit var healthdatastore healthdatastore initialize the instance and start the connection with healthdatastore = healthdatastore context, listener also { it connectservice } these are the provided arguments listener – healthdatastore connectionlistener instance, used to observe the connection results and handle connection failures context – typically app or activity context samsung health data sdk with samsung health data sdk, establishing a connection is simpler, as there is no need to implement a connection listener import the following class import com samsung android sdk health data healthdatastore notethe class name healthdatastore class is the same as in samsung health sdk for android however, their import directories differ make sure that you are using the correct path we can now establish the connection and obtain a healthdatastore instance by calling healthdataservice getstore context here, context can be your app context request permissions upon successful connection to samsung health, your app must ensure that it has permissions to access the health data from samsung health since samsung sdks enforce data access control, defining and checking permissions must be done before any data operations are performed samsung health sdk for android in samsung health sdk for android, you must first create a permission set, specifying which data type your app intends to access and the access permission read or write for example, to request read and write permissions for exercise data val permissions = setof healthpermissionmanager permissionkey healthconstants exercise health_data_type, healthpermissionmanager permissiontype read , healthpermissionmanager permissionkey healthconstants exercise health_data_type, healthpermissionmanager permissiontype write then, to check existing permissions and request any that are missing, use the healthpermissionmanager class val permissionmanager = healthpermissionmanager healthdatastore runcatching { val grantedpermissions = permissionmanager ispermissionacquired permissions if grantedpermissions values all { it } { log i app_tag, "all required permissions granted" } else { log i app_tag, "not all required permissions granted" permissionmanager requestpermissions permissions, context setresultlistener permissionlistener } } onfailure { error -> error message? let { log i app_tag, it } } samsung health data sdk in samsung health data sdk, requesting data access permissions is simpler for example, to request read and write permissions for exercise data val permissions = setof permission of datatypes exercise, accesstype read , permission of datatypes exercise, accesstype write then, to check if all necessary permissions have been granted val grantedpermissions = healthdatastore getgrantedpermissions permissions val areallpermissionsgranted = grantedpermissions containsall permissions if there are any missing permissions, prompt the user to grant them try { val result = healthdatastore requestpermissions permissions, context // … } // catch any error read exercise data samsung health sdk for android in samsung health sdk for android, to read exercise data, you need to create a read request by defining the data type and time range set the data type using healthconstants exercise health_data_type and specify the local time range using setlocaltimerange, which accepts the start and end time in longs val readrequest = healthdataresolver readrequest builder setdatatype healthconstants exercise health_data_type setlocaltimerange healthconstants exercise start_time, healthconstants exercise time_offset, starttime, endtime build next, initialize a healthdataresolver object using the previously obtained healthdatastore instance and handler and launch the prepared readrequest to process the results for example, you can retrieve the device id associated with each recorded exercise this is useful when you want to determine which device the data originates from to achieve this, you can create an iterator to access healthdata that represents an exercise record val healthdataresolver = healthdataresolver healthdatastore, handler try { healthdataresolver read readrequest await run { try { val iterator = iterator while iterator hasnext { val healthdata = iterator next val deviceid = healthdata getstring healthconstants exercise device_uuid // process obtained deviceid or other data } } finally { close } } } catch exception exception { exception message? let { log i tag, it } } samsung health data sdk in samsung health data sdk, you can achieve the same result with simpler and more concise code as before, you need to create a read request first, create a localtimefilter to access data for the current day val starttime = localdate now atstartofday val endtime = localdatetime now val localtimefilter = localtimefilter of starttime, endtime then, apply it to the prepared request val readrequest = datatypes exercise readdatarequestbuilder setlocaltimefilter localtimefilter build to launch the request, simply call the readdata method of the healthdatastore instance, passing readrequest as an argument the result includes a datalist, which you can iterate through to access exercise data val exercisedatalist = healthdatastore readdata readrequest datalist exercisedatalist foreach { healthdatapoint -> val deviceid = healthdatapoint datasource? deviceid // process obtained deviceid or other data } read aggregated data for data types that represent summarized values, such as total, minimum, maximum or last values, you can use aggregate requests to compute these results samsung health sdk for android in samsung health sdk for android, to read aggregated data for a specific period, you need to create aggregaterequest with a defined time range and aggregation function for example, to read the total calories burned from exercise since the start of the day, you can call addfunction with aggregatefunction sum setlocaltimerange with starttime as the start of the day and endtime as the current time setdatatype with healthconstants exercise health_data_type below is an implementation of aggregaterequest that reads the total exercise calories since the start of the day note that you also need to define the key id to retrieve the aggregated data later val exercisetotalcaloriesid = "exercise_total_calories" val aggregaterequest = healthdataresolver aggregaterequest builder addfunction healthdataresolver aggregaterequest aggregatefunction sum, healthconstants exercise calorie, exercisetotalcaloriesid setlocaltimerange healthconstants exercise start_time, healthconstants exercise time_offset, starttime, endtime setdatatype healthconstants exercise health_data_type build next, launch the request synchronously and iterate through the results to get the total calories var totalcalories = 0 try { healthdataresolver aggregate aggregaterequest await run { try { val iterator = iterator if iterator hasnext { val healthdata = iterator next totalcalories = healthdata getint exercisetotalcaloriesid } } finally { close } } } catch exception exception { exception message? let { log i tag, it } } to get the total exercise duration, the logic remains the same the only difference is the property argument of the request’s addfunction , as well as the key to retrieve the aggregated data addfunction healthdataresolver aggregaterequest aggregatefunction sum, healthconstants exercise duration, "exercise_total_duration" samsung health data sdk in samsung health data sdk, it is simpler to get the aggregated data first, you need to create localtimefilter to define the time range val starttime = localdate now atstartofday val endtime = localdatetime now val localtimefilter = localtimefilter of starttime, endtime then, build an aggregaterequest instance by calling requestbuilder on the desired aggregate data type for exercise data, this could be either datatype exercisetype total_calories or datatype exercisetype total_duration the full request is shown below val aggregaterequest = datatype exercisetype total_calories requestbuilder setlocaltimefilter localtimefilter build to obtain the aggregated data, create an aggregate request and access the datalist since this type of request returns a single-element list containing the aggregated value, you can use kotlin’s mapnotnull function to extract it safely, ensuring it’s not null healthdatastore aggregatedata aggregaterequest datalist mapnotnull { it value } insert data let's explore how to insert prepared exercise data into samsung health samsung health sdk for android to insert data in samsung health sdk for android, you first need to create a healthdata instance that contains the exercise data to be inserted the health data includes the start time, end time, exercise type or duration, and live data time-series data across different exercise stages the livedata placeholder contains the user’s heart rate or speed across each exercise phase let's prepare a set of dummy data to insert in real-world scenarios, healthdata includes real-time measurements captured from wearable devices or other health and fitness equipment prepare data to be inserted first, create livedata - a list of objects of your custom data class exerciselivedata according to the documentation for samsung health sdk for android, it is recommended to provide start_time and at least one additional field for each instance of livedata for more details, please refer to livedata declare the start_time, heart_rate and speed data val livedatalist = listof exerciselivedata start_time = instant ofepochsecond 1766394000 toepochmilli , heart_rate = 144f, speed = 1 6f , exerciselivedata start_time = instant ofepochsecond 1766394030 toepochmilli , heart_rate = 146f, speed = 1 8f , // add more entries convert livedata list next, convert the livedata list to jsonblob bytearray format by using the sdk function getjsonblob this function takes a list of exerciselivedata as an argument and returns bytearray you can simply create a helper function for this task private fun createlivedata livedatalist list<exerciselivedata> bytearray { val zip = healthdatautil getjsonblob livedatalist return zip } create healthdata object create a healthdata object that holds all exercise data, including timestamps, calories, distance, duration and livedata the livedata is attached using the putblob function in addition to the standard fields start_time, end_time, and time_offset, it is necessary to specify the exercise type based on the predefined exercise type table, setting the value to 1002 represents a running exercise val calories = 73f val distance = 1000f val exercisetype = 1002 val starttime = instant ofepochsecond 1766394000 val endtime = instant ofepochsecond 1766394300 val duration = duration between starttime, endtime val timeoffset = timezone getdefault getoffset endtime toepochmilli tolong val healthdata = healthdata apply { sourcedevice = deviceid putlong healthconstants exercise start_time, starttime toepochmilli putlong healthconstants exercise end_time, endtime toepochmilli putlong healthconstants exercise time_offset, timeoffset putint healthconstants exercise exercise_type, exercisetype putlong healthconstants exercise duration, duration tomillis putfloat healthconstants exercise calorie, calories putfloat healthconstants exercise distance, distance putblob healthconstants exercise live_data, createlivedata livedatalist } insert the prepared data use a healthdataresolver class to build an insertrequest initialize a healthdataresolver instance and pass in the already connected healthdatastore utilize a builder function and set healthconstants exercise health_data_type as the data type retrieve the local device id using the healthdevicemanager instance, as you need to specify the source device that provides this data call the insert function with the prepared insertrequest and wait for the result below is an implementation example val handler = handler looper getmainlooper val healthdataresolver = healthdataresolver healthdatastore, handler try { val localdevice = healthdevicemanager healthdatastore localdevice uuid val data = exerciseinsertdata getexercisedata endtime, localdevice if data != null { val insertrequest = healthdataresolver insertrequest builder setdatatype healthconstants exercise health_data_type build insertrequest addhealthdata data val result = healthdataresolver insert insertrequest await if result status == healthresultholder baseresult status_successful { log i tag, "inserted running exercise count of data ${result count}" } else { log i tag, "inserting failed" } } } catch e exception { throw e } samsung health data sdk in samsung health data sdk, preparing livedata to be inserted into samsung health app is simplified by the help of the exerciselog class with predefined fields such as timestamp, heartrate, cadence and more, this class is ready to capture information for each phase of an exercise session this eliminates the need to manually encode it to jsonblob bytearray format instead, you can simply create a list of exerciselog objects, each representing a phase of the exercise val exerciselog = listof exerciselog of timestamp = instant ofepochsecond 1766394000 , heartrate = 144f, speed = 1 6f, cadence = null, count = null, power = null , exerciselog of timestamp = instant ofepochsecond 1766394030 , heartrate = 146f, speed = 1 8f, cadence = null, count = null, power = null // add more entries create a healthdatapoint instance another key difference in samsung health data sdk is that, instead of creating a healthdata instance, the sdk provides a healthdatapoint object that represents the entire exercise before creating a healthdatapoint instance, you need the following list of exerciselog objects predefined exercise type use addfielddata function to set the exercise type property with a predefined enum value and include list of datatype exercisetype sessions exercisesession object in the running exercise, there will always be a single-element list - an exercisesession element created based on a previously defined list of exerciselog objects to create an exercisesession object, use exercisesession builder and set the relevant data, such as start time, end time, exercise type, calories and duration once the relevant information is prepared, you can call the builder method to initialize a healthdatapoint instance and set the properties, such as start time, end time, and exercise type, by calling the addfielddata function the code is shown below val calories = 73f val distance = 1000f val starttime = instant ofepochsecond 1766394000 val endtime = instant ofepochsecond 1766394300 val duration = duration between starttime, endtime var healthdatapoint healthdatapoint? try { val session = exercisesession builder setstarttime starttime setendtime endtime setexercisetype datatype exercisetype predefinedexercisetype running setduration duration setcalories calories setdistance distance setcomment "routine running" setlog exerciselog build healthdatapoint = healthdatapoint builder setstarttime starttime setendtime endtime addfielddata datatype exercisetype exercise_type, datatype exercisetype predefinedexercisetype running addfielddata datatype exercisetype sessions, listof session build } catch e exception { throw e } insert the prepared data to insert the prepared data, simply build insertrequest by calling the insertdatarequestbuilder method on datatypes exercise attach the created data healthdatapoint instance by calling the adddata function finalize the request with the build method next, call the insertdata method of the healthdatastore instance and pass the created insertrequest as an argument val insertrequest = datatypes exercise insertdatarequestbuilder adddata data build healthdatastore insertdata insertrequest exception handling robust health apps can recover when things go wrong let's examine the differences between both sdks when handling such scenarios samsung health sdk for android in the case of samsung health sdk for android, the methods for handling errors depend on the exception types for example, connection exceptions with samsung health are handled by the healthdatastore connectionlistener's event handler you can use the healthconnectionerror class to check whether the error has a resolution based on the error type, you can implement different handling strategies for exceptions related to requests such as reading or writing data, refer to the healthresultholder baseresult class and its getstatus method however, since there are no dedicated exception class, developers must handle the exceptions that are part of the standard java language, such as illegalargumentexception, securityexception or illegalstateexception samsung health data sdk when working with samsung health data sdk, key functions such as aggregatedata , requestpermissions , or getgrantedpermissions may throw exceptions under certain conditions to prevent unexpected crashes or blank screens, it’s best to funnel these exceptions into a central error handler you can do so by wrapping every api invocation with try { // sdk function invocation } catch e healthdataexception { handlehealthdataexception e } about healthdataexception healthdataexception is the main exception class for samsung health data sdk the handlehealthdataexception function • shows an error log • tries to “resolve” the exception some healthdataexception instances include a resolution intent you can check if the exception has a resolution by checking the hasresolution property of the exception object and trying to fix it by invoking resolve examples of such exceptions • err_old_version_platform indicates samsung health app is outdated • err_platform_not_installed signals that samsung health app is not installed in both cases, the resolution involves opening the device’s app marketplace to prompt the user to install or update samsung health app once the issue is fixed, control returns to the app so it can continue functioning this approach not only keeps your ui clean, but allows for a consistent, guided error experience when something goes wrong, users can see a clear message of what happened and how to fix it include migration completion information in the app manifest please add the following details to the androidmanifest xml file of your app <manifest > <application > <meta-data android name="com samsung android sdk health data migration_completed" android value="true"/> </application> </manifest> summary we have covered how to migrate an app that uses samsung health sdk for android to samsung health data sdk when migrating your app to samsung health data sdk, you can follow the described process and code examples to complete the migration for more details, please refer to samsung health data sdk introduction partner request before distributing your app the developer mode of samsung health data sdk is a feature provided solely for development purposes to ensure that an app using samsung health data sdk functions properly without enabling developer mode, you need to submit a partner request through the developer site before distributing your app on app marketplaces after the partner app is approved, the app's detailed information will be registered in samsung's system having a trouble? we are operating a developer support channel on the samsung developer site if you encounter any issue or any question, please visit developer support and submit your query after logging in your samsung account