Google Fit API SleepSession returns empty sleep sessions array Kotlin

1k Views Asked by At

I'm trying to read sleep data from Google Fit. The sessionsClient reads from Fit successfully, however, it does not return any sessions in response.sessions even though there are sleep sessions logged in Fit. Due to the API update being relatively recent, I am unable to find any resources online to resolve this so any suggestions would be appreciated.

The response returns this:

SessionReadResult{status=Status{statusCode=SUCCESS, resolution=null}, sessions=[], sessionDataSets=[]}

I followed the updated documentation from https://developers.google.com/fit/scenarios/read-sleep-data#android

Here is the sleep data logged in Fit:

enter image description here

And the code used:

        //Sets the start time to the month previous so data is got from then
        val endTime = LocalDateTime.now().atZone(ZoneId.systemDefault())
        val startTime = endTime.minusMonths(1)

        //Sleep session request
        val request = SessionReadRequest.Builder()
            .readSessionsFromAllApps()
            .includeSleepSessions()
            .read(DataType.TYPE_SLEEP_SEGMENT)
            .enableServerQueries()
            .setTimeInterval(startTime.toEpochSecond(), endTime.toEpochSecond(), TimeUnit.MILLISECONDS)
            .build()

        //Set fitnessOptions
        val fitnessOptions = FitnessOptions.builder()
            .accessSleepSessions(FitnessOptions.ACCESS_READ)
            .addDataType(DataType.TYPE_SLEEP_SEGMENT, FitnessOptions.ACCESS_READ)
            .build()

        //Get permissions from user
        if (!GoogleSignIn.hasPermissions(GoogleSignIn.getLastSignedInAccount(this), fitnessOptions)) {
            GoogleSignIn.requestPermissions(
                this,
                RC_REQUEST_SLEEP_AND_CONTINUE_SUBSCRIPTION,
                GoogleSignIn.getLastSignedInAccount(this),
                fitnessOptions);
        }

        //Make read request and process response
        getSessionsClient(this, GoogleSignIn.getAccountForExtension(this, fitnessOptions))
            .readSession(request)
            .addOnSuccessListener { response ->
                Log.i(TAG, "Read Success")

                for (session in response.sessions) {
                    val sessionStart = session.getStartTime(TimeUnit.MILLISECONDS)
                    val sessionEnd = session.getEndTime(TimeUnit.MILLISECONDS)
                    Log.i(TAG, "Sleep between $sessionStart and $sessionEnd")

                    // If the sleep session has finer granularity sub-components, extract them:
                    val dataSets = response.getDataSet(session)
                    for (dataSet in dataSets) {
                        for (point in dataSet.dataPoints) {
                            val sleepStageVal = point.getValue(Field.FIELD_SLEEP_SEGMENT_TYPE).asInt()
                            val sleepStage = SLEEP_STAGE_NAMES[sleepStageVal]
                            val segmentStart = point.getStartTime(TimeUnit.MILLISECONDS)
                            val segmentEnd = point.getEndTime(TimeUnit.MILLISECONDS)
                            Log.i(TAG, "\t* Type $sleepStage between $segmentStart and $segmentEnd")
                        }
                    }
                }
                setBarChartValues(pTime)
            }
            .addOnFailureListener { e ->
                Log.i(TAG, "Failure Response: ", e)
            }
    }
3

There are 3 best solutions below

0
On

I have resolved this by using the sample project from Google found here: https://github.com/android/fit-samples/blob/main/SleepKotlin/app/src/main/java/com/google/android/gms/fit/samples/basicsleepkotlin/MainActivity.kt

It has a lot more code/steps than described in the documentation, especially regarding the new sleep permissions.

0
On

You are passing date time in seconds but you have specified that is in milliseconds.

Replace

.setTimeInterval(startTime.toEpochSecond(), endTime.toEpochSecond(), TimeUnit.MILLISECONDS)

with

.setTimeInterval(startTime.toEpochSecond(), endTime.toEpochSecond(), TimeUnit.SECONDS)
0
On

Faced the same issue lately, Here's the tip which worked for me -> Make sure you are using a real device in which Google fit app is running (tracking the data) to debug/test your app instead of an emulator.

If you are using an emulator it's gonna return nothing in response.session even though if sessions are there.