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

Google Fit API报错:与Google Play服务连接丢失问题求助

解决Google Fit API偶发com.google.android.gms.common.api.ApiException: 8错误

这个偶发的**INTERNAL_ERROR(错误码8)**确实挺头疼的,尤其是必须卸载应用才能恢复的情况,我结合自己的开发经验和社区常见方案,给你几个可行的排查和解决方向:

1. 先确保Google Play服务状态正常

错误提示里的「连接丢失」大概率和Google Play服务的状态有关,建议在发起Fit API请求前,先检查Play服务是否可用:

GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
int resultCode = apiAvailability.isGooglePlayServicesAvailable(context);
if (resultCode != ConnectionResult.SUCCESS) {
    if (apiAvailability.isUserResolvableError(resultCode)) {
        // 提示用户更新/修复Google Play服务
        apiAvailability.getErrorDialog(activity, resultCode, 9000).show();
    }
    return;
}

如果Play服务版本过旧或者出现异常,很容易导致这类连接问题,提前检查能避免很多偶发错误。

2. 优化重试策略,不要直接原地重试

官方文档说重试可以解决,但直接在onFailure里重新调用readData可能没用——因为此时连接状态可能还处于异常状态。建议:

  • 给重试加延迟(比如1-2秒),让Play服务有时间恢复连接
  • 重试前重新获取有效登录账号,避免使用失效的账号实例
  • 限制重试次数,防止无限循环

修改你的onFailure方法示例:

.addOnFailureListener(new OnFailureListener() {
    private int retryCount = 0;
    private static final int MAX_RETRIES = 3;

    @Override
    public void onFailure(@NonNull Exception e) {
        Crashlytics.log(Log.ASSERT, "fail :", e.toString());
        
        if (e instanceof ApiException && ((ApiException) e).getStatusCode() == CommonStatusCodes.INTERNAL_ERROR) {
            if (retryCount < MAX_RETRIES) {
                retryCount++;
                // 延迟1秒后重试
                new Handler(Looper.getMainLooper()).postDelayed(() -> {
                    GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(MainActivity.activity);
                    if (account != null) {
                        // 重新发起请求
                        Fitness.getHistoryClient(MainActivity.activity, account)
                                .readData(readRequest)
                                .addOnFailureListener(this)
                                .addOnSuccessListener(new OnSuccessListener<DataReadResponse>() {
                                    @Override
                                    public void onSuccess(DataReadResponse dataReadResponse) {
                                        // 复用之前的成功处理逻辑
                                        for (Bucket bucket : dataReadResponse.getBuckets()) {
                                            for (DataSet dataSet : bucket.getDataSets()) {
                                                for (DataPoint dataPoint : dataSet.getDataPoints()) {
                                                    User.current().userFitnessData.totalDistance = dataPoint.getValue(dataPoint.getDataType().getFields().get(0)).asFloat();
                                                }
                                            }
                                        }
                                        Crashlytics.log(Log.ASSERT, "Todays Steps", User.current().userFitnessData.getTodaysSteps() + "");
                                        if (callBack != null) callBack.onDistanceDataReceived();
                                    }
                                });
                    }
                }, 1000);
            } else {
                // 重试多次失败后,提示用户或者触发账号重新授权
                Toast.makeText(MainActivity.activity, "获取数据失败,请稍后重试", Toast.LENGTH_SHORT).show();
            }
        }
    }
})

3. 清理Fit客户端的本地连接状态

卸载应用能解决问题,说明本地缓存的Fit连接状态出了异常。可以尝试在重试前主动断开并重新初始化客户端:

// 断开现有连接
Fitness.getHistoryClient(MainActivity.activity, account).disconnect();
// 延迟后重新发起请求
new Handler(Looper.getMainLooper()).postDelayed(() -> {
    Fitness.getHistoryClient(MainActivity.activity, account)
            .readData(readRequest)
            .addOnFailureListener(...)
            .addOnSuccessListener(...);
}, 1500);

4. 检查账号授权状态是否有效

有时候用户的账号授权可能悄悄失效(比如系统清理了授权缓存),这时候即使getLastSignedInAccount不为null,也没有Fit的访问权限。建议在请求前检查授权:

// 假设你已经定义了FitnessOptions
FitnessOptions fitnessOptions = FitnessOptions.builder()
        .addDataType(DataType.TYPE_DISTANCE_DELTA, FitnessOptions.ACCESS_READ)
        .addDataType(DataType.AGGREGATE_DISTANCE_DELTA, FitnessOptions.ACCESS_READ)
        .build();

GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(MainActivity.activity);
if (!GoogleSignIn.hasPermissions(account, fitnessOptions)) {
    // 重新请求授权
    GoogleSignIn.requestPermissions(
            MainActivity.activity,
            1001,
            account,
            fitnessOptions);
    return;
}

5. 排查时间范围的合法性

虽然你的代码看起来没问题,但偶发情况下可能startTime和endTime出现异常(比如时间戳为0,或者startTime大于endTime),建议在构建DataReadRequest前添加校验:

if (startTime >= endTime) {
    Crashlytics.log(Log.WARN, "TimeRangeError", "startTime >= endTime");
    return;
}

最后要说明:这类内部错误有时候也可能是Google服务端的临时波动,但卸载能解决的情况,基本都是本地客户端状态异常导致的,按照上面的方案优化后,应该能大幅降低出现频率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:21:50