尝试访问 Google Fit API 时出现异常 - 用户必须登录才能进行此 API 调用

问题描述 投票:0回答:3

我正在尝试设置一个在 WearOS 上运行的可穿戴应用程序(适用于华为手表 2),以向 Google Fit 帐户提供一种连续的心率(BPM)馈送,该帐户被读入另一个智能手机应用程序。

当我尝试设置帐户并按如下方式访问数据时出现问题:

    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)
        }
    }

异常堆栈跟踪:

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)

我的手表与我用来读取数据的智能手机配对(我只需要从 google fit 获得更快的更新,并考虑过强制执行此操作。此处没有可用的代码)。 存在相同的 google fit 帐户,登录到 Google Fit 应用程序并在两台设备上同步。 一切都在智能手机上顺利运行(即使使用相同的代码),而在手表上设置帐户时出现“用户必须登录”异常。

Google 服务依赖项、应用程序权限在两种设备上的设置方式相同,以及所需的 OAuth 设置、SHA1 和开发人员控制台上的凭据。

这可能是与手表->应用->Google Fit 帐户同步有关的问题,还是我遗漏了什么?

android kotlin wear-os google-fit google-fit-api
3个回答
2
投票

在 Google 控制台中注册项目,并在为您的项目添加 OAuth 2.0 客户端 ID 后将您的 Google 帐户添加为测试用户。

这应该可以解决登录问题。


1
投票

这是我修复它的方法:

  • 使用您的电子邮件验证您在 Google Cloud 中是否有测试用户
  • 验证您在 Google Cloud Credentials 上是否拥有与您的证书相关联的 OAuth 2.0 客户端 ID
  • 使用 Package Manager 之类的应用程序验证您在 Android 上的应用程序证书是否与上面写的相对应
  • 确保在尝试访问任何其他内容之前调用
    GoogleSignIn.hasPermissions
    并且它返回
    true

已检查的论文应修复 Google Fit 的大多数错误,不会给您任何结果或让您停留在加载屏幕上

另外,Google Fit 历史请求需要有一个好的

TimeUnit
ex for
Type_WEIGHT
TimeUnit 应该是
MILLISECONDS
因为任何更高的值都不会返回任何值

前历史请求生成器:

DataReadRequest.Builder()
    .read(DataType.TYPE_WEIGHT)
    .setTimeRange(/* 1st January 2013 */, /* now */, TimeUnut.MILLISECONDS)
    .build()

1
投票

固定

我已经弄清楚这里的主要问题是什么。 出现在您面前的允许您实际选择您的 Google 帐户的对话框有一个错误。显然,当您从中选择一个帐户时,您的帐户实际上并未被选中,因为不知何故,对话框在被选中之前就消失了。要确认这一点,只需从后台删除您的应用程序并再次运行它。您会再次看到相同的对话框,这意味着您之前没有选择过您的帐户。

要解决此问题,只需确保在该对话框中按住您的手指在 Google 帐户上,然后在一两秒后松开,以确保它确实被选中。否则,如果您的帐户未被选择,那么每当您关闭并重新运行该应用程序时,该对话框将再次出现,要求您重新选择您的帐户。

或者如果您收到此

"The user must be signed in to make this API call"
错误,只需添加再次触发该对话框的逻辑。


如果以上都不起作用,请尝试在 OAuth 同意屏幕中添加范围。就我而言,我正在构建一个应用程序来读取/写入有关步骤的数据。这就是我启用这两个范围的原因:

.../auth/fitness.activity.write
.../auth/fitness.activity.read
© www.soinside.com 2019 - 2024. All rights reserved.