I am trying to set up a wearable app (for Huawei Watch 2) running on WearOS to provide a sort of continuous feed of Heart Rate (BPM) into a Google Fit account, which is read into another smartphone application.
The issue comes when I am trying to set up the account and access the data as it follows:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (ContextCompat.checkSelfPermission(this, Manifest.permission.BODY_SENSORS)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.BODY_SENSORS),GOOGLE_FIT_PERMISSIONS_REQUEST_CODE)
}
fitnessOptions = FitnessOptions.builder()
.addDataType(DataType.TYPE_HEART_RATE_BPM, FitnessOptions.ACCESS_READ)
.addDataType(DataType.TYPE_HEART_RATE_BPM, FitnessOptions.ACCESS_WRITE)
.build()
account = GoogleSignIn.getAccountForExtension(this, fitnessOptions)
if (!GoogleSignIn.hasPermissions(account, fitnessOptions)) {
GoogleSignIn.requestPermissions(
this, // your activity
GOOGLE_FIT_PERMISSIONS_REQUEST_CODE, // e.g. 1
account,
fitnessOptions);
} else {
accessGoogleFit()
}
timer.scheduleAtFixedRate(
object : TimerTask() {
override fun run() {
Log.i("[TimerTask]", "Retrieving data..")
accessGoogleFit()
Log.i("[Account]", "" + account.email)
}
},0, 1000
)
// Enables Always-on
setAmbientEnabled()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (resultCode) {
Activity.RESULT_OK -> when (requestCode) {
GOOGLE_FIT_PERMISSIONS_REQUEST_CODE -> accessGoogleFit()
else -> {}
}
else -> {}
}
}
private fun accessGoogleFit() {
val cal: Calendar = Calendar.getInstance()
val now = Date()
cal.setTime(now)
val endTime: Long = cal.getTimeInMillis()
cal.add(Calendar.DAY_OF_MONTH, -1)
val startTime: Long = cal.getTimeInMillis()
val historyRequest = DataReadRequest.Builder()
.read(DataType.TYPE_HEART_RATE_BPM)
.enableServerQueries()
.setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS)
.build()
val sourceRequest = DataSourcesRequest.Builder()
.setDataTypes(DataType.TYPE_HEART_RATE_BPM)
.setDataSourceTypes(DataSource.TYPE_RAW, DataSource.TYPE_DERIVED)
.build()
Fitness.getHistoryClient(this,account)
.readData(historyRequest)
.addOnSuccessListener{
response-> txt_GoogleFit_FitData.setText(response.dataSets.get(0).toString())
}
.addOnFailureListener{ e ->
Log.e("[GoogleFIT]", "Find data sources request failed", e)
}
Fitness.getSensorsClient(this, account)
.findDataSources(sourceRequest)
.addOnSuccessListener { dataSources ->
dataSources.forEach {
Log.i("[GoogleFIT]", "Data source found: ${it.streamIdentifier}")
Log.i("[GoogleFIT]", "Data Source type: ${it.dataType.name}")
if (it.dataType == DataType.TYPE_HEART_RATE_BPM) {
Log.i("[GoogleFIT]", "Data source for LOCATION_SAMPLE found!")
}
}
}
.addOnFailureListener { e ->
Log.e("[GoogleFIT]", "Find data sources request failed", e)
}
}
Stack trace of exception:
2021-01-27 17:08:07.032 13743-13767/com.example.watch_bpmupdated2 I/[TimerTask]: Retrieving data..
2021-01-27 17:08:07.036 13743-13767/com.example.watch_bpmupdated2 I/[Account]: <<default account>>
2021-01-27 17:08:07.057 13743-13743/com.example.watch_bpmupdated2 E/[GoogleFIT]: Find data sources request failed
com.google.android.gms.common.api.ApiException: 4: The user must be signed in to make this API call.
at com.google.android.gms.common.internal.ApiExceptionUtil.fromStatus(com.google.android.gms:play-services-base@@17.1.0:4)
at com.google.android.gms.common.internal.zai.zaf(com.google.android.gms:play-services-base@@17.1.0:2)
at com.google.android.gms.common.internal.zak.onComplete(com.google.android.gms:play-services-base@@17.1.0:6)
at com.google.android.gms.common.api.internal.BasePendingResult.zaa(com.google.android.gms:play-services-base@@17.1.0:176)
at com.google.android.gms.common.api.internal.BasePendingResult.setResult(com.google.android.gms:play-services-base@@17.1.0:135)
at com.google.android.gms.common.api.internal.BaseImplementation$ApiMethodImpl.setFailedResult(com.google.android.gms:play-services-base@@17.1.0:29)
at com.google.android.gms.common.api.internal.zad.zaa(com.google.android.gms:play-services-base@@17.1.0:9)
at com.google.android.gms.common.api.internal.GoogleApiManager$zaa.zac(com.google.android.gms:play-services-base@@17.1.0:175)
at com.google.android.gms.common.api.internal.GoogleApiManager$zaa.onConnectionFailed(com.google.android.gms:play-services-base@@17.1.0:79)
at com.google.android.gms.common.internal.zag.onConnectionFailed(com.google.android.gms:play-services-base@@17.1.0:2)
at com.google.android.gms.common.internal.BaseGmsClient$zzg.zza(com.google.android.gms:play-services-basement@@17.1.1:6)
at com.google.android.gms.common.internal.BaseGmsClient$zza.zza(com.google.android.gms:play-services-basement@@17.1.1:25)
at com.google.android.gms.common.internal.BaseGmsClient$zzb.zzo(com.google.android.gms:play-services-basement@@17.1.1:11)
at com.google.android.gms.common.internal.BaseGmsClient$zzc.handleMessage(com.google.android.gms:play-services-basement@@17.1.1:49)
at android.os.Handler.dispatchMessage(Handler.java:105)
at com.google.android.gms.internal.common.zzi.dispatchMessage(com.google.android.gms:play-services-basement@@17.1.1:8)
at android.os.Looper.loop(Looper.java:164)
at android.os.HandlerThread.run(HandlerThread.java:65)
2021-01-27 17:08:07.060 13743-13743/com.example.watch_bpmupdated2 E/[GoogleFIT]: Find data sources request failed
com.google.android.gms.common.api.ApiException: 4: The user must be signed in to make this API call.
at com.google.android.gms.common.internal.ApiExceptionUtil.fromStatus(com.google.android.gms:play-services-base@@17.1.0:4)
at com.google.android.gms.common.internal.zai.zaf(com.google.android.gms:play-services-base@@17.1.0:2)
at com.google.android.gms.common.internal.zak.onComplete(com.google.android.gms:play-services-base@@17.1.0:6)
at com.google.android.gms.common.api.internal.BasePendingResult.zaa(com.google.android.gms:play-services-base@@17.1.0:176)
at com.google.android.gms.common.api.internal.BasePendingResult.setResult(com.google.android.gms:play-services-base@@17.1.0:135)
at com.google.android.gms.common.api.internal.BaseImplementation$ApiMethodImpl.setFailedResult(com.google.android.gms:play-services-base@@17.1.0:29)
at com.google.android.gms.common.api.internal.zad.zaa(com.google.android.gms:play-services-base@@17.1.0:9)
at com.google.android.gms.common.api.internal.GoogleApiManager$zaa.zac(com.google.android.gms:play-services-base@@17.1.0:175)
at com.google.android.gms.common.api.internal.GoogleApiManager$zaa.onConnectionFailed(com.google.android.gms:play-services-base@@17.1.0:79)
at com.google.android.gms.common.internal.zag.onConnectionFailed(com.google.android.gms:play-services-base@@17.1.0:2)
at com.google.android.gms.common.internal.BaseGmsClient$zzg.zza(com.google.android.gms:play-services-basement@@17.1.1:6)
at com.google.android.gms.common.internal.BaseGmsClient$zza.zza(com.google.android.gms:play-services-basement@@17.1.1:25)
at com.google.android.gms.common.internal.BaseGmsClient$zzb.zzo(com.google.android.gms:play-services-basement@@17.1.1:11)
at com.google.android.gms.common.internal.BaseGmsClient$zzc.handleMessage(com.google.android.gms:play-services-basement@@17.1.1:49)
at android.os.Handler.dispatchMessage(Handler.java:105)
at com.google.android.gms.internal.common.zzi.dispatchMessage(com.google.android.gms:play-services-basement@@17.1.1:8)
at android.os.Looper.loop(Looper.java:164)
at android.os.HandlerThread.run(HandlerThread.java:65)
My watch is paired to the smartphone I am using to read the data (I just need faster updates from google fit, and thought about forcing this. Code not available here for that). The same google fit account is present, logged into Google Fit app and synced on both devices. Everything runs smoothly on the smartphone (even with the same code), while on the Watch I get the "user must be signed in" exception when setting up the account.
Google services dependencies, application permissions are set the same way on both devices, as well as the required OAuth settings, SHA1 and credentials on the developer console.
Could this be an issue related to the watch->App->Google Fit account synchronization, or am I missing something?