Google Fit睡眠追踪集成报错:需用户OAuth授权
解决Google Fit睡眠追踪中的ResolvableApiException: 5000错误
错误原因
这个5000: Application needs OAuth consent from the user错误直接表明:你的应用尚未获得用户的OAuth授权。Google Fit的睡眠数据属于敏感隐私数据,必须先完成用户授权流程,才能访问相关数据。你的现有代码跳过了授权步骤,直接尝试读取数据,因此触发了该异常。
解决方案
要解决这个问题,需要补充运行时权限请求和Google Fit OAuth授权的逻辑,同时处理异常中的授权引导。
1. 基础配置检查
- 在
AndroidManifest.xml中添加必要权限(Android 10及以上需要):<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" /> <uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" /> - 确保在Google Cloud Console中已启用Fit API,并配置了正确的OAuth客户端ID,同时添加
https://www.googleapis.com/auth/fitness.sleep.read权限范围。
2. 完整代码修改
步骤1:添加权限检查与授权引导方法
private val REQUEST_ACTIVITY_RECOGNITION = 1001 private val REQUEST_FIT_AUTH = 1002 private val REQUEST_RESOLVE_ERROR = 1003 private fun prepareToReadSleepData() { // 先检查Android运行时权限 if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACTIVITY_RECOGNITION) != PackageManager.PERMISSION_GRANTED ) { ActivityCompat.requestPermissions( this, arrayOf(Manifest.permission.ACTIVITY_RECOGNITION), REQUEST_ACTIVITY_RECOGNITION ) return } // 配置Google Fit需要的权限范围 val fitnessOptions = FitnessOptions.builder() .addDataType(DataType.TYPE_SLEEP_SEGMENT, FitnessOptions.ACCESS_READ) .addDataType(DataType.TYPE_SLEEP_SESSION, FitnessOptions.ACCESS_READ) .build() // 检查是否已获得Fit授权 if (!GoogleSignIn.hasPermissions(getGoogleAccount(), fitnessOptions)) { GoogleSignIn.requestPermissions( this, REQUEST_FIT_AUTH, getGoogleAccount(), fitnessOptions ) } else { // 权限齐全,读取睡眠数据 readSleepData() } }
步骤2:修改原读取数据方法的异常处理
更新readSleepData()中的失败监听,处理ResolvableApiException:
private fun readSleepData() { val request = SessionReadRequest.Builder() .readSessionsFromAllApps() .includeSleepSessions() .read(DataType.TYPE_SLEEP_SEGMENT) .setTimeInterval(periodStartMillis, periodEndMillis, TimeUnit.MILLISECONDS) .build() val sessionsClient = Fitness.getSessionsClient(this, getGoogleAccount()) sessionsClient.readSession(request) .addOnSuccessListener { response -> for (session in response.sessions) { val sessionStart = session.getStartTime(TimeUnit.MILLISECONDS) val sessionEnd = session.getEndTime(TimeUnit.MILLISECONDS) Log.i(TAG, "睡眠时段:$sessionStart 至 $sessionEnd") val dataSets = response.getDataSet(session) for (dataSet in dataSets) { for (point in dataSet.dataPoints) { val sleepStageVal = point.getValue(Field.FIELD_SLEEP_SEGMENT_TYPE).asInt() val sleepStage = SLEEP_STAGES[sleepStageVal] val segmentStart = point.getStartTime(TimeUnit.MILLISECONDS) val segmentEnd = point.getEndTime(TimeUnit.MILLISECONDS) Log.i(TAG, "\t睡眠阶段:$sleepStage,时段:$segmentStart 至 $segmentEnd") } } } } .addOnFailureListener { e -> Log.w(TAG, "获取睡眠数据失败", e) // 处理可解析的授权异常,引导用户完成授权 if (e is ResolvableApiException) { e.startResolutionForResult(this, REQUEST_RESOLVE_ERROR) } } }
步骤3:添加权限与授权的回调处理
在你的Activity中重写回调方法,处理权限请求和授权结果:
override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == REQUEST_ACTIVITY_RECOGNITION) { if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { prepareToReadSleepData() } else { Toast.makeText(this, "需要运动识别权限才能访问睡眠数据", Toast.LENGTH_SHORT).show() } } } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) when (requestCode) { REQUEST_FIT_AUTH, REQUEST_RESOLVE_ERROR -> { if (resultCode == RESULT_OK) { readSleepData() } else { Toast.makeText(this, "授权失败,无法读取睡眠数据", Toast.LENGTH_SHORT).show() } } } }
3. 使用方式
之后不要直接调用readSleepData(),而是调用prepareToReadSleepData(),它会自动完成权限检查、授权引导,再读取数据。
内容的提问来源于stack exchange,提问作者Dipan Das
相关产品推荐
相关产品推荐

