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
相关产品推荐
相关产品推荐

