“女朋友说想减肥了,该怎么答复她?”

有的男同胞饶有信念,认为这是一道送分题——当然是毫不迟疑地通知女友:”不必减,你一点也不胖,认真推敲还有点瘦……”

No!还是太年老,你们可能在一段感情的炙热里,但一看就不懂生存。答案早就更新n个版本了!我厂阿强近期也被提了此问,他给出了一个有技术含量的暖心答案——女友关怀体态和体重器上的数量,阿强更关怀她的身体健康。于是阿强施展本人看家本事,写了个卡路里计数器,把对关心女友准确到数字,用数字通知她日常应该放弃怎么的衰弱饮食和运动量,同时陪她一起践行衰弱生存。

阿强把整个开发过程分享进去,供宽广男同胞学习和借鉴。以下便是如何通过Android Studio的Kotlin开发一个简略的卡路里计数器利用的全过程。

实现原理:

华为静止衰弱服务容许用户存储智能手机或其余设施收集的静止衰弱数据,如智能手表、智能手环和计步器上的数据。这些数据能够在生态系统中平安共享。

次要性能

· 数据存储:轻松存储你的静止与衰弱数据。

· 数据凋谢:除了提供许多静止和保健数据接口外,它还反对共享各种静止与衰弱数据,包含步数、体重和心率。

· 数据拜访受权治理:用户能够治理开发人员对其静止与衰弱数据的拜访,保障本身的数据隐衷和合法权利。

· 设施拜访:能够通过蓝牙测量硬件设施的数据,并容许咱们上传这些数据。

利用性能

这个卡路里计数器利用蕴含两个界面。通过华为Account Kit的首页,点击“登录华为账号”按钮登录利用。登陆后进入下一个界面,在这个页面上,可增加“卡路里”和“体重”信息。信息以图形的形式显示,借助了MPAndroidChart的收费库。示例代码已在相干社区进行开源,欢送开发者关注、下载并提供宝贵意见:
Github官网地址:https://github.com/HMS-Core/h...

Gitee官网地址:https://gitee.com/hms-core/hm...

  1. 集成HUAWEI HMS Core

首先,咱们须要在Console上创立一个帐户,而后创立一个我的项目,并将其集成到利用中。能够依照此链接中概述的步骤疾速实现此操作,也能够借助官网codelab来实现操作。

  1. 集成华为静止衰弱服务

申请获取静止衰弱服务(Health Kit)。通过此链接登录Console后,单击下图中显示的“Health Kit”。

而后,单击“申请Health Kit”即可实现申请。

接下来须要申请利用应用数据的许可,包含“体重”和“卡路里”数据。只申请必要的数据权限,即“拜访和增加身高和体重数据”和“拜访和增加卡路里(包含基础代谢率BMR)数据”

而后单击“提交”按钮,实现所有流程。

须要留神的是,你会看到下图中的某些选项被锁定,因为它们是敏感数据。如果你想在利用中应用敏感数据,还须要发送电子邮件至hihealth@huawei.com邮箱,题目命名为“申请Health Kit凋谢权限”。对方会尽快回复。你能够从点击此链接取得更多详细信息。

在Console取得必要的权限后,关上Android Studio持续开发利用。

点击“build.gradle (工程级)”,而后将所需的依赖增加到我的项目级的“build.gradle”文件中。

留神:咱们为图形库增加了jitpack链接。

maven {url ‘https://developer.huawei.com/repo/'}maven { url ‘https://jitpack.io' }

点击关上“build.gradle(利用级)”文件。以下依赖关系对于运行Health Kit来说就足够了,但咱们还将增加Account Kit和图形库的依赖关系。

 implementation 'com.huawei.agconnect:agconnect-core:1.4.2.301'    implementation 'com.huawei.hms:hwid:5.1.0.301'    implementation 'com.huawei.hms:health:5.1.0.301'implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'

最初,关上“AndroidManifest.xml”文件,将App ID作为元数据信息增加到“Application”标签中。能够通过以下两种办法获取咱们的利用ID:1. 进入Console,单击开发局部的“华为ID”,而后抉择我的项目,查看利用ID。2. 在“agconnect-services.json”文件中找到利用ID。

 <meta-data            android:name="com.huawei.hms.client.appid"            android:value="您的利用 Id"/>
  1. 开发利用

Health Kit为咱们提供了3个API:

· DataController:增加、更新、删除和读取静止与衰弱数据。

· ActivityRecordsController:将流动记录写入平台并更新记录。

· AutoRecordController:读取实时静止与衰弱数据。

咱们应用DataController在利用中解决卡路里和体重数据。Health Kit提供了安全可靠的数据服务,所以咱们会申请用户容许应用他们的衰弱数据。

“activity_main.xml”文件蕴含logo、利用名、输出按钮等信息。

<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context=".MainActivity">
 <TextView        android:id="@+id/tvAppName"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginTop="8dp"        android:text="@string/app_name"        android:textColor="@color/colorPrimary"        android:textSize="24sp"        android:textStyle="bold"        app:layout_constraintLeft_toLeftOf="parent"        app:layout_constraintRight_toRightOf="parent"        app:layout_constraintTop_toBottomOf="@+id/ivLogo" />
<com.huawei.hms.support.hwid.ui.HuaweiIdAuthButton        android:id="@+id/btnLogin"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        app:layout_constraintBottom_toBottomOf="parent"        app:layout_constraintEnd_toEndOf="parent"        app:layout_constraintStart_toStartOf="parent"        app:layout_constraintTop_toTopOf="parent"        app:layout_constraintVertical_bias="0.7" />
<ImageView        android:id="@+id/ivLogo"        android:layout_width="172dp"        android:layout_height="113dp"        app:layout_constraintBottom_toBottomOf="parent"        app:layout_constraintEnd_toEndOf="parent"        app:layout_constraintHorizontal_bias="0.497"        app:layout_constraintStart_toStartOf="parent"        app:layout_constraintTop_toTopOf="parent"        app:layout_constraintVertical_bias="0.3"        app:srcCompat="@drawable/ic_logo" />        </androidx.constraintlayout.widget.ConstraintLayout>

MainActivity.kt蕴含登录过程所需的代码。

package com.huawei.healthtracker import android.content.Intentimport android.os.Bundleimport android.util.Logimport androidx.appcompat.app.AppCompatActivityimport com.huawei.hms.common.ApiExceptionimport com.huawei.hms.hihealth.data.Scopesimport com.huawei.hms.support.api.entity.auth.Scopeimport com.huawei.hms.support.hwid.HuaweiIdAuthManagerimport com.huawei.hms.support.hwid.request.HuaweiIdAuthParamsimport com.huawei.hms.support.hwid.request.HuaweiIdAuthParamsHelperimport com.huawei.hms.support.hwid.service.HuaweiIdAuthServiceimport com.huawei.hms.support.hwid.ui.HuaweiIdAuthButton class MainActivity : AppCompatActivity() {     private val TAG = "MainActivity"     private lateinit var btnLogin: HuaweiIdAuthButton    private lateinit var mAuthParam: HuaweiIdAuthParams    private lateinit var mAuthService: HuaweiIdAuthService     private val REQUEST_SIGN_IN_LOGIN = 1001      override fun onCreate(savedInstanceState: Bundle?) {         super.onCreate(savedInstanceState)        setContentView(R.layout.activity_main)         btnLogin = findViewById(R.id.btnLogin)         btnLogin.setOnClickListener {            signIn()        }     }     private fun signIn() {         val scopeList = listOf(            Scope(Scopes.HEALTHKIT_CALORIES_BOTH),            Scope(Scopes.HEALTHKIT_HEIGHTWEIGHT_BOTH),        )         mAuthParam =            HuaweiIdAuthParamsHelper(HuaweiIdAuthParams.DEFAULT_AUTH_REQUEST_PARAM).apply {                setIdToken()                    .setAccessToken()                    .setScopeList(scopeList)            }.createParams()         mAuthService = HuaweiIdAuthManager.getService(this, mAuthParam)         val authHuaweiIdTask = mAuthService.silentSignIn()         authHuaweiIdTask.addOnSuccessListener {            val intent = Intent(this, CalorieTrackerActivity::class.java)            startActivity(intent)        }            .addOnFailureListener {                startActivityForResult(mAuthService.signInIntent, REQUEST_SIGN_IN_LOGIN)            }    }     override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {        super.onActivityResult(requestCode, resultCode, data)         when (requestCode) {            REQUEST_SIGN_IN_LOGIN -> {                 val authHuaweiIdTask = HuaweiIdAuthManager.parseAuthResultFromIntent(data)                if (authHuaweiIdTask.isSuccessful) {                     val intent = Intent(this, CalorieTrackerActivity::class.java)                    startActivity(intent)                 } else {                    Log.i(                        TAG,                        "signIn failed: ${(authHuaweiIdTask.exception as ApiException).statusCode}"                    )                }            }        }    } }

确保你已将数据的权限设置为“范畴”。单击登录按钮时,用户将看到受权页面。并且,受权页面在“范畴”字段中显示权限。默认状况下不标记这些权限,因而用户应标记它们。


在“CalorieTrackerActivity”页面上,能够增加和查看卡路里和体重信息。

“activity_calorie_tracker.xml”蕴含卡路里计数器页面的设计代码。

<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context=".CalorieTrackerActivity">
<Button        android:id="@+id/btnShowConsCal"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginTop="32dp"        android:text="Show Cons. Cal."        android:textAllCaps="false"        app:layout_constraintEnd_toStartOf="@+id/guideline"        app:layout_constraintHorizontal_bias="0.5"        app:layout_constraintStart_toStartOf="parent"        app:layout_constraintTop_toBottomOf="@+id/btnAddConsumedCal" />
 <Button        android:id="@+id/btnShowWeight"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginTop="32dp"        android:text="Show Weight"        android:textAllCaps="false"        app:layout_constraintEnd_toEndOf="parent"        app:layout_constraintHorizontal_bias="0.5"        app:layout_constraintStart_toStartOf="@+id/guideline"        app:layout_constraintTop_toBottomOf="@+id/btnAddWeight" />
<Button        android:id="@+id/btnAddConsumedCal"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginTop="16dp"        android:text="Add"        android:textAllCaps="false"        app:layout_constraintEnd_toStartOf="@+id/guideline"        app:layout_constraintHorizontal_bias="0.5"        app:layout_constraintStart_toStartOf="parent"        app:layout_constraintTop_toBottomOf="@+id/etConsumedCal" />
  <Button        android:id="@+id/btnAddWeight"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginTop="16dp"        android:text="Add"        android:textAllCaps="false"        app:layout_constraintEnd_toEndOf="parent"        app:layout_constraintHorizontal_bias="0.5"        app:layout_constraintStart_toStartOf="@+id/guideline"        app:layout_constraintTop_toBottomOf="@+id/etBurntCal" />
<TextView        android:id="@+id/textView"        android:layout_width="0dp"        android:layout_height="wrap_content"        android:layout_marginStart="16dp"        android:layout_marginTop="16dp"        android:text="Consumed Calorie"        android:textColor="@color/black"        android:textSize="18sp"        android:textStyle="bold"        app:layout_constraintEnd_toStartOf="@+id/guideline"        app:layout_constraintStart_toStartOf="parent"        app:layout_constraintTop_toTopOf="parent" />
<TextView        android:id="@+id/textView2"        android:layout_width="0dp"        android:layout_height="wrap_content"        android:layout_marginStart="16dp"        android:layout_marginTop="16dp"        android:text="Weight"        android:textColor="@color/black"        android:textSize="18sp"        android:textStyle="bold"        app:layout_constraintEnd_toEndOf="parent"        app:layout_constraintStart_toStartOf="@+id/guideline"        app:layout_constraintTop_toTopOf="parent" />
  <EditText        android:id="@+id/etConsumedCal"        android:layout_width="0dp"        android:layout_height="wrap_content"        android:layout_marginStart="16dp"        android:layout_marginTop="8dp"        android:layout_marginEnd="32dp"        android:ems="10"        android:hint="Kcal"        android:inputType="number"        android:maxLength="4"        app:layout_constraintEnd_toStartOf="@+id/guideline"        app:layout_constraintStart_toStartOf="parent"        app:layout_constraintTop_toBottomOf="@+id/textView" />
  <EditText        android:id="@+id/etBurntCal"        android:layout_width="0dp"        android:layout_height="wrap_content"        android:layout_marginStart="16dp"        android:layout_marginTop="8dp"        android:layout_marginEnd="32dp"        android:ems="10"        android:hint="Kg"        android:inputType="number"        android:maxLength="3"        app:layout_constraintEnd_toEndOf="parent"        app:layout_constraintStart_toStartOf="@+id/guideline"        app:layout_constraintTop_toBottomOf="@+id/textView2" />
  <androidx.constraintlayout.widget.Guideline        android:id="@+id/guideline"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:orientation="vertical"        app:layout_constraintGuide_percent="0.5"        app:layout_constraintTop_toTopOf="parent" />
<View        android:id="@+id/view_vertical"        android:layout_width="1dp"        android:layout_height="0dp"        android:layout_marginTop="16dp"        android:layout_marginBottom="16dp"        android:background="@android:color/darker_gray"        app:layout_constraintBottom_toBottomOf="@+id/btnAddConsumedCal"        app:layout_constraintEnd_toEndOf="parent"        app:layout_constraintStart_toStartOf="parent"        app:layout_constraintTop_toTopOf="parent" />
<androidx.cardview.widget.CardView        android:layout_width="0dp"        android:layout_height="0dp"        android:layout_marginStart="16dp"        android:layout_marginTop="16dp"        android:layout_marginEnd="16dp"        android:layout_marginBottom="32dp"        android:background="@color/colorCardBackground"        app:cardCornerRadius="4dp"        app:layout_constraintBottom_toBottomOf="parent"        app:layout_constraintEnd_toEndOf="parent"        app:layout_constraintStart_toStartOf="parent"        app:layout_constraintTop_toBottomOf="@+id/btnShowWeight">
<LinearLayout            android:layout_width="match_parent"            android:layout_height="match_parent"            android:orientation="vertical">
 <TextView                android:id="@+id/tvChartHead"                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:layout_marginTop="16dp"                android:gravity="center_horizontal"                android:text="Weekly Consumed Calories"                android:textColor="@color/black"                android:textSize="18sp"                android:textStyle="bold" />
<com.github.mikephil.charting.charts.BarChart                android:id="@+id/barchartWeeklyCal"                android:layout_width="match_parent"                android:layout_height="match_parent"                android:layout_margin="16dp"                android:background="@android:color/white" />        </LinearLayout>    </androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>

刚刚咱们介绍了Data Controllers,当初就来创立一个Data Controller,而后将要应用的数据写入权限。

class CalorieTrackerActivity : AppCompatActivity() {  // ...    private lateinit var dataController: DataController     override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentView(R.layout.activity_calorie_tracker)         initDataController()         //...    }            private fun initDataController() {        val hiHealthOptions = HiHealthOptions.builder()            .addDataType(DataType.DT_CONTINUOUS_CALORIES_CONSUMED, HiHealthOptions.ACCESS_READ)            .addDataType(DataType.DT_CONTINUOUS_CALORIES_CONSUMED, HiHealthOptions.ACCESS_WRITE)            .addDataType(DataType.DT_INSTANTANEOUS_BODY_WEIGHT, HiHealthOptions.ACCESS_READ)            .addDataType(DataType.DT_INSTANTANEOUS_BODY_WEIGHT, HiHealthOptions.ACCESS_WRITE)            .build()         val signInHuaweiId = HuaweiIdAuthManager.getExtendedAuthResult(hiHealthOptions)        dataController = HuaweiHiHealth.getDataController(this, signInHuaweiId)    }  }

通过addConsumedCalorie办法来记录数据。此前,须要设置一个工夫距离:将以后工夫作为完结工夫,并将其之前的一秒作为开始工夫。

  private fun addConsumedCalorie(calorie: Float) {      val dataCollector: DataCollector = DataCollector.Builder().setPackageName(this)            .setDataType(DataType.DT_CONTINUOUS_CALORIES_CONSUMED)            .setDataGenerateType(DataCollector.DATA_TYPE_RAW)            .build()         val sampleSet = SampleSet.create(dataCollector)         val currentTime = System.currentTimeMillis()         val samplePoint = sampleSet.createSamplePoint()            .setTimeInterval(currentTime - 1, currentTime, TimeUnit.MILLISECONDS)        samplePoint.getFieldValue(Field.FIELD_CALORIES).setFloatValue(calorie)        sampleSet.addSample(samplePoint)               val insertTask: Task<Void> = dataController.insert(sampleSet)         insertTask.addOnSuccessListener {            Toast.makeText(this, "Calorie added successfully", Toast.LENGTH_SHORT).show()        }.addOnFailureListener { e ->            Toast.makeText(this, e.message.toString(), Toast.LENGTH_LONG).show()        }    }

咱们创立了一个名为addWightData的办法,相似于addConsumedCalori办法。但这一次,输出的开始工夫和完结工夫的值必须雷同。否则,当输出分量信息时,利用将呈现解体。咱们还更改了数据类型。

private fun addWeightData(weight: Float) {        val dataCollector: DataCollector = DataCollector.Builder().setPackageName(this)            .setDataType(DataType.DT_INSTANTANEOUS_BODY_WEIGHT)            .setDataGenerateType(DataCollector.DATA_TYPE_RAW)            .build()         val sampleSet = SampleSet.create(dataCollector)         val currentTime = System.currentTimeMillis()         val samplePoint = sampleSet.createSamplePoint()            .setTimeInterval(currentTime, currentTime, TimeUnit.MILLISECONDS)        samplePoint.getFieldValue(Field.FIELD_BODY_WEIGHT).setFloatValue(weight)        sampleSet.addSample(samplePoint)         val insertTask: Task<Void> = dataController.insert(sampleSet)         insertTask.addOnSuccessListener {            Toast.makeText(this, "Weight added successfully", Toast.LENGTH_SHORT).show()        }.addOnFailureListener { e ->            Toast.makeText(this, e.message.toString(), Toast.LENGTH_SHORT).show()        }    }
接下来应用readConsumedData办法来读取耗费的卡路里数据。咱们抉择了一周前到以后的工夫范畴,而后检索了这个工夫范畴内的所有数据,并将其作为工夫值放在Map上。最初,调用showCaloriesWeekly办法在条形图中显示这些数据。
 private fun readConsumedData() {         val caloriesMap = mutableMapOf<Long, Float>()         val endDate = System.currentTimeMillis()        val startDate = endDate - SIX_DAY_MILLIS         val readOptions = ReadOptions.Builder()            .read(DataType.DT_CONTINUOUS_CALORIES_CONSUMED)            .setTimeRange(startDate, endDate, TimeUnit.MILLISECONDS).build()         val readReplyTask = dataController.read(readOptions)         readReplyTask.addOnSuccessListener { readReply ->            for (sampleSet in readReply.sampleSets) {                if (sampleSet.isEmpty.not()) {                    sampleSet.samplePoints.forEach {                        caloriesMap.put(                            it.getStartTime(TimeUnit.MILLISECONDS),                            it.getFieldValue(Field.FIELD_CALORIES).asFloatValue()                        )                    }                } else {                    Toast.makeText(this, "No data to show", Toast.LENGTH_SHORT).show()                }            }             showCaloriesWeekly(caloriesMap)         }.addOnFailureListener {            Log.i(TAG, it.message.toString())        }    }

应用readWightData办法来检索记录的体重信息。

 private fun readWeightData() {         val weightsMap = mutableMapOf<Long, Float>()         val endDate = System.currentTimeMillis()        val startDate = endDate - SIX_DAY_MILLIS         val readOptions = ReadOptions.Builder().read(DataType.DT_INSTANTANEOUS_BODY_WEIGHT)            .setTimeRange(startDate, endDate, TimeUnit.MILLISECONDS).build()         val readReplyTask = dataController.read(readOptions)         readReplyTask.addOnSuccessListener { readReply ->             for (sampleSet in readReply.sampleSets) {                if (sampleSet.isEmpty.not()) {                    sampleSet.samplePoints.forEach {                        weightsMap.put(                            it.getStartTime(TimeUnit.MILLISECONDS),                            it.getFieldValue(Field.FIELD_BODY_WEIGHT).asFloatValue()                        )                    }                } else {                    Toast.makeText(this, "No data to show", Toast.LENGTH_SHORT).show()                }            }             showWeightsWeekly(weightsMap)         }.addOnFailureListener {            Log.i(TAG, it.message.toString())        }    }

应用showCaloriesWeekly办法获取上周的数据作为工夫值。在获取值后,将上周每天的数据相加。最初调用initBarChart办法在条形图上显示每日数据。

 private fun showCaloriesWeekly(dataList: Map<Long, Float>) {         val arrangedValuesAsMap = mutableMapOf<Long, Float>()        val currentTimeMillis = System.currentTimeMillis()         var firstDayCal = 0f        var secondDayCal = 0f        var thirdDayCal = 0f        var fourthDayCal = 0f        var fifthDayCal = 0f        var sixthDayCal = 0f        var seventhDayCal = 0f         dataList.forEach { (time, value) ->            when (time) {                in getTodayStartInMillis()..currentTimeMillis -> {                    seventhDayCal += value                }                in getTodayStartInMillis() - ONE_DAY_MILLIS until getTodayStartInMillis() -> {                    sixthDayCal += value                }                in getTodayStartInMillis() - ONE_DAY_MILLIS * 2 until                        getTodayStartInMillis() - ONE_DAY_MILLIS -> {                    fifthDayCal += value                }                in getTodayStartInMillis() - ONE_DAY_MILLIS * 3 until                        getTodayStartInMillis() - ONE_DAY_MILLIS * 2 -> {                    fourthDayCal += value                }                in getTodayStartInMillis() - ONE_DAY_MILLIS * 4 until                        getTodayStartInMillis() - ONE_DAY_MILLIS * 3 -> {                    thirdDayCal += value                }                in getTodayStartInMillis() - ONE_DAY_MILLIS * 5 until                        getTodayStartInMillis() - ONE_DAY_MILLIS * 4 -> {                    secondDayCal += value                }                in getTodayStartInMillis() - ONE_DAY_MILLIS * 6 until                        getTodayStartInMillis() - ONE_DAY_MILLIS * 5 -> {                    firstDayCal += value                }            }        }         arrangedValuesAsMap.put(getTodayStartInMillis() - ONE_DAY_MILLIS * 6, firstDayCal)        arrangedValuesAsMap.put(getTodayStartInMillis() - ONE_DAY_MILLIS * 5, secondDayCal)        arrangedValuesAsMap.put(getTodayStartInMillis() - ONE_DAY_MILLIS * 4, thirdDayCal)        arrangedValuesAsMap.put(getTodayStartInMillis() - ONE_DAY_MILLIS * 3, fourthDayCal)        arrangedValuesAsMap.put(getTodayStartInMillis() - ONE_DAY_MILLIS * 2, fifthDayCal)        arrangedValuesAsMap.put(getTodayStartInMillis() - ONE_DAY_MILLIS, sixthDayCal)        arrangedValuesAsMap.put(getTodayStartInMillis(), seventhDayCal)         initBarChart(arrangedValuesAsMap)     }

showWightWeekly的工作原理简直与showCaloriesWeekly办法类似。它们之间惟一的区别是,咱们不在showWightWeekly办法中求和每日值,而是只取得每日的一个最新值。

private fun showWeightsWeekly(dataList: Map<Long, Float>) {         val arrangedValuesAsMap = mutableMapOf<Long, Float>()        val currentTimeMillis = System.currentTimeMillis()         var firstDayWeight = 0f        var secondDayWeight = 0f        var thirdDayWeight = 0f        var fourthDayWeight = 0f        var fifthDayWeight = 0f        var sixthDayWeight = 0f        var seventhDayWeight = 0f         dataList.forEach { (time, value) ->            when (time) {                in getTodayStartInMillis()..currentTimeMillis -> {                    seventhDayWeight = value                }                in getTodayStartInMillis() - ONE_DAY_MILLIS until getTodayStartInMillis() -> {                    sixthDayWeight = value                }                in getTodayStartInMillis() - ONE_DAY_MILLIS * 2 until                        getTodayStartInMillis() - ONE_DAY_MILLIS -> {                    fifthDayWeight = value                }                in getTodayStartInMillis() - ONE_DAY_MILLIS * 3 until                        getTodayStartInMillis() - ONE_DAY_MILLIS * 2 -> {                    fourthDayWeight = value                }                in getTodayStartInMillis() - ONE_DAY_MILLIS * 4 until                        getTodayStartInMillis() - ONE_DAY_MILLIS * 3 -> {                    thirdDayWeight = value                }                in getTodayStartInMillis() - ONE_DAY_MILLIS * 5 until                        getTodayStartInMillis() - ONE_DAY_MILLIS * 4 -> {                    secondDayWeight = value                }                in getTodayStartInMillis() - ONE_DAY_MILLIS * 6 until                        getTodayStartInMillis() - ONE_DAY_MILLIS * 5 -> {                    firstDayWeight = value                }            }        }         arrangedValuesAsMap.put(getTodayStartInMillis() - ONE_DAY_MILLIS * 6, firstDayWeight)        arrangedValuesAsMap.put(getTodayStartInMillis() - ONE_DAY_MILLIS * 5, secondDayWeight)        arrangedValuesAsMap.put(getTodayStartInMillis() - ONE_DAY_MILLIS * 4, thirdDayWeight)        arrangedValuesAsMap.put(getTodayStartInMillis() - ONE_DAY_MILLIS * 3, fourthDayWeight)        arrangedValuesAsMap.put(getTodayStartInMillis() - ONE_DAY_MILLIS * 2, fifthDayWeight)        arrangedValuesAsMap.put(getTodayStartInMillis() - ONE_DAY_MILLIS, sixthDayWeight)        arrangedValuesAsMap.put(getTodayStartInMillis(), seventhDayWeight)         initBarChart(arrangedValuesAsMap)     }

InitBarChart以图形模式显示数据。

  private fun initBarChart(values: MutableMap<Long, Float>) {         var barIndex = 0f        val labelWeekdayNames = arrayListOf<String>()        val entries = ArrayList<BarEntry>()         val simpleDateFormat = SimpleDateFormat("E", Locale.US)         values.forEach { (time, value) ->            labelWeekdayNames.add(simpleDateFormat.format(time))            entries.add(BarEntry(barIndex, value))            barIndex++        }         barChart.apply {            setDrawBarShadow(false)            setDrawValueAboveBar(false)            description.isEnabled = false            setDrawGridBackground(false)            isDoubleTapToZoomEnabled = false        }         barChart.xAxis.apply {            setDrawGridLines(false)            position = XAxis.XAxisPosition.BOTTOM            granularity = 1f            setDrawLabels(true)            setDrawAxisLine(false)            valueFormatter = IndexAxisValueFormatter(labelWeekdayNames)            axisMaximum = labelWeekdayNames.size.toFloat()        }         barChart.axisRight.isEnabled = false         val legend = barChart.legend        legend.isEnabled = false         val dataSets = arrayListOf<IBarDataSet>()        val barDataSet = BarDataSet(entries, " ")        barDataSet.color = Color.parseColor("#76C33A")        barDataSet.setDrawValues(false)        dataSets.add(barDataSet)         val data = BarData(dataSets)        barChart.data = data        barChart.invalidate()        barChart.animateY(1500)     }

此外

除了增加和读取静止与衰弱数据外,Health Kit还提供更新数据、删除数据和革除所有数据的性能。尽管咱们没有在利用中应用这些性能,但也能够疾速理解一下。

updateWight:能够在指定的工夫范畴内更新数据。如果想应用体重信息,那就须要将开始工夫和完结工夫设置为雷同的工夫值。但如果咱们想更新卡路里值,就须要设置为一个稍长的工夫范畴。如果指定工夫范畴内没有要更新的值时,它将主动增加新的分量或卡路里值。

private fun updateWeight(weight: Float, startTimeInMillis: Long, endTimeInMillis: Long) {         val dataCollector: DataCollector = DataCollector.Builder().setPackageName(this)            .setDataType(DataType.DT_INSTANTANEOUS_BODY_WEIGHT)            .setDataGenerateType(DataCollector.DATA_TYPE_RAW)            .build()         val sampleSet = SampleSet.create(dataCollector)         val samplePoint = sampleSet.createSamplePoint()            .setTimeInterval(startTimeInMillis, endTimeInMillis, TimeUnit.MILLISECONDS)        samplePoint.getFieldValue(Field.FIELD_BODY_WEIGHT).setFloatValue(weight)         sampleSet.addSample(samplePoint)         val updateOptions = UpdateOptions.Builder()            .setTimeInterval(startTimeInMillis, endTimeInMillis, TimeUnit.MILLISECONDS)            .setSampleSet(sampleSet)            .build()         dataController.update(updateOptions)            .addOnSuccessListener {                Toast.makeText(this, "Weight has been updated successfully", Toast.LENGTH_SHORT)                    .show()            }            .addOnFailureListener { e ->                Toast.makeText(this, e.message.toString(), Toast.LENGTH_SHORT).show()            }           }

deleteWight:删除指定范畴内的值。

 private fun deleteWeight(startTimeInMillis: Long, endTimeInMillis: Long) {         val dataCollector: DataCollector = DataCollector.Builder().setPackageName(this)            .setDataType(DataType.DT_INSTANTANEOUS_BODY_WEIGHT)            .setDataGenerateType(DataCollector.DATA_TYPE_RAW)            .build()         val deleteOptions = DeleteOptions.Builder()            .addDataCollector(dataCollector)            .setTimeInterval(startTimeInMillis, endTimeInMillis, TimeUnit.MILLISECONDS)            .build()         dataController.delete(deleteOptions).addOnSuccessListener {            Toast.makeText(this, "Weight has been deleted successfully", Toast.LENGTH_SHORT)                .show()        }            .addOnFailureListener { e ->                Toast.makeText(this, e.message.toString(), Toast.LENGTH_SHORT).show()            }     }

clearHealthData:删除Health Kit中的所有数据。

 private fun clearHealthData() {         dataController.clearAll()            .addOnSuccessListener {                Toast.makeText(this, "All Health Kit data has been deleted.", Toast.LENGTH_SHORT)                    .show()            }            .addOnFailureListener { e ->                Toast.makeText(this, e.message.toString(), Toast.LENGTH_SHORT).show()            }     }

提醒和技巧

⚠️确保已将数据的权限设置为范畴。否则,将返回错误代码50005。

⚠️应用data controller写入数据时,请确保应用正确的工夫距离。否则,当你尝试写入数据时,利用将产生解体。

欲了解HMS Core更多详情,请参阅:

华为开发者联盟官网
获取开发领导文档
参加开发者探讨请到CSDN社区或者Reddit社区
下载demo和示例代码请到Github或者Gitee
解决集成问题请到Stack Overflow

原文链接:https://developer.huawei.com/...
原作者:胡椒