Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Programming Guide
Table of Contents
1.
OVERVIEW .........................................................................................................................................................4
1.1. DATA FRAMEWORK................................................................................................................................................. 4
1.2. ARCHITECTURE ........................................................................................................................................................ 5
1.2.1.
DATA SOURCE DEVICE ..................................................................................................................................... 5
1.2.2.
DATA FRAMEWORK......................................................................................................................................... 5
1.2.3.
SAMSUNG DIGITAL HEALTH APPLICATION...................................................................................................... 5
2.
DEVELOPMENT ENVIRONMENT......................................................................................................................... 11
2.1. PREREQUISITES ..................................................................................................................................................... 11
2.2. DOWNLOADING HEALTH DATA OF SAMSUNG DIGITAL HEALTH SDK .................................................................. 11
2.3. TESTING YOUR APPLICATION WITH HEALTHDEVAPP ........................................................................................... 12
2.4. PUBLISHING YOUR APPLICATION .......................................................................................................................... 13
3.
4.
5.
6.
SAMPLE APPLICATIONS..................................................................................................................................... 41
6.1. SIMPLEHEALTH ...................................................................................................................................................... 41
6.1.1.
MAINACTIVITY ............................................................................................................................................... 42
6.1.2.
STEPCOUNTREPORTER .................................................................................................................................. 44
6.2. FOODNOTE ............................................................................................................................................................ 46
6.2.1.
MAINACTIVITY ............................................................................................................................................... 48
6.2.2.
CHOOSEFOODACTIVITY ................................................................................................................................. 50
6.2.3.
MEALSTOREACTIVITY .................................................................................................................................... 51
Page | 2
6.2.4.
Programming Guide
FOODDATAHELPER ........................................................................................................................................ 52
APPENDIX A.
APPENDIX B.
COPYRIGHT .............................................................................................................................................................. 59
Page | 3
Programming Guide
1. Overview
Health is a main keyword nowadays and related services are increasing continuously with the need for health
improvement. Samsung Digital Health SDK helps developers to make useful health applications that handle health
data safely, and share health data with other applications based on users consent.
Description
Data Framework
S Health
An application that helps that monitors users activities and helps user makes a healthier life
with pedometer, exercise, heart rate, and etc.
Its written as italic in this document.
Table 1: Glossary
1.1.Data Framework
The Data Framework of Samsung Digital Health SDK provides the following features:
-
Page | 4
Programming Guide
Privacy
Granting permission based on users consent to read or write the specific data type
1.2.Architecture
The Data Framework of Samsung Digital Health is designed to provide safe access for health data and a seamless
health service to user. Figure 2 is the architecture for the Data Framework of Samsung Digital Health.
Page | 5
Programming Guide
develop applications even if S Health is not installed in the device. You c and find it in the [samsung-digitalhealth-healthdata]\Tools folder.
Figure 3 shows the relationship between classes and interfaces of the com.samsung.android.sdk.healthdata
package. Detailed descriptions for each class and interface are in the API Reference under the [samsung-digitalhealth-healthdata]\Docs\API Reference folder.
HealthDataService initializes the Health data service. APIs of the com.samsung.android.sdk.healthdata
works properly after initialize() is called without an exception.
HealthDataStore handles the connection to the data storage of the device. It receives its connection result with
HealthDataStore.ConnectionLsitener. Most requests require the connection to the health data store.
The Data Framework provides classes and interface to insert, read, update, or delete health data.
HealthDataResolver is a central class to handle health data. It sends a data request with related request
interfaces and gets a result through HealthResultHolder. The result can be received immediately with
HealthDataHolder.BaseResult, HealthDataResolver.ReadResult or
HealthDataResolver.AggregateResult. Or it can be received asynchronously with
HealthResultHolder.ResultListener. See 4.1 for more information.
Page | 6
Programming Guide
<<interface>>
HealthDataStore.ConnectionListener
HealthDataService
HealthDataStore
HealthDeviceManager
+initialize()
<<interface>>
HealthResultHolder
HealthDataResolver
<<interface>>
HealthResultHolder.ResultListener
HealthDataResolver.Filter
<<interface>>
HealthDataResolver.ReadRequest
HealthDevice
HealthDevice.Builder
HealthDataResolver.ReadRequest.Builder
HealthResultHolder.BaseResult
<<interface>>
HealthDataResolver.InsertRequest
HealthData
HealthDataResolver.ReadResult
HealthDataResolver.InsertRequest.Builder
HealthDataResolver.AggregateResult
<<interface>>
HealthDataResolver.UpdateRequest
HealthDataResolver.UpdateRequest.Builder
<<interface>>
HealthDataResolver.DeleteRequest
HealthDataResolver.DeleteRequest.Builder
<<interface>>
HealthDataResolver.AggregateRequest
HealthDataResolver.AggregateRequest.Builder
Page | 7
Programming Guide
Application developers can use platform-defined data types that Samsung Digital Health provides. See 4.2 for more
information. Especially HealthConstants.Common contains the following mandatory properties for health data.
-
HealthConstants.Common is the base class of predefined data types of Samsung Digital Health as in Figure 4.
Page | 8
Programming Guide
Users health data can be accessed with the users consent. Figure 5 shows relationship between classes and
interface related to HealthPermissionManager. It requests permissions with
HealthPermissionManager.PermissionKey that contains the required permission to read or write for the
specific health data type. The permission result can be received synchronous or asynchronously. See 4.3 for more
information.
<<interface>>
HealthDataStore.ConnectionListener
HealthDataStore
HealthPermissionManager
<<interface>>
HealthResultHolder
HealthPermissionManager.PermissionKey
<<interface>>
HealthResultHolder.ResultListener
HealthResultHolder.BaseResult
HealthPermissionManager.PermissionType
HealthPermissionManager.PermissionResult
com.samsung.android.sdk.healthdata
Main interfaces and classes in the library are described in Table 2. See the API reference on details.
com.samsung.android.sdk.healthdata
Interface / Class
Description
HealthConnectionErrorResult
This class handles errors for connection failure to the health data store.
HealthConstants
This class defines constants of health data and contains interfaces for various kinds of
health data such as the count of steps or exercise.
HealthData
This class is an object for a health data type, e.g., the blood pressure or weight.
Quantitative and qualitative values can be specified for the specific health data type
based on its data structure definition. It is used to manage health data with
HealthDataResolver.
HealthDataObserver
HealthDataResolver
This class accesses health data to insert, read, update, and delete with the filter and
aggregate functions.
HealthDataService
HealthDataStore
This class handles the connection to the data store in the device.
HealthDataUnit
This class provides unified units for the health data store.
Page | 9
Programming Guide
HealthDevice
This class contains detailed device information that provides health data.
HeatlthDeviceManager
HealthPermissionManager
This class requests permission to read or write health data for the specific health data
type.
HealthResultHolder
HealthUserProfile
Page | 10
Programming Guide
2. Development Environment
To develop applications with Samsung Digital Health features, check prerequisites for the SDK first.
2.1.Prerequisites
Before downloading Samsung Digital Health SDK, refer to the following information.
Android Version
Android 4.4 KitKat (API level 19) or above
Available Devices
Samsung Android devices (KitKat or above)
Description
API Reference
Describes Samsung Digital Health APIs
Programming Guide
Contains development information to create Samsung Digital Health applications
Libs
samsung-digital-health-healthdata-v1.0.0.jar
Client library of Samsung Digital Health SDK
sdk-v1.0.0.jar
Basic library for the Samsung SDK
Samples
SimpleHealth
Sample application that demonstrates how to use Samsung Digital Health SDK
FoodNote
Sample application to check daily calorie intake
Tools
HealthDevApp.apk
An application to substitute S Health. It provides the Samsung Digital Health service on the
development phase.
DataImportSample-Weight.csv/txt
Example files to import health data with HealthDevApp
Page | 11
Programming Guide
Figure 6: HealthDevApp
It includes the following features.
-
Dashboard
HealthDevApp provides a test environment for user profile such as the name, gender, birthday, or
height.
Pedometer
It shows health data in the health data store with its detailed values by each data type.
User profile
HealthDevApp provides the Samsung Digital Health service for your application.
It provides a simple way to collect health data for steps. If you check it and walk with the device,
pedometer data is inserted to the health data store. Accumulated pedometer data can be checked in
Step Count on Dashboard.
Permission setting
Page | 12
Importing health data with csv or txt is provided for your convenience. Health data of the file can
be inserted to the health data store. Refer to Appendix A for more information.
Export Data
Permissions can be managed and checked for each application of permission related.
Import Data
Programming Guide
Health data in the health data store can be exported to the text or csv file. Refer to Appendix B for
more information. Refer to Appendix B for more information.
Password
It provides the test environment if user sets a password for health data. If the password is set, the
health data store is not connected until the password in entered.
Platform Type
If you use HealthDevApp in the debugging mode, you need to add the following metadata to the
AndroidManifest.xml file of your application project.
<meta-data
android:name="com.samsung.android.health.platform_type"
android:value="dev" />
Packaging Application
If your application is ready to publish, change the value of metadata information for the health platform type to
"rel" as shown below and package your application.
<meta-data
android:name="com.samsung.android.health.platform_type"
android:value="rel" />
If you dont change the value above, your application doesnt run with S Health.
Page | 13
Programming Guide
3.1.Importing Library
Add samsung-digital-health-healthdata-v1.0.0.jar and sdk-v1.0.0.jar to the libs folder in your created application
project.
Acquires the required permission to read or write users health data with HealthPermissionManager.
import com.samsung.android.sdk.healthdata.*;
Page | 14
Programming Guide
Figure 7 show an activity for resolve() if the connection to the health data store fails. If it is caused by
OLD_VERSION_PLATFORM, the activity needs to download the latest S Health. If it is caused by OLD_VERSION_SDK,
its required to download the latest version of your application.
Page | 15
Programming Guide
Page | 16
Programming Guide
Privacy
Its result is received through HealthResultHolder as a container for the corresponding result. The result of
HealthDataResolver.ReadResult and HealthDataResolver.AggregateResult are returned as the
Cursor interface. You can check the data value by moving the cursor.
The result of the health data request can be received either synchronously or asynchronously. You can choose one of
them for your application design.
If you want to get the result immediately for the health data request, use HealthResultHolder.await() as
shown below. It throws an exception if it is called in the main thread.
import com.samsung.android.sdk.healthdata.*;
// The state of connection
private HealthDataStore mStore;
private void readGlucoseSynchronously(long start, long end) {
Copyright Samsung Electronics, Co., Ltd. All rights reserved.
Page | 17
Programming Guide
Page | 18
Programming Guide
}
c.close();
}
else {
Log.d(APP_TAG, "There is no result.");
}
}
};
} catch (Exception e) {
Log.d(APP_TAG, "Reading health data fails.");
}
}
Data type
Health data including mandatory properties that are defined in the data type.
See 4.2 on details for health data properties of the health data type.
The Data Framework registers the current device where your application is installed. If the source device is the
current device, its ID can be checked as shown below.
import com.samsung.android.sdk.healthdata.*;
// The state of connection
private HealthDataStore mStore;
private void getCurrentDeviceInfo() {
HealthDeviceManager deviceManager = new HealthDeviceManager(mStore);
HealthDevice device = deviceManager.getLocalDevice();
String devicdId = device.getUuid();
}
Page | 19
Programming Guide
deviceManager.registerDevice(device);
} catch {
// Error handling
}
}
When you insert health data to the health data store, check units of data values are correct. Get more information
from 4.1.9.
The health data store accepts only validated health data. If any mandatory property is missing,
HealthDataResolver.insert() throws an exception. If property values dont satisfy the validation range, it succeeds but
inserted values are ignored.
You can check the number of data with BaseResult.getCount() in the result of HealthDataResolver.insert(). The size
limitation for blob type insertion is 1 megabyte.
Source device if a condition for source devices that provides health data is required
Package name if a condition for the package name that provides health data is required
4.1.5. Filter
HealthDataResolver.Filter is very useful to clear the data range for reading, updating, and aggregating health
data. Each filter contains one comparison below.
-
eq()
greaterThan()
greaterThanEquals()
in()
lessThan()
lessThanEquals()
not()
Multiple filters can be combined with and() and or() as Figure 8 and example below.
Page | 20
Programming Guide
If all three filters above need to be combined with and(), refer to the following example.
Filter badFilterEx = Filter.and(Filter.and(filter1, filter2), filter3); // Bad example for Filter
Filter goodFilterEx = Filter.and(filter1, filter2, filter3);
If you want to make a filter for the specific property, refer to the following example.
Filter badFilterEx = Filter.or(
Filter.eq("Property1", "AAA"),
Filter.eq("Property1", "BBB"),
Filter.eq("Property1", "CCC"));
Filter goodFilterEx = Filter.in("Property1", {"AAA", "BBB", "CCC"});
Data type
Health data that includes values for the specific properties to be updated
Page | 21
Programming Guide
Data type
If you want to specify the data range more, set a filter to DeleteRequest. Data IDs of the result can be used to
delete data.
4.1.8. Aggregation
The Data Framework provides useful aggregate functions to get statistical information. Available aggregate functions
are:
-
SUM
COUNT
AVG
MIN
MAX
You can add a group for the specific property of the data type with alias that make easy to figure the result value out.
Especially a time group with the specific time unit can be specified with
HealthDataResolver.Aggregate.TimeGroupUnit. Available time units and the value formation for each time
unit in the result are described in Table 4.
Unit
Minutely
yyyy-mm-dd hh:mm
(e.g. 2014-10-09 18:17)
Hourly
yyyy-mm-dd hh
(e.g. 2014-10-09 18)
Daily
yyyy-mm-dd
(e.g. 2014-10-09)
Weekly
yyyy-ww
(e.g. 2014-41)
Monthly
yyyy-mm
(e.g. 2014-10)
Unit
Item
Unit
Height
cm
Calorie
Kcal
Weight
Kg
Sp3ed
m/h
Page | 22
Programming Guide
Temperature
Celsius
Kg
Distance
Meter
Muscle mass
Kg
Blood glucose
mmol
Bone mass
Kg
HbA1c
Time
Millisecond
Blood Pressure
mmHg
Body water
Liter
Description
HealthConstants.Weight
HealthConstants.BloodGlucose
HealthConstants.HbA1c
HealthConstants.BloodPressure
Page | 23
Programming Guide
HealthConstants.BodyTemperature
HealthConstants.HeartRate
HealthConstants.Electrocardiogram
HealthConstants.OxygenSaturation
HealthConstants.StepCount
HealthConstants.Sleep
HealthConstants.AmbientTemperature
HealthConstants.UvExposure
HealthConstants.Exercise
Whole workout that user does for enhancing fitness and health
HealthConstants.WaterIntake
Records about how much and many times user takes water
HealthConstants.CaffeinIntake
HealthConstants.FoodInfo
HealthConstants.FoodIntake
Description
ID of health data.
UUID
CREATED_TIME
UPDATED_TIME
PACKAGE_NAME
DEVICE_UUID
Description
Base element for the data type. Its attributes are shown below.
-
"id"
Data type ID
"import"
Page | 24
Programming Guide
"version"
<publisher>
<documentation>
<title>
Indicates the version of the manifest. Its numeric. If there are manifests with different
version values, the higher version works.
Documentation section defines informational text. It has the following sub elements.
-
<title>
<description>
Title of the data type with the specific language code for localization. Its attribute is shown below.
-
The value of this element without the "lang" language attribute becomes the default title.
<description>
The value of this element without the "lang" language attribute becomes the default title.
<visibility>
<owner-app-list>
<package>
<policy>
"public"
If the visibility is not public, you can list the allowed applications to access or extend this data type.
It has a <package> sub element.
Package name of the allowed application.
Data policy. Its attributes are shown below.
-
"session" for measured data with the end time which has a session.
<medical-country>
"medical": Data encryption and listing allowed countries with <medical-country> are
required.
Need to write all allowed countries if the "privacy" attribute is "medical". It has the following
attribute and allowed country code values.
Page | 25
Programming Guide
"allowed"
<property>
Allowed or prohibited country codes with two-letter uppercase as defined by ISO 3166-1.
Defines detailed information for each property of this data type including the default value,
validation range, title and description. Its attributes are shown below.
-
"name"
"type"
"yes" if the property is a mandatory property for the data type. Be careful not to make the
property as "yes" if you add a new property to update your application.
If the property is defined as mandatory, the value for the property has to be specified when
new data is inserted.
"unique"
<default-value>
Default value of the property to be filled when a new health data is inserted without value
specification
<validation>
Validation range
-
"min"
"max"
<documentation>
Page | 26
Programming Guide
Line 10-16: data policy with its lifetime, measurement type, privacy level
Line 18: Name, mandatory option, data type, and unique option for the property
Page | 27
Programming Guide
4.3.Privacy
Privacy is a key for handling health data. Samsung Digital Health enables your application to access health data based
on users consent. An application needs to declare proper permissions for handling required health data types and to
handle SecureException when the application cannot gain user consent because user can withdraw consent at
any time. See 5.2 on details for permission declaration.
Declared permissions in manifest can be checked in the user permission menu of Settings of S Health or applications
as in Figure 9. The permission menu shows declared all the data types and user may change permission for each data
type at any time. When a permission API is called in an application, the Data Framework shows permissions related
to the requested permission API only. The flow can be preceded after user approves or denies the data type usage.
User consent is limited to the device. Even if multiple devices use the same Samsung account, the application has to
acquire user consent on each device independently.
Page | 28
Programming Guide
5. Use Cases
Useful examples to develop an application are as follows.
-
Connecting to HealthDataStore
Inserting data
Updating data
Deleting data
Reading data
Aggregating data
Observing change
5.1.Connecting to HealthDataStore
An application has to connect to HealthDataStore to handle health data. Other APIs work after the health data
store is connected successfully. Its sequence is shown below.
1) Implement the HealthDataStore.ConnectionListener interface.
2) Create a HealthDataStore instance.
3) Call connectService() to connect to health service.
4) After receiving the onConnected() callback, other APIs work properly.
: ConnectionListener
: Application
: HealthDataStore
<<implement>>
1
<<create>>
2
3 : connectService()
4 : onConnected()
Page | 29
Programming Guide
import com.samsung.android.sdk.healthdata.*;
public class MainActivity extends Activity {
private HealthDataStore mStore;
@Override
public void onCreate(Bundle savedInstanceState) {
HealthDataService healthDataService = new HealthDataService();
try {
healthDataService.initialize(this);
} catch (Exception e) {
// Handles exceptions
}
mStore = new HealthDataStore(this, mConnectionListener);
mStore.connectService();
}
@Override
public void onDestroy() {
mStore.disconnectService();
}
private final HealthDataStore.ConnectionListener mConnectionListener = new
HealthDataStore.ConnectionListener() {
@Override
public void onConnected() {
// The connection is successful.
}
@Override
public void onConnectionFailed(HealthConnectionErrorResult error) {
// The connection fails.
error.resolve(mInstance);
}
@Override
public void onDisconnected() {
// The connection is disconnected.
}
};
}
Page | 30
Programming Guide
5) The Data Framework makes the user to select the allowance for the requested permission. If the user consents,
the application can access data.
Page | 31
Programming Guide
To access health data, the application needs to get user permission. You need to call the permission request API, and
the application needs to specify data types on its manifest file. If the required data type is missing on its manifest file,
the user permission API fails.
Permissions to read and write are different entities. If the application needs to declare permission for multiple data
types, use semicolon (;). The following example shows manifest to declare permissions for reading and writing.
<meta-data
android:name="com.samsung.android.health.permission.read"
android:value="com.samsung.health.blood_pressure;com.samsung.health.heart_rate" />
<meta-data
android:name="com.samsung.android.health.permission.write"
android:value="com.samsung.health.heart_rate" />
5.3.Inserting data
An application can insert created data into the health data storage. The data request works either synchronously or
asynchronously. See 4.1.2 for additional information. Make sure not to make the synchronous request on the UI
thread. The sequence for the asynchronous request is shown below.
1) Implement the HealthResultHolder.ResultListener<BaseResult> interface.
2) Create a HealthDataResolver.InsertRequest instance.
3) Add a HealthData instances to InsertRequest.
4) Create a HealthDataResolver instance.
5) Call insert() to insert data.
6) The application can check the result asynchronously on the onResult() callback.
Page | 32
Programming Guide
: ResultListener <BaseResult>
: InsertRequest
: HealthDataResolver
: Application
<<implement>>
1
<<create>>
2
3 : addHealthData()
<<create>>
4
5 : insert()
6 : onResult()
Page | 33
Programming Guide
5.4.Updating data
An application can update data on the health data storage. The data request works either synchronously or
asynchronously. See 4.1.2 for additional information. Make sure not to make the synchronous request on the UI
thread. Only health data that is inserted by your application can be updated. The following example shows how to
update the food amount of existing health data. Its sequence for the asynchronous request is shown below.
1) Implement the HealthResultHolder.ResultListener<BaseResult> interface.
2) Create a HealthDataResolver.UpdateRequest instance and set a filter.
3) Create a HealthDataResolver instance.
4) Call update().
5) The application can check the result asynchronously on the onResult() callback.
: ResultListener <BaseResult>
: UpdateRequest
: HealthDataResolver
: Application
<<implement>>
1
<<new>>
2
<<create>>
3
4 : update()
5 : onResult()
Page | 34
Programming Guide
5.5.Deleting data
An application can delete data on the health data storage. The data request works either synchronously or
asynchronously. See 4.1.2 for additional information. Make sure not to make the synchronous request on the UI
thread. Only health data that is inserted by your application can be deleted. Its sequence for the asynchronous
request is shown below.
1) Implement the HealthResultHolder.ResultListener<BaseResult> interface.
2) Create a HealthDataResolver.DeleteRequest instance.
3) Set "datauuids" to be deleted.
4) Create a HealthDataResolver instance.
5) Call delete().
6) The application can check the result asynchronously on the onResult() callback.
Copyright Samsung Electronics, Co., Ltd. All rights reserved.
Page | 35
Programming Guide
: ResultListener <BaseResult>
: Application
: DeleteRequest
: HealthDataResolver
<<implement>>
1
<<new>>
2
3 : deleteHealthData()
<<new>>
4
5 : delete()
6 : onResult()
Page | 36
Programming Guide
};
5.6.Reading data
An application can read data on the health data storage. The data request works either synchronously or
asynchronously. See 4.1.2 for additional information. Make sure not to make the synchronous request on the UI
thread. The sequence for the asynchronous request is shown below.
1) Implement the HealthResultHolder.ResultListener<ReadResult> interface.
2) Create a HealthDataResolver.ReadRequest instance.
3) Create a HealthDataResolver instance.
4) Call read().
5) The application can check the result asynchronously on the onResult() callback. If the request is successful,
the application gets Cursor that contains the result.
: ResultListener <ReadResult>
: Application
: ReadRequest
: HealthDataResolver
<<implement>>
1
<<new>>
2
<<new>>
3
4 : read()
5 : onResult()
Page | 37
Programming Guide
5.7.Aggregating data
An application can aggregate health data with frequently used aggregate functions like average or sum. The data
request works either synchronously or asynchronously. See 4.1.2 for additional information. Make sure not to make
the synchronous request on the UI thread. The sequence for the asynchronous request is shown below.
1) Implement the HealthResultHolder.ResultListener<AggregateResult> interface.
2) Create a HealthDataResolver.AggregateRequest instance.
3) Create a HealthDataResolver instance.
4) Call aggregate().
5) The application can check the result asynchronously on the onResult() callback. If the request is successful,
the application gets Cursor that contains the result.
Page | 38
Programming Guide
: ResultListener <AggregateResult>
: Application
: AggregateRequest
: HealthDataResolver
<<implement>>
1
<<new>>
2
<<new>>
3
4 : aggregate()
5 : onResult()
Page | 39
Programming Guide
5.8.Observing change
An application can observe changes in the health data storage. If observed data type is changed, notification is
received in its callback. The sequence is shown below.
1) Implement the HealthDataObserver listener.
2) Call addObserver() to add an observer for the specific health data type.
3) If the observed data type is changed, the application receives notification in the onChange() callback.
: HealthDataObserver
: Application
: Platform
<<implement>>
1
2 : addObserver()
3 : onChange()
Page | 40
Programming Guide
6. Sample Applications
6.1.SimpleHealth
Samsung Digital Health SDK provides SimpleHealth as a sample application. SimpleHealth demonstrates how to use
the APIs for Samsung Digital Health to retrieve and show the count of steps in today including a process to get
permission to read HealthConstants.StepCount health data.
Prerequisites to run SimpleHealth are shown below.
-
Prepare a device that supports Android 4.4KitKat (API level 19) or above.
Description
It contains following operations.
MainActivity.java
Page | 41
Programming Guide
StepCountReporter.java
6.1.1. MainActivity
MainActivity is derived from Android Activity. It connects to the health data store and requests permission to read
the HealthConstants.StepCount data type from the data store. It also provides an option menu for the
permission setting to check the status for step count data.
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mInstance = this;
mKeySet = new HashSet<PermissionKey>();
mKeySet.add(new PermissionKey(HealthConstants.StepCount.HEALTH_DATA_TYPE, PermissionType.READ));
HealthDataService healthDataService = new HealthDataService();
try {
healthDataService.initialize(this);
} catch (Exception e) {
// Handles exceptions
}
// Create a HealthDataStore instance and set its listener
mStore = new HealthDataStore(this, mConnectionListener);
// Request the connection to the health data store
mStore.connectService();
}
@Override
public void onDestroy() {
mStore.disconnectService();
super.onDestroy();
}
Page | 42
Programming Guide
Page | 43
Programming Guide
alert.setPositiveButton("OK", null);
alert.show();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
menu.add(1, MENU_ITEM_PERMISSION_SETTING, 0, "Permission Setting");
return true;
}
@Override
public boolean onOptionsItemSelected(android.view.MenuItem item) {
if (item.getItemId() == (MENU_ITEM_PERMISSION_SETTING)) {
HealthPermissionManager pmsManager = new HealthPermissionManager(mStore);
try {
// Show user permission UI for allowing user to change options
pmsManager.requestPermissions(mKeySet).setResultListener(mPermissionListener);
} catch (Exception e) {
Log.e(APP_TAG, e.getClass().getName() + " - " + e.getMessage());
Log.e(APP_TAG, "Permission setting fails.");
}
}
return true;
}
6.1.2. StepCountReporter
StepCountReporter interacts with HealthDataResolver and HealthContentObserver objects to get today's
total step count and updates the step count change to MainActivity. HealthDataResolver is used to read the step
count data for today. HealthContentObserver is used to observe a change for steps.
Page | 44
Programming Guide
Filter.lessThanEquals(HealthConstants.StepCount.START_TIME,
endTime));
Page | 45
Programming Guide
6.2.FoodNote
Samsung Digital Health SDK provides FoodNote as a sample application. FoodNote demonstrates how to use the APIs
for Samsung Digital Health to check the selected days calorie intake including getting permission to read and write
health data for HealthConstants.FoodIntake and HealthConstants.FoodInfo.
Prerequisites to run FoodNote are shown below.
-
Prepare a device that supports Android 4.4 KitKat (API level 19) or above.
Page | 46
Programming Guide
MainActivity.java
ChooseFoodActivity.java
MealStoreActivity.java
FoodDataHelper.java
Description
-
Reads and shows food intake data of the selected day and
the meal type
Page | 47
Programming Guide
6.2.1. MainActivity
MainActivity is derived from Android Activity. It connects to the health data store and requests permission to read,
write the HealthConstants.FoodIntake data type from the data store. And it provides an option menu for the
permission setting to access food intake and food info data.
permissions to mPermissionKeySet
PermissionKey(FoodIntake.HEALTH_DATA_TYPE, PermissionType.READ));
PermissionKey(FoodIntake.HEALTH_DATA_TYPE, PermissionType.WRITE));
PermissionKey(FoodInfo.HEALTH_DATA_TYPE, PermissionType.READ));
PermissionKey(FoodInfo.HEALTH_DATA_TYPE, PermissionType.WRITE));
Page | 48
Programming Guide
}
}
public static MainActivity getInstance() {
return mInstance;
}
public FoodDataHelper getFoodDataHelper() {
return mDataHelper;
}
private final HealthDataStore.ConnectionListener mConnectionListener =
new HealthDataStore.ConnectionListener() {
@Override
public void onConnected() {
Log.d(TAG, "onConnected");
HealthPermissionManager pmsManager = new HealthPermissionManager(mStore);
Map<PermissionKey, Boolean> permissionMap =
pmsManager.isPermissionAcquired(mPermissionkeySet);
// Check the permissions acquired or not
if (permissionMap.containsValue(Boolean.FALSE)) {
requestPermissions();
}
// Show the intake calories of the given day
mDataHelper.readDailyIntakeCalories(MainActivity.this, mDayStartTime);
}
@Override
public void onConnectionFailed(HealthConnectionErrorResult error) {
Log.d(TAG, "onConnectionFailed");
// Set an activity to resolve the error
error.resolve(MainActivity.this);
}
@Override
public void onDisconnected() {
Log.d(TAG, "onDisconnected");
}
};
Page | 49
Programming Guide
// Show a permission alarm and initializes the calories if permissions are not acquired
if (resultMap.values().contains(Boolean.FALSE)) {
showPermissionAlarmDialog();
} else {
// Get the calories of Indexed time and display it
mDataHelper.readDailyIntakeCalories(MainActivity.this, mDayStartTime);
// Register an observer to listen changes of the calories
HealthDataObserver.addObserver(mStore, FoodIntake.HEALTH_DATA_TYPE, mObserver);
}
}
};
private void showPermissionAlarmDialog() {
if (isFinishing()) {
return;
}
AlertDialog.Builder alert = new AlertDialog.Builder(MainActivity.this);
alert.setTitle("Notice");
alert.setMessage("All permissions must be acquired");
alert.setPositiveButton("OK", null);
alert.show();
}
6.2.2. ChooseFoodActivity
ChooseFood interacts with the HealthDataResolver object in FoodDataHelper to insert the selected food
calories with the number of intake and apply the changed calories to MealStore.
The code below shows how to choose the food from FoodInfo class and Input the number of intake.
public class ChooseFoodActivity extends Activity {
// ...
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Get the intake day and meal type from Android Intent
Copyright Samsung Electronics, Co., Ltd. All rights reserved.
Page | 50
Programming Guide
mIntakeDay = getIntent().getExtras().getLong(AppConstants.BUNDLE_KEY_INTAKE_DAY);
mMealType = getIntent().getExtras().getInt(AppConstants.BUNDLE_KEY_MEAL_TYPE);
// ...
// Load the FoodList from FoodInfoTable class
List<String> foodNameArray = new ArrayList<String>();
foodNameArray.addAll(FoodInfoTable.keySet());
Collections.sort(foodNameArray);
// ...
// Show a Dialog to set intake times, after tap the food from food list
nameListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mSelectedFoodType = ((TextView) view).getText().toString();
AlertDialog.Builder intakeDialogBuiler = createDialogBuilder();
intakeDialogBuiler.show();
}
});
}
private AlertDialog.Builder createDialogBuilder() {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
// Set EditText of the dialog
final EditText input = new EditText(this);
dialogBuilder.setTitle(R.string.editTextTitle);
dialogBuilder.setMessage(mSelectedFoodType + " : "
+ FoodInfoTable.get(mSelectedFoodType).calorie + " kcals/time");
dialogBuilder.setView(input);
input.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
dialogBuilder.setPositiveButton(R.string.confirm, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// Take the String value (intake count) from EditText
String takeCount = input.getText().toString();
// Check for null or "0" value
if (!takeCount.isEmpty() && !("0".equals(takeCount))) {
FoodDataHelper dataHelper = MainActivity.getInstance().getFoodDataHelper();
dataHelper.insertFoodInfo(mSelectedFoodType, Float.valueOf(takeCount), mMealType,
mIntakeDay);
}
}
});
return dialogBuilder;
}
}
6.2.3. MealStoreActivity
MealStoreActivity interacts with the HealthDataResolver object in the FoodDataHelper class to get and delete the
calories and updates the calories.
The code below shows how to delete selected food from food intake data.
public class MealStoreActivity extends Activity implements FoodDataHelper.MealDetailsCallback {
// ...
Copyright Samsung Electronics, Co., Ltd. All rights reserved.
Page | 51
Programming Guide
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Get the intake day and meal type from Android Intent
mIntakeDay = getIntent().getExtras().getLong(AppConstants.BUNDLE_KEY_INTAKE_DAY);
mMealType = getIntent().getExtras().getInt(AppConstants.BUNDLE_KEY_MEAL_TYPE);
// ...
mDataHelper = MainActivity.getInstance().getFoodDataHelper();
// Get the cached food intake data
mDataHelper.readDailyIntakeDetails(MealStoreActivity.this, mIntakeDay, mMealType);
// ...
findViewById(R.id.delete).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.delete:
int id = mCachedFoodListView.getCheckedItemPosition();
if (id != ListView.INVALID_POSITION) {
// Get the food intake UUID from mFoodNameArray
String selectedUuid = mIntakeUuidArray.get(id);
// Delete the selected food by the foodintake UUID
mDataHelper.deleteFoodIntake(selectedUuid);
if (!mFoodNameArray.get(id).trim().contains("(Not Deletable)")) {
mFoodNameArray.remove(id);
}
mFoodNameArray.remove(id);
// Read the food intake data after deletion
mDataHelper.readDailyIntakeDetails(MealStoreActivity.this,
mIntakeDay, mMealType);
// Change the UI, after deletion
mCachedFoodListView.clearChoices();
mNameArrayAdapter.notifyDataSetChanged();
}
break;
}
}
});
}
}
6.2.4. FoodDataHelper
Inserting Food Intake Data
The code below shows how to insert food intake data.
public void insertFoodInfo(String foodName) {
HealthData data = new HealthData();
// Get the FoodInfoTable's key from the selected food name to use nutrition information
FoodInfoTable.FoodInfo foodInfo = FoodInfoTable.get(foodName);
// Fill out the mandatory properties to insert data
data.putString(FoodInfo.PROVIDER_FOOD_ID, foodInfo.providerFoodId);
data.putString(FoodInfo.INFO_PROVIDER, foodInfo.infoProvider);
data.putString(FoodInfo.NAME, foodInfo.name);
// ...
Copyright Samsung Electronics, Co., Ltd. All rights reserved.
Page | 52
Programming Guide
data.putFloat(FoodInfo.CALCIUM, foodInfo.calcium);
data.putFloat(FoodInfo.IRON, foodInfo.iron);
// Register the local device if it is not registered
data.setSourceDevice(new HealthDeviceManager(mStore).getLocalDevice().getUuid());
HealthDataResolver resolver = new HealthDataResolver(mStore, null);
InsertRequest request = new
InsertRequest.Builder().setDataType(FoodIntake.HEALTH_DATA_TYPE).build();
request.addHealthData(data);
mSavedUuid = data.getUuid();
resolver.insert(request);
}
Page | 53
Programming Guide
new HealthResultHolder.ResultListener<ReadResult>() {
@Override
public void onResult(ReadResult result) {
Cursor c = null;
try {
c = result.getResultCursor();
if (c == null) {
Log.e(MainActivity.TAG, "null cursor!");
return;
}
float
float
float
float
float
breakfast = 0.f;
lunch = 0.f;
dinner = 0.f;
snacks = 0.f;
total = 0.f;
Page | 54
Programming Guide
HealthDataResolver.Filter filter =
Filter.and(Filter.greaterThanEquals(FoodIntake.START_TIME, startTime),
Filter.lessThanEquals(FoodIntake.START_TIME, startTime + DAY_END_TIME),
Filter.eq(FoodIntake.MEAL_TYPE, mealType));
// Read the foodIntake data of specified day and meal type(startTime to end)
HealthDataResolver.ReadRequest request = new ReadRequest.Builder()
.setDataType(FoodIntake.HEALTH_DATA_TYPE)
.setProperties(new String[] { FoodIntake.UUID, FoodIntake.NAME, FoodIntake.CALORIE,
FoodIntake.AMOUNT, FoodIntake.PACKAGE_NAME })
.setFilter(filter)
.build();
try {
resolver.read(request).setResultListener(mIntakeDetailListener);
} catch (Exception e) {
Log.e(MainActivity.TAG, "read error!");
Log.e(MainActivity.TAG, e.getClass().getName() + " - " + e.getMessage());
}
}
private final HealthResultHolder.ResultListener<ReadResult> mIntakeDetailListener =
new HealthResultHolder.ResultListener<ReadResult>() {
@Override
public void onResult(ReadResult result) {
Cursor c = null;
float intakeTimes;
float intakeCalories;
String foodName;
float totalCalories = 0.f;
String packageName;
try {
c = result.getResultCursor();
if (c == null) {
Log.e(MainActivity.TAG, "null cursor!");
return;
}
ArrayList<String> savedUuidList = new ArrayList<String>();
List<String> foodNameList = new ArrayList<String>();
while (c.moveToNext()) {
savedUuidList.add(c.getString(c.getColumnIndex(FoodIntake.UUID)));
// Set the variables to get the food intake details
foodName = c.getString(c.getColumnIndex(FoodIntake.NAME));
intakeTimes = c.getFloat(c.getColumnIndex(FoodIntake.AMOUNT)));
intakeCalories = c.getFloat(c.getColumnIndex(FoodIntake.CALORIE)));
packageName = c.getString(c.getColumnIndex(FoodIntake.PACKAGE_NAME));
// Add the food intake information to List(for UI)
foodNameList.add(foodName + " : " + (intakeCalories / unitCalories) + " times"
+ " (" + intakeCalories + "kcals)");
// Calculate the total calories from food intake data
totalCalories += intakeCalories;
}
mMealDetailsCallback.onMealDetailsRetrieved(totalCalories, savedUuidList, foodNameList);
} finally {
if (c != null) {
c.close();
}
}
}
Copyright Samsung Electronics, Co., Ltd. All rights reserved.
Page | 55
Programming Guide
};
Page | 56
Programming Guide
File Extension
Only ".csv" and ".txt" file extension are acceptable.
Delimiter
Each property of a specific health data type is delimited with the following characters.
File type
Delimiter
csv
comma (",")
txt
tab ("\t")
If you edit txt, use double quotations for the comma in a string value. In case of csv, you dont need to add double
quotations for the comma in a string value.
Time Format
The following formats are allowed for time related data such as created_time, updated_time, start_time,
end_time, and time_offset.
-
YYYY-MM-DD HH:mm:ss.SSS
Page | 57
Programming Guide
Select data types to export data. If you dont select the file type separately, data is exported as csv. To select
the data type:
The exported data file is saved under the 'SHealth' folder of the device storage.
Note
If any data is not saved, the health data type is not exported. The health data type which contains a property with the
BLOB type is not exported. E.g. electrocardiography.
Page | 58
Programming Guide
Copyright
Copyright 2015 Samsung Electronics Co. Ltd. All Rights Reserved.
Though every care has been taken to ensure the accuracy of this document, Samsung Electronics Co., Ltd. cannot
accept responsibility for any errors or omissions or for any loss occurred to any person, whether legal or natural,
from acting, or refraining from action, as a result of the information contained herein. Information in this document
is subject to change at any time without obligation to notify any person of such changes.
Samsung Electronics Co. Ltd. may have patents or patent pending applications, trademarks copyrights or other
intellectual property rights covering subject matter in this document. The furnishing of this document does not give
the recipient or reader any license to these patents, trademarks copyrights or other intellectual property rights.
No part of this document may be communicated, distributed, reproduced or transmitted in any form or by any
means, electronic or mechanical or otherwise, for any purpose, without the prior written permission of Samsung
Electronics Co. Ltd.
The document is subject to revision without further notice.
All brand names and product names mentioned in this document are trademarks or registered trademarks of their
respective owners.
For more information, please visit http://developer.samsung.com/
Page | 59