Awareness Kit and Health Kit are most common services in health-related apps. Awareness Kit is used to detect user behavior activities and Health Kit is used to read the step count.
This codelab will use Awareness Kit and Health Kit to implement the use case below.
This codelab describes the integration of multiple kits like Awareness Kit and Health Kit. Moreover, Awareness Kit helps the app quickly obtain the user behavior activities and Health Kit helps the app read user's real-time data, such as step count.
This codelab will be helpful for the apps that are going to be developed under health, sports and medical domains. Awareness Kit is used to detect the user behavior activities and Health Kit is used to constantly synchronize the step count and other physical activity details. Also, this project will calculate user calories burned information automatically based on the data provided by Health Kit.
In this codelab, you will create a demo project, and use Awareness Kit and Health Kit to read the user step count in real time and calculate calories burned data.
App flow diagram
In this codelab, you will learn how to:
To integrate HMS Core kits, you need to complete the following preparations:
To obtain behavior change of a user, you will need to use the HMS Core Awareness SDK, and your app must initialize the SDK when starting up. Register the receiver class and call add barrier code in the onCreate() method of the class.
Java:
// receiver class initialization
private void registerReceiverClass() {
final String barrierReceiverAction = getActivity().getApplication().getPackageName() + "BEHAVIOR_BARRIER_RECEIVER_ACTION";
Intent intent = new Intent(barrierReceiverAction);
// You can also create PendingIntent with getActivity() or getService().
// This depends on what action you want Awareness Kit to trigger when the barrier status changes.
mPendingIntent = PendingIntent.getBroadcast(getActivity(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Register a broadcast receiver to receive the broadcast sent by Awareness Kit when the barrier status changes.
mBarrierReceiver = new BehaviorBarrierReceiver();
getActivity().registerReceiver(mBarrierReceiver, new IntentFilter(barrierReceiverAction));
AwarenessBarrier beginWalkingBarrier = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
beginWalkingBarrier = BehaviorBarrier.beginning(BehaviorBarrier.BEHAVIOR_WALKING);
}
AddBarrierForAwarness.addBarrier(getActivity(), getResources().getString(R.string.BEGINNING_BARRIER_LABEL), beginWalkingBarrier, mPendingIntent);
}
Kotlin:
// receiver class initialization
private fun registerReceiverClass() {
val barrierReceiverAction: String = (activity?.getApplication()?.getPackageName() ?: "") + resources.getString(R.string.BEHAVIOR_ACTION)
val intent = Intent(barrierReceiverAction)
// You can also create PendingIntent with getActivity() or getService().
// This depends on what action you want Awareness Kit to trigger when the barrier status changes.
mPendingIntent = PendingIntent.getBroadcast(activity, DefaultValues.DEFAULT_VALUE, intent, PendingIntent.FLAG_UPDATE_CURRENT)
// Register a broadcast receiver to receive the broadcast sent by Awareness Kit when the barrier status changes.
mBarrierReceiver = BehaviorBarrierReceiver()
activity?.registerReceiver(mBarrierReceiver, IntentFilter(barrierReceiverAction))
var beginWalkingBarrier: AwarenessBarrier? = null
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
beginWalkingBarrier = BehaviorBarrier.beginning(BehaviorBarrier.BEHAVIOR_WALKING)
}
// Add the beginning barrier to listen user behavior changes.
activity?.let { AddBarrierForAwarness.addBarrier(it, resources.getString(R.string.BEGINNING_BARRIER_LABEL), beginWalkingBarrier, mPendingIntent) }
}
Step 1 : Use the add barrier code to obtain the behavior status
Java:
/*
* Add the barrier and get the behavior changes
*
* @param Context application context
* @param string label used to identify barrier
* @param AwarenessBarrier barrier to check kind of request
*/
public static void addBarrier(Context context, final String label, AwarenessBarrier barrier, PendingIntent pendingIntent) {
BarrierUpdateRequest.Builder builder = new BarrierUpdateRequest.Builder();
// When the status of the registered barrier changes, pendingIntent is triggered.
// Label is used to uniquely identify the barrier. You can query a barrier by the label and delete it.
BarrierUpdateRequest request = builder.addBarrier(label, barrier, pendingIntent).build();
Awareness.getBarrierClient(context).updateBarriers(request)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
showToast(context, context.getString(R.string.add_barrier_success));
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
showToast(context, e.toString());
}
});
}
Kotlin:
/*
* Add the barrier and get the behavior changes
*
* @param Context application context
* @param string label used to identify barrier
* @param AwarenessBarrier barrier to check kind of request
*/
fun addBarrier(context: Context, label: String?, barrier: AwarenessBarrier?, pendingIntent: PendingIntent?) {
val builder = BarrierUpdateRequest.Builder()
// When the status of the registered barrier changes, pendingIntent is triggered.
// Label is used to uniquely identify the barrier. You can query a barrier by the label and delete it.
val request = builder.addBarrier(label!!, barrier!!, pendingIntent!!).build()
Awareness.getBarrierClient(context).updateBarriers(request)
.addOnSuccessListener { showToast(context, "add barrier success") }
.addOnFailureListener { e -
showToast(context, e.toString())}}
Step 2: Use the receiver class code to listen the event of behavior changes
Java:
// Broadcast receiver to listen the event
final class BehaviorBarrierReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
BarrierStatus barrierStatus = BarrierStatus.extract(intent);
String label = barrierStatus.getBarrierLabel();
int barrierPresentStatus = barrierStatus.getPresentStatus();
switch (label) {
case BEGINNING_BARRIER_LABEL :
if (barrierPresentStatus == BarrierStatus.TRUE) {
binding.tvStatus.setText(getResources().getText(R.string.user_status_start_walking));
binding.tvStatus.setText(getResources().getText(R.string.user_status_walking));
CommonUtil.logger(getResources().getString(R.string.startwalk),TAG);
// The user starts to walk.
callToStartStepCount();
}
break;
case ENDING_BARRIER_LABEL :
binding.tvStatus.setText(getActivity().getText(R.string.user_status_stop_walking));
CommonUtil.logger(getResources().getString(R.string.stopwalking),TAG);
// The user stops walking.
callToStopStepCount();
break;
default:
binding.tvStatus.setText(getActivity().getText(R.string.user_status));
break;
}
}
}
Kotlin:
// Broadcast receiver to listen the event
inner class BehaviorBarrierReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val barrierStatus = BarrierStatus.extract(intent)
val label = barrierStatus.barrierLabel
val barrierPresentStatus = barrierStatus.presentStatus
when (label) {
BEGINNING_BARRIER_LABEL -> if (barrierPresentStatus == BarrierStatus.TRUE) {
// The user starts to walk so call the method to start to read step count.
callToStartStepCount()
}
ENDING_BARRIER_LABEL -> if (barrierPresentStatus == BarrierStatus.TRUE) {
// The user stops walking so call the method to stop reading step count.
callToStopStepCount()
}
}
}
}
Step 1: AGC Console
Step 2: Initialize Health Kit in onCreate of the Activity
Java:
// Initialize and create an instance of Health Kit in oncreate of activity.
HiHealthOptions options = HiHealthOptions.builder().build();
AuthHuaweiId signInHuaweiId = HuaweiIdAuthManager.getExtendedAuthResult(options);
autoRecorderController = HuaweiHiHealth.getAutoRecorderController(getActivity(), signInHuaweiId);
Kotlin:
// Initialize and create an instance of Health Kit in oncreate of activity.
val options = HiHealthOptions.builder().build()
val signInHuaweiId = HuaweiIdAuthManager.getExtendedAuthResult(options)
mSettingController = activity?.let {
HuaweiHiHealth.getSettingController(it, signInHuaweiId) }
controller = activity?.let { HuaweiHiHealth.getAutoRecorderController(it, signInHuaweiId) }
Step 3: Authorization of Health Kit
Follow the following three steps to complete the Health app authorization.
Java:
/*
* signIn For the HealthKit
*/
private fun signInForHealthKit() {
// Add the scope based on the requirement.
List<Scope> scopeList = new ArrayList<>();
scopeList.add(new Scope(Scopes.HEALTHKIT_STEP_BOTH));
// View and save step counts in HUAWEI Health Kit.
scopeList.add(new Scope(Scopes.HEALTHKIT_HEIGHTWEIGHT_BOTH)); // View and save height and weight in HUAWEI Health Kit.
scopeList.add(new Scope(Scopes.HEALTHKIT_HEARTRATE_BOTH));
// View and save the heart rate data in HUAWEI Health Kit.
// Configure authorization parameters.
HuaweiIdAuthParamsHelper authParamsHelper = new HuaweiIdAuthParamsHelper(
HuaweiIdAuthParams.DEFAULT_AUTH_REQUEST_PARAM);
HuaweiIdAuthParams authParams = authParamsHelper.setIdToken()
.setAccessToken()
.setScopeList(scopeList)
.createParams();
// Initialize the HuaweiIdAuthService object.
final HuaweiIdAuthService authService = HuaweiIdAuthManager.getService(getActivity(),
authParams);
// Silent sign-in. If authorization has been granted by the current account, the authorization screen will not display. This is an asynchronous method.
Task<AuthHuaweiId> authHuaweiIdTask = authService.silentSignIn();
// Add the callback for the call result.
authHuaweiIdTask.addOnSuccessListener(new OnSuccessListener<AuthHuaweiId>() {
@Override
public void onSuccess(AuthHuaweiId huaweiId) {
// Silent sign-in succeeded.
Toast.makeText(getActivity(), getActivity().getString(R.string.silentSignIn_success), Toast.LENGTH_LONG).show();
checkOrAuthorizeHealth();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception exception) {
// Silent sign-in failed. This indicates that the authorization has not been granted by the current account.
Intent signInIntent = authService.getSignInIntent();
startActivityForResult(signInIntent, com.huawei.myhealth.java.utils.DefaultValues.REQUEST_SIGN_IN_LOGIN);
}
});
Kotlin:
/*
* signIn For the HealthKit
*/
private fun signInForHealthKit() {
// Add the scope based on the requirement.
val scopeList: List<Scope> = java.util.ArrayList()
scopeList.toMutableList().add(Scope(Scopes.HEALTHKIT_STEP_BOTH))
val authParamsHelper = HuaweiIdAuthParamsHelper(HuaweiIdAuthParams.DEFAULT_AUTH_REQUEST_PARAM)
val authParams = authParamsHelper.setIdToken().setAccessToken().setScopeList(scopeList).createParams()
val authService = HuaweiIdAuthManager.getService(activity, authParams)
val authHuaweiIdTask = authService.silentSignIn()
authHuaweiIdTask.addOnSuccessListener { huaweiId: AuthHuaweiId? ->
// Check with Huawei Health app Auth.
checkOrAuthorizeHealth()
}.addOnFailureListener { exception ->
if (exception is ApiException) {
val apiException = exception as ApiException
val signInIntent = authService.signInIntent
startActivityForResult(signInIntent, REQUEST_SIGN_IN_LOGIN)}}}
Java:
/*
* check for the checkOrAuthorizeHealth
*/
private void checkOrAuthorizeHealth()
{
// Check the Health authorization status. If the authorization has not been granted, display the authorization screen in the HUAWEI Health app.
Task<Boolean> authTask = mSettingController.getHealthAppAuthorisation();
authTask.addOnSuccessListener(new OnSuccessListener<Boolean>() {
@Override
public void onSuccess(Boolean result) {
if (Boolean.TRUE.equals(result)) {
initAwarness();
} else {
// If the authorization has not been granted, display the authorization screen in the HUAWEI Health app.
Uri healthKitSchemaUri = Uri.parse(getActivity().getString(R.string.HEALTH_APP_SETTING_DATA_SHARE_HEALTHKIT_ACTIVITY_SCHEME));
Intent intent = new Intent(Intent.ACTION_VIEW, healthKitSchemaUri);
// Check whether the authorization screen of the Health app can be displayed.
if (intent.resolveActivity(getActivity().getPackageManager()) != null) {
// Display the authorization screen by using the startActivityForResult() method of the activity.
// You can change HihealthKitMainActivity to the actual activity.
startActivityForResult(intent, REQUEST_HEALTH_AUTH);
}
}
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception exception) {
if (exception != null) {
CommonUtil.logger(exception.getMessage().toString(), TAG);
}
}
});
}
Kotlin:
/*
* check for the checkOrAuthorizeHealth
*/
private fun checkOrAuthorizeHealth() {
// Check the Health authorization status. If the authorization has not been granted, display the authorization screen in the HUAWEI Health app.
val authTask: Task<Boolean> = mSettingController!!.healthAppAuthorisation
authTask.addOnSuccessListener(object : OnSuccessListener<Boolean?> {
override fun onSuccess(result: Boolean?) {
if (java.lang.Boolean.TRUE == result) {
// The result of checkOrAuthorizeHealth is success. Initialize Awareness Kit.
initAwarness()
} else {
// If the authorization has not been granted, display the authorization screen in the HUAWEI Health app.
val healthKitSchemaUri: Uri = Uri.parse(activity?.getString(R.string.HEALTH_APP_SETTING_DATA_SHARE_HEALTHKIT_ACTIVITY_SCHEME))
val intent = Intent(Intent.ACTION_VIEW, healthKitSchemaUri)
// Check whether the authorization screen of the Health app can be displayed.
if (activity?.packageManager?.let { intent.resolveActivity(it) } != null) {
// Display the authorization screen by using the startActivityForResult() method of the activity.
// You can change HihealthKitMainActivity to the actual activity.
startActivityForResult(intent, DefaultValues.REQUEST_HEALTH_AUTH)
}
}
}
}).addOnFailureListener(object : OnFailureListener {
override fun onFailure(exception: Exception?) {
if (exception != null) {
CommonUtil.logger(exception.message.toString(), TAG)
}
}
})}
Java:
/*
* Check the result codes as requested
*
* @param requestCode returns the resultcode of status
* @param data Holds the result data
*/
override fun onActivityResult(requestCode: Int, resultCode: Int, @Nullable data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
// Handle the sign-in response.
handleSignInResult(requestCode, data)
// Process the response returned from the Health authorization screen.
handleHealthAuthResult(requestCode);
}
// Handle the Health Auth result here.
private fun handleHealthAuthResult(requestCode: Int) {
if (requestCode != REQUEST_HEALTH_AUTH) {
return
}
// This will return the queryHealthAuthorization result.
queryHealthAuthorization()
}
// Handle the sign-in result.
private fun handleSignInResult(requestCode: Int, data: Intent?) {
// Handle only the authorized responses.
if (requestCode != REQUEST_SIGN_IN_LOGIN) {
return
}
// Obtain the authorization response from the intent.
val result: HuaweiIdAuthResult = HuaweiIdAuthAPIManager.HuaweiIdAuthAPIService.parseHuaweiIdFromIntent(data)
if (result.isSuccess()) {
// Obtain the authorization result.
val authResult: HuaweiIdAuthResult = HuaweiIdAuthAPIManager.HuaweiIdAuthAPIService.parseHuaweiIdFromIntent(data)
// Sign-in succeeded, so now check for health authorization.
checkOrAuthorizeHealth()
}
}
// Handle Healthquery result.
private fun queryHealthAuthorization() {
val queryTask = mSettingController!!.healthAppAuthorisation
queryTask.addOnSuccessListener { result ->
if (java.lang.Boolean.TRUE == result) {
// Health result is success. Now initialize Awareness Kit.
initAwarness()
}
}.addOnFailureListener { exception ->
if (exception != null) {
CommonUtil.logger(exception.message.toString(),TAG) }}}
Kotlin:
/*
* Check the result codes as requested
*
* @param requestCode returns the resultcode of status
* @param data Holds the result data
*/
override fun onActivityResult(requestCode: Int, resultCode: Int, @Nullable data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
// Handle the sign-in response.
handleSignInResult(requestCode, data)
// Process the response returned from the Health authorization screen.
handleHealthAuthResult(requestCode);
}
// Handle the Health Auth result here.
private fun handleHealthAuthResult(requestCode: Int) {
if (requestCode != REQUEST_HEALTH_AUTH) {
return
}
// This will return the queryHealthAuthorization result.
queryHealthAuthorization()
}
// Handle the sign-in result.
private fun handleSignInResult(requestCode: Int, data: Intent?) {
// Handle only the authorized responses.
if (requestCode != REQUEST_SIGN_IN_LOGIN) {
return
}
// Obtain the authorization response from the intent.
val result: HuaweiIdAuthResult = HuaweiIdAuthAPIManager.HuaweiIdAuthAPIService.parseHuaweiIdFromIntent(data)
if (result.isSuccess()) {
// Obtain the authorization result.
val authResult: HuaweiIdAuthResult = HuaweiIdAuthAPIManager.HuaweiIdAuthAPIService.parseHuaweiIdFromIntent(data)
// Sign-in succeeded, so now check for health authorization.
checkOrAuthorizeHealth()
}
}
// Handle Healthquery result.
private fun queryHealthAuthorization() {
val queryTask = mSettingController!!.healthAppAuthorisation
queryTask.addOnSuccessListener { result ->
if (java.lang.Boolean.TRUE == result) {
// Health result is success. Now initialize Awareness Kit.
initAwarness()
}
}.addOnFailureListener { exception ->
if (exception != null) {
CommonUtil.logger(exception.message.toString(),TAG) }}}
Step 4: Start/Stop reading step count
Java:
// Create the data callback object onSamplePointListener to print the step count data.
private OnSamplePointListener onSamplePointListener = new OnSamplePointListener() {
@Override
public void onSamplePoint(SamplePoint samplePoint) {
// Step count will be returned in this listener.
stepCount = samplePoint.getFieldValue(Field.FIELD_STEPS).toString();
// Update the step count.
callToUpdateStepCount(stepCount);
}
};
// Called from the receiver class of Awareness Kit when the user starts to walk (mentioned in Step 2 of Awareness Kit).
private void callToStartStepCount()
{
if (autoRecorderController == null) {
initAutoRecorderController();
}
// Start recording real-time steps.
autoRecorderController.startRecord(DataType.DT_CONTINUOUS_STEPS_TOTAL, new OnSamplePointListener() {
@Override
public void onSamplePoint(SamplePoint samplePoint) {
// The step count, time, and type data reported by the pedometer is called back to the app through
// samplePoint.
stepCount = samplePoint.getFieldValue(Field.FIELD_STEPS).toString();
// Update the step count.
callToUpdateStepCount(stepCount);
}
}).addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
// Successfully started reading the step count.
CommonUtil.logger(getResources().getString(R.string.start_stepcount_success),TAG);
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
// Failed to start reading the step count.
CommonUtil.logger(getResources().getString(R.string.start_stepcount_failed),TAG);
}
});
}
// Called from the receiver class of Awareness Kit when the user stop walking (mentioned in Step 2 of Awareness Kit).
private void callToStopStepCount()
{
// Start recording real-time steps.
autoRecorderController.startRecord(DataType.DT_CONTINUOUS_STEPS_TOTAL, new OnSamplePointListener() {
@Override
public void onSamplePoint(SamplePoint samplePoint) {
// The step count, time, and type data reported by the pedometer is called back to the app through
// samplePoint.
stepCount = samplePoint.getFieldValue(Field.FIELD_STEPS).toString();
// Update the step count.
callToUpdateStepCount(stepCount);
}
}).addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
// Successfully stopped reading the step count.
CommonUtil.logger(getResources().getString(R.string.stop_stepcount_success),TAG);
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
// Failed to stop reading the step count.
CommonUtil.logger(getResources().getString(R.string.stop_stepcount_failed),TAG);
}
});
// Update the step count in db.
callToUpdateStepCount(stepCount);
}
Kotlin:
// Create the data callback object onSamplePointListener to print the step count data.
private val onSamplePointListener = OnSamplePointListener { samplePoint ->
for (field in samplePoint.dataType.fields) {
stepCount = samplePoint.getFieldValue(Field.FIELD_STEPS).toString()
// Update the step count to the UI.
callToUpdateStepCount(stepCount)}
}
}
// Called from the receiver class of Awareness Kit when the user starts to walk (mentioned in Step 2 of Awareness Kit).
private fun callToStartStepCount() {
val dataType = DataType.DT_CONTINUOUS_STEPS_TOTAL
controller?.startRecord(dataType, onSamplePointListener)?.addOnCompleteListener(OnCompleteListener { taskResult ->
// Handling of callback exceptions needs to be added for the case that the calling fails due to the app not being authorized or type not being supported.
if (taskResult.isSuccessful) {
// Successfully started reading the step count.
CommonUtil.logger(resources.getString(R.string.start_stepcount_success),TAG) } else {
// Failed to start reading the step count.
CommonUtil.logger(resources.getString(R.string.start_stepcount_failed),TAG)
}
})
}
// Called from the receiver class of Awareness Kit when the user stop walking (mentioned in Step 2 of Awareness Kit).
private fun callToStopStepCount() {
controller?.stopRecord(DataType.DT_CONTINUOUS_STEPS_TOTAL, onSamplePointListener)
?.addOnCompleteListener(OnCompleteListener<Void?> { taskResult ->
// Handling of callback exceptions needs to be added for the case that the calling fails due to the app not being authorized or type not being supported.
if (taskResult.isSuccessful) {
// Successfully stopped reading the step count.
CommonUtil.logger(resources.getString(R.string.stop_stepcount_success),TAG) } else {
// Failed to stop reading the step count.
CommonUtil.logger(resources.getString(R.string.stop_stepcount_failed),TAG) }
})
// Update the step count to the UI.
callToUpdateStepCount(stepCount)}
Well done. You have successfully built a My Health app and learned how to:
You can also click the button below to download the source code.
Download Source Code