You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter Firebase中Facebook登录后读取Google Fitness API睡眠数据问题

Flutter Firebase Facebook登录后无法读取Google Fitness睡眠数据问题

我们基于Flutter开发一款睡眠数据仪表盘应用,通过Firebase实现社交登录,支持谷歌、Facebook及邮箱/密码三种登录方式。

谷歌登录正常情况

使用谷歌账号登录时,应用可正常获取睡眠数据,我们通过在GoogleSignIn中传入权限范围实现:

FirebaseAuth.instance, UserRepository(), GoogleSignIn(scopes:[
'https://www.googleapis.com/auth/fitness.sleep.read',
])),

Facebook登录后的错误

使用Facebook登录时,读取睡眠数据会持续抛出如下错误,核心困惑是不知道如何在Facebook登录流程中传入Google API权限范围:

W/FLUTTER_HEALTH::ERROR(31643): There was an error getting the sleeping data!
W/FLUTTER_HEALTH::ERROR(31643): 4: The user must be signed in to make this API call.
W/FLUTTER_HEALTH::ERROR(31643): [Ljava.lang.StackTraceElement;@7eb1aa0
W/FLUTTER_HEALTH::ERROR(31643): There was an error getting the sleeping data!
W/FLUTTER_HEALTH::ERROR(31643): 4: The user must be signed in to make this API call.
W/FLUTTER_HEALTH::ERROR(31643): [Ljava.lang.StackTraceElement;@ef740cc
W/FLUTTER_HEALTH::ERROR(31643): There was an error getting the sleeping data!
W/FLUTTER_HEALTH::ERROR(31643): 4: The user must be signed in to make this API call.
W/FLUTTER_HEALTH::ERROR(31643): [Ljava.lang.StackTraceElement;@abd9db8

当前读取睡眠数据的代码

Future fetchSleepData() async {
     List<HealthDataPoint> _healthDataList = [];
    final types = [
      HealthDataType.SLEEP_ASLEEP,
      HealthDataType.SLEEP_AWAKE,
      HealthDataType.SLEEP_IN_BED
    ];

    final permissions = [
      HealthDataAccess.READ,
      HealthDataAccess.READ,
      HealthDataAccess.READ
    ];
    final now = DateTime.now();
    final yesterday = now.subtract(Duration(days: 10));
    HealthFactory health = HealthFactory();
    bool requested =
        await health.requestAuthorization(types, permissions: permissions);
    await Permission.activityRecognition.request();
    await Permission.location.request();
    if (requested) {
      try {
        // fetch health data
        List<HealthDataPoint> healthData =
            await health.getHealthDataFromTypes(yesterday, now, types);
        // save all the new data points (only the first 100)
        _healthDataList.addAll((healthData.length < 100)
            ? healthData
            : healthData.sublist(0, 100));
      } catch (error) {
        print("Exception in getHealthDataFromTypes: $error");
      }
      // filter out duplicates
      _healthDataList = HealthFactory.removeDuplicates(_healthDataList);
      // print the results
      _healthDataList.forEach((x) => print(x));
    }
  }

解决方案建议

  1. 核心逻辑明确
    Google Fitness API仅接受Google账号的OAuth 2.0令牌认证,Facebook登录的凭证无法直接用于调用该API。无论用户用哪种方式登录Firebase,要读取Google睡眠数据,都需要额外完成Google账号的授权流程。

  2. 具体实现步骤

    • 当用户通过Facebook/邮箱登录后,首次进入睡眠数据页面时,触发Google账号授权流程,传入fitness.sleep.read权限范围。
    • 授权成功后,确保HealthFactory使用Google的认证令牌进行API调用。
  3. 代码调整示例
    在fetchSleepData执行前,先检查并获取Google授权:

    final GoogleSignIn _googleSignIn = GoogleSignIn(scopes: [
      'https://www.googleapis.com/auth/fitness.sleep.read',
    ]);
    
    Future<void> ensureGoogleAuth() async {
      if (!await _googleSignIn.isSignedIn()) {
        await _googleSignIn.signIn();
      }
    }
    

    调用顺序调整为:先执行ensureGoogleAuth(),再执行fetchSleepData()。

  4. 用户体验优化
    在Facebook登录后首次访问睡眠数据时,添加明确提示,告知用户需要关联Google账号以获取睡眠数据,避免授权弹窗过于突兀。

内容的提问来源于stack exchange,提问作者Ramesh Angamuthu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 06:13:17