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

Android步行计步应用中GoogleSignIn.requestPermissions弹出空白加载弹窗及Fitness API权限调用报错问题

解决Google Fit计步应用的两个核心问题

我来帮你拆解并解决遇到的这两个问题:

问题2:The user must be signed in to make this API call 错误

这个报错的核心原因是:你调用Fitness API时,用户还没完成完整的Google账号登录授权流程。当前你用GoogleSignIn.getAccountForExtension获取的只是关联Fitness的扩展账户,但并没有确保用户已经通过Google Sign-In完成了账号登录。

修复步骤:

  1. 先检查用户是否已登录Google账号,再检查Fitness权限
  2. 若未登录,先启动Google登录流程,再请求Fitness权限

修改onCreate及相关逻辑如下:

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    fitnessOptions = FitnessOptions.builder() 
            .addDataType(DataType.TYPE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)
            .addDataType(DataType.AGGREGATE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)
            .addDataType(DataType.TYPE_CALORIES_EXPENDED, FitnessOptions.ACCESS_READ)
            .addDataType(DataType.AGGREGATE_CALORIES_EXPENDED, FitnessOptions.ACCESS_READ)
            .addDataType(DataType.TYPE_DISTANCE_DELTA, FitnessOptions.ACCESS_READ)
            .addDataType(DataType.AGGREGATE_DISTANCE_DELTA, FitnessOptions.ACCESS_READ) 
            .build(); 

    // 先处理Android 10+必需的Activity Recognition权限
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACTIVITY_RECOGNITION)
            != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.ACTIVITY_RECOGNITION},
                MY_PERMISSIONS_REQUEST_ACTIVITY_RECOGNITION);
    } else {
        checkGoogleSignInStatus();
    }

    setContentView(R.layout.activity_start); 
    btnPause = findViewById(R.id.btnPause); 
    btnPause.setOnClickListener(v -> {
        // 这里添加暂停逻辑
    }); 
}

// 新增方法:检查Google登录及权限状态
private void checkGoogleSignInStatus() {
    GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this);
    if (account == null || !GoogleSignIn.hasPermissions(account, fitnessOptions)) {
        if (account == null) {
            // 未登录,先启动Google登录+权限请求流程
            GoogleSignInClient signInClient = GoogleSignIn.getClient(this, GoogleSignInOptions.DEFAULT_SIGN_IN);
            signInClient.requestPermissions(
                    this,
                    RC_REQUEST_STEP_COUNT_AND_CONTINUE_SUBSCRIPTION,
                    GoogleSignIn.getAccountForExtension(this, fitnessOptions),
                    fitnessOptions);
        } else {
            // 已登录但缺少Fitness权限,单独请求权限
            GoogleSignIn.requestPermissions(
                    this,
                    RC_REQUEST_STEP_COUNT_AND_CONTINUE_SUBSCRIPTION,
                    account,
                    fitnessOptions);
        }
    } else {
        // 已登录且权限齐全,启动数据订阅
        startSubscription(DataType.TYPE_STEP_COUNT_DELTA);
    }
}

// 处理Activity Recognition权限请求结果
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == MY_PERMISSIONS_REQUEST_ACTIVITY_RECOGNITION) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            checkGoogleSignInStatus();
        } else {
            Toast.makeText(this, "需要Activity Recognition权限才能获取步数数据", Toast.LENGTH_SHORT).show();
        }
    }
}

问题1:调用GoogleSignIn.requestPermissions时弹出空白加载弹窗

这个空白弹窗通常是因为权限请求流程启动时,用户还未完成Google账号登录,导致流程异常。通过上面的修复,我们先确保用户完成Google登录,再请求Fitness权限,就能解决这个问题。

另外还要注意:

  • 确保AndroidManifest.xml已按照官方要求配置好Google Fit的权限、元数据及API密钥
  • 测试时使用已添加Google账号的设备/模拟器,避免因无账号导致流程中断

额外代码优化建议

  1. 你的getDataUsingSensor方法中,强制转换所有字段值为float可能报错,不同DataType的字段类型不同,建议做类型判断:
@Override 
public void onDataPoint(@NonNull DataPoint dataPoint) { 
    for (Field field : dataPoint.getDataType().getFields()) {
        Value value = dataPoint.getValue(field);
        if (field.equals(Field.FIELD_STEPS)) {
            int steps = value.asInt();
            tvSteps.setText(String.valueOf(steps));
        } else if (field.equals(Field.FIELD_DISTANCE)) {
            float distance = value.asFloat();
            tvDistance.setText(String.format("%.2f km", distance));
        }
        // 其他字段同理处理
    }
}
  1. 在onDestroy中移除传感器监听,避免内存泄漏:
private OnDataPointListener dataPointListener;

// 修改getDataUsingSensor方法保存listener引用
public void getDataUsingSensor(DataType dataType) { 
    dataPointListener = new OnDataPointListener() { 
        @Override 
        public void onDataPoint(@NonNull DataPoint dataPoint) { 
            // 数据处理逻辑
        } 
    };
    Fitness.getSensorsClient(this, GoogleSignIn.getLastSignedInAccount(this))
            .add(new SensorRequest.Builder()
                    .setDataType(dataType)
                    .setSamplingRate(1, TimeUnit.SECONDS)
                    .build(), dataPointListener);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    if (dataPointListener != null && GoogleSignIn.getLastSignedInAccount(this) != null) {
        Fitness.getSensorsClient(this, GoogleSignIn.getLastSignedInAccount(this))
                .remove(dataPointListener);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 11:27:33