如何利用Google Fitness API访问智能手表心率传感器?
Hey there! I’ve been in your exact shoes before—trying to skip the massive PPG/DSP learning curve when you’re short on time, so Google Fitness API is totally the right shortcut here. Let’s walk through a clear, step-by-step guide to get you connected to the heart rate sensor and pulling data in no time.
Before writing any code, you need to set up your project in the Google Cloud Console:
- Create a new project (or use your existing Android Studio project’s ID)
- Search for and enable the Google Fitness API
- Go to "Credentials" > "Create Credentials" > "OAuth client ID"
- Select "Android" as the application type, then enter your app’s package name and SHA-1 fingerprint (you can get this from Android Studio’s "Signing Report" tab)
- Download the
google-services.jsonfile and drop it into your app module’s root directory
Update your project files to link the API:
- Add dependencies to your module-level
build.gradle(use the latest version available):implementation 'com.google.android.gms:play-services-fitness:21.1.0' implementation 'com.google.android.gms:play-services-auth:20.7.0' - Add permissions to your
AndroidManifest.xml(critical for accessing sensors and fitness data):<uses-permission android:name="android.permission.BODY_SENSORS" /> <uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" /> - Add Google Play Services meta-data inside the
<application>tag:<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
Google Fitness requires explicit user permission to access health data. Here’s how to handle that:
private const val REQUEST_OAUTH = 1001 fun requestFitnessPermissions(context: Context, activity: Activity) { val fitnessOptions = FitnessOptions.builder() .addDataType(DataType.TYPE_HEART_RATE_BPM, FitnessOptions.ACCESS_READ) // Add WRITE if you want to save data to Google Fit's cloud .addDataType(DataType.TYPE_HEART_RATE_BPM, FitnessOptions.ACCESS_WRITE) .build() val account = GoogleSignIn.getLastSignedInAccount(context) if (account == null) { // No signed-in account—prompt user to sign in with Google GoogleSignIn.getClient(context, GoogleSignInOptions.DEFAULT_SIGN_IN) .signInIntent.let { activity.startActivityForResult(it, REQUEST_OAUTH) } } else if (!GoogleSignIn.hasPermissions(account, fitnessOptions)) { // Request missing permissions GoogleSignIn.requestPermissions( activity, REQUEST_OAUTH, account, fitnessOptions ) } else { // Already authorized—start pulling heart rate data startHeartRateStreaming(context, account) } } // Handle permission result (use ActivityResultContracts if using modern Android) override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == REQUEST_OAUTH && resultCode == Activity.RESULT_OK) { val account = GoogleSignIn.getLastSignedInAccount(this) account?.let { startHeartRateStreaming(this, it) } } }
Once authorized, use the SensorsClient to get live heart rate readings from the watch’s sensor:
private lateinit var heartRateListener: OnDataPointListener fun startHeartRateStreaming(context: Context, account: GoogleSignInAccount) { val sensorsClient = Fitness.getSensorsClient(context, account) heartRateListener = OnDataPointListener { dataPoint -> // Extract heart rate value from the data point for (field in dataPoint.dataType.fields) { val bpm = dataPoint.getValue(field).asFloat() // Do whatever you need here—update your UI, queue data for cloud upload, etc. Log.d("HeartRate", "Current BPM: $bpm") } } val sensorRequest = SensorRequest.builder() .setDataType(DataType.TYPE_HEART_RATE_BPM) .setSamplingRate(1, TimeUnit.SECONDS) // Adjust based on your needs (1s is standard) .build() sensorsClient.add(sensorRequest, heartRateListener) .addOnCompleteListener { task -> if (task.isSuccessful) { Log.d("FitnessAPI", "Heart rate listener registered successfully") } else { Log.e("FitnessAPI", "Failed to register listener", task.exception) } } } // Don't forget to clean up the listener when you're done (e.g., in onPause) fun stopHeartRateStreaming(context: Context, account: GoogleSignInAccount) { val sensorsClient = Fitness.getSensorsClient(context, account) sensorsClient.remove(heartRateListener) .addOnCompleteListener { task -> if (task.isSuccessful) { Log.d("FitnessAPI", "Heart rate listener removed") } } }
Once you have the BPM value, sending it to your own cloud backend is straightforward. Use Retrofit or OkHttp to make a POST request. Here’s a quick Retrofit example:
- Define an interface for your API:
interface HeartRateApi { @POST("/api/heart-rate") suspend fun uploadHeartRate(@Body heartRateData: HeartRateData): Response<Unit> } data class HeartRateData(val bpm: Float, val timestamp: Long, val userId: String) - Initialize Retrofit and send the data:
val retrofit = Retrofit.Builder() .baseUrl("https://your-cloud-endpoint.com") .addConverterFactory(GsonConverterFactory.create()) .build() val api = retrofit.create(HeartRateApi::class.java) // Call this when you have a new BPM reading CoroutineScope(Dispatchers.IO).launch { try { val response = api.uploadHeartRate( HeartRateData( bpm = currentBpm, timestamp = System.currentTimeMillis(), userId = "user-id-here" ) ) if (response.isSuccessful) { Log.d("CloudUpload", "Heart rate data uploaded successfully") } } catch (e: Exception) { Log.e("CloudUpload", "Upload failed", e) } }
- On Wear OS devices, the
BODY_SENSORSpermission needs to be granted manually by the user—prompt them to enable it in settings if your app can’t access the sensor. - Test on an actual Wear OS watch instead of an emulator, since emulators often don’t simulate heart rate sensors accurately.
- If you need historical heart rate data (not just real-time), use the
HistoryClientinstead ofSensorsClientto query past readings.
内容的提问来源于stack exchange,提问作者MKR125

