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

Android集成Google Fit后,如何获取步数计数器的定时更新回调?

看起来你已经搞定了Google Fit的基础集成,接下来要实现通过PendingIntent获取步数更新的定时回调,把数据同步到服务器对吧?我来一步步帮你完成这个需求:

实现步数更新的PendingIntent回调步骤

1. 编写接收更新的BroadcastReceiver

首先得创建一个BroadcastReceiver子类,用来接收Google Fit推送的步数更新广播,在里面处理数据获取和上传服务器的逻辑:

public class StepUpdateReceiver extends BroadcastReceiver {
    private static final String TAG = "StepUpdateReceiver";
    // 注意:这里要确保mGoogleApiClient是可用的,你可以通过全局引用或者在Receiver里重新初始化
    private GoogleApiClient mGoogleApiClient;

    @Override
    public void onReceive(Context context, Intent intent) {
        if (Fitness.ACTION_DATA_AVAILABLE.equals(intent.getAction())) {
            // 初始化GoogleApiClient(如果之前没保持连接的话)
            initGoogleApiClient(context);
            if (mGoogleApiClient.isConnected()) {
                fetchLatestStepData();
            } else {
                mGoogleApiClient.connect();
            }
        }
    }

    private void initGoogleApiClient(Context context) {
        if (mGoogleApiClient == null) {
            mGoogleApiClient = new GoogleApiClient.Builder(context)
                    .addApi(Fitness.HISTORY_API)
                    .addScope(new Scope(Scopes.FITNESS_BODY_READ_WRITE))
                    .addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
                        @Override
                        public void onConnected(@Nullable Bundle bundle) {
                            fetchLatestStepData();
                        }

                        @Override
                        public void onConnectionSuspended(int i) {
                            Log.w(TAG, "GoogleApiClient suspended");
                        }
                    })
                    .addOnConnectionFailedListener(connectionResult -> 
                            Log.e(TAG, "GoogleApiClient connection failed: " + connectionResult.getErrorMessage()))
                    .build();
        }
    }

    private void fetchLatestStepData() {
        // 获取最近24小时的步数数据,你可以根据需求调整时间范围
        Calendar cal = Calendar.getInstance();
        long endTime = cal.getTimeInMillis();
        cal.add(Calendar.DAY_OF_YEAR, -1);
        long startTime = cal.getTimeInMillis();

        DataReadRequest readRequest = new DataReadRequest.Builder()
                .aggregate(DataType.TYPE_STEP_COUNT_DELTA, DataType.AGGREGATE_STEP_COUNT_DELTA)
                .setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS)
                .bucketByTime(1, TimeUnit.HOURS) // 按小时分桶统计,可按需修改
                .build();

        Fitness.HistoryApi.readData(mGoogleApiClient, readRequest)
                .setResultCallback(dataReadResult -> {
                    if (dataReadResult.getStatus().isSuccess()) {
                        int totalSteps = calculateTotalSteps(dataReadResult);
                        Log.d(TAG, "获取到的总步数:" + totalSteps);
                        // 调用你的服务器接口上传数据
                        uploadStepsToServer(totalSteps);
                    } else {
                        Log.e(TAG, "读取步数数据失败:" + dataReadResult.getStatus().getMessage());
                    }
                    // 用完后断开连接,避免资源占用
                    if (mGoogleApiClient.isConnected()) {
                        mGoogleApiClient.disconnect();
                    }
                });
    }

    private int calculateTotalSteps(DataReadResult result) {
        int total = 0;
        // 处理分桶数据
        if (!result.getBuckets().isEmpty()) {
            for (Bucket bucket : result.getBuckets()) {
                for (DataSet dataSet : bucket.getDataSets()) {
                    total += sumDataSet(dataSet);
                }
            }
        } else {
            // 处理直接返回的数据集
            for (DataSet dataSet : result.getDataSets()) {
                total += sumDataSet(dataSet);
            }
        }
        return total;
    }

    private int sumDataSet(DataSet dataSet) {
        int sum = 0;
        for (DataPoint dp : dataSet.getDataPoints()) {
            for (Field field : dp.getDataType().getFields()) {
                sum += dp.getValue(field).asInt();
            }
        }
        return sum;
    }

    private void uploadStepsToServer(int steps) {
        // 这里实现你的服务器上传逻辑,比如用Retrofit/OkHttp发送请求
        // 示例伪代码:
        // ApiService service = RetrofitClient.getInstance().create(ApiService.class);
        // Call<Void> call = service.uploadUserSteps(steps);
        // call.enqueue(new Callback<Void>() {
        //     @Override
        //     public void onResponse(Call<Void> call, Response<Void> response) {
        //         if (response.isSuccessful()) {
        //             Log.d(TAG, "步数上传成功");
        //         }
        //     }
        //     @Override
        //     public void onFailure(Call<Void> call, Throwable t) {
        //         Log.e(TAG, "步数上传失败:" + t.getMessage());
        //     }
        // });
    }
}

2. 在Manifest中注册Receiver

别忘了在AndroidManifest.xml里注册这个Receiver,确保系统能找到它:

<receiver
    android:name=".StepUpdateReceiver"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.android.gms.fitness.ACTION_DATA_AVAILABLE" />
    </intent-filter>
</receiver>

3. 注册PendingIntent到Google Fit

在你的GoogleApiClient连接成功后(比如onConnected回调里),创建PendingIntent并绑定到Recording API,这样有新步数数据时就会触发回调:

@Override
public void onConnected(@Nullable Bundle bundle) {
    super.onConnected(bundle);
    Log.d(TAG, "GoogleApiClient 连接成功");

    // 创建触发Receiver的Intent
    Intent intent = new Intent(this, StepUpdateReceiver.class);
    intent.setAction(Fitness.ACTION_DATA_AVAILABLE);
    // 根据Android版本选择合适的Flag,Android12+建议用FLAG_IMMUTABLE
    PendingIntent pendingIntent = PendingIntent.getBroadcast(
            this,
            0,
            intent,
            PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
    );

    // 订阅步数数据更新
    Fitness.RecordingApi.subscribe(mGoogleApiClient, DataType.TYPE_STEP_COUNT_DELTA)
            .setResultCallback(status -> {
                if (status.isSuccess()) {
                    if (status.getStatusCode() == FitnessStatusCodes.SUCCESS_ALREADY_SUBSCRIBED) {
                        Log.d(TAG, "已经订阅过步数更新");
                    } else {
                        Log.d(TAG, "成功订阅步数更新");
                    }
                    // 注册PendingIntent,让Google Fit在有新数据时触发
                    Fitness.RecordingApi.registerDataUpdateCallback(mGoogleApiClient, pendingIntent)
                            .setResultCallback(callbackStatus -> {
                                if (callbackStatus.isSuccess()) {
                                    Log.d(TAG, "PendingIntent 注册成功");
                                } else {
                                    Log.e(TAG, "PendingIntent 注册失败:" + callbackStatus.getMessage());
                                }
                            });
                } else {
                    Log.e(TAG, "订阅步数更新失败:" + status.getMessage());
                }
            });
}

一些关键注意事项

  • 权限处理:Android10及以上需要申请ACTIVITY_RECOGNITION权限,Android12+还要注意PendingIntent的Flag选择,避免兼容性问题。
  • ApiClient生命周期:在Receiver里初始化ApiClient后,记得在数据处理完成后断开连接,防止内存泄漏。
  • 耗时操作:如果上传服务器的逻辑比较耗时,建议在Receiver里启动WorkManager或者IntentService来处理,避免出现ANR。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:42:58