0

I am using Google Fit API for a class project and I have never used this API before. I am using Android Studio to create an app where it can start walking sessions and record the distance that the user traveled during the session. Using the Google Fit API documentation I also used a RecordingClient to subscribe to distance data during the session. Below is my code, I suspect that I am querying for the data incorrectly. And I am aware that some functions may be deprecated, but I am unsure if that could be the issue too or what to replace it with if it is.

Code Snippet:

class ActivityLogFragment : Fragment() {
    private lateinit var thiscontext: Context

    private var _binding: FragmentActivityLogBinding? = null

    // This property is only valid between onCreateView and
    // onDestroyView.
    private val binding get() = _binding!!
    private var inSession: Boolean = false
    private var startTime: Long = 0
    private var endTime: Long = 0
    private var sessionName = ""
    lateinit var session: Session
    private var distance = 0.0


    private val fitnessOptions = FitnessOptions.builder()
        .addDataType(DataType.TYPE_DISTANCE_DELTA, FitnessOptions.ACCESS_WRITE)
        .addDataType(DataType.TYPE_DISTANCE_DELTA, FitnessOptions.ACCESS_READ)
        .build()


    @RequiresApi(Build.VERSION_CODES.Q)
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        thiscontext = container!!.context
        val dashboardViewModel =
            ViewModelProvider(this)[ActivityLogViewModel::class.java]

        _binding = FragmentActivityLogBinding.inflate(inflater, container, false)

        if (!GoogleSignIn.hasPermissions(GoogleSignIn.getAccountForExtension(requireContext(), fitnessOptions), fitnessOptions)) {
            GoogleSignIn.requestPermissions(
                requireActivity(), // your activity
                1, // e.g. 1
                GoogleSignIn.getAccountForExtension(requireContext(), fitnessOptions),
                fitnessOptions)
        }

        val sessionButton: Button = binding.sessionButton
        sessionButton.setOnClickListener {
            if (!inSession) {
                inSession = true
                sessionButton.text = "End Activity Session"
                sessionManager()
            }
            else {
                inSession = false
                sessionButton.text = "Start Activity Session"
                sessionManager()
            }
        }
        // Remember add this line

        return binding.root
    }

    @SuppressLint("SimpleDateFormat")
    private fun sessionManager() {

        // Initialize session
        distance = 0.0

        if (inSession) {

            // Make toast message that activity session has started
            Toast.makeText(context, "Activity session started!", Toast.LENGTH_SHORT).show()

            // Set Session Name to current day and time
            val sdf = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US)
            sessionName = "Activity Session ${sdf.format(Date())}"

            // Start time is the current time
            startTime = System.currentTimeMillis()

            // Create unique random ID for the session
            val sessionId = UUID.randomUUID().toString()

            // Build a new session
            session = Session.Builder()
                .setName(sessionName)
                .setIdentifier(sessionId)
                .setDescription("Walk")
                .setActivity(FitnessActivities.WALKING)
                .setStartTime(startTime, TimeUnit.MILLISECONDS)
                .build()

            // Subscribe to distance data (start recording distance data)
            Fitness.getRecordingClient(requireContext(), GoogleSignIn.getAccountForExtension(requireActivity(), fitnessOptions))
                .subscribe(DataType.TYPE_DISTANCE_DELTA)
                .addOnSuccessListener {
                    Log.i(TAG, "Successfully Subscribed!")
                }
                .addOnFailureListener {e ->
                    Log.w(TAG, "There was a problem subscribing", e)
                }

            // Log the session identifier for testing purposes
            Log.w(TAG, "Session Identifier: ${session.identifier}")

            // Start the Session
            Fitness.getSessionsClient(requireContext(), GoogleSignIn.getAccountForExtension(requireActivity(), fitnessOptions))
                .startSession(session)
                .addOnSuccessListener {
                    Log.i(TAG, "Session started successfully!")
                    Log.i(TAG, "Session Identifier: ${session.identifier}") // Logging the session identifier again
                }
                .addOnFailureListener { e ->
                    Log.w(TAG, "There was an error starting the session", e)
                }
        } else { // If user is ending the session

            // Make notification that the activity session has ended
            Toast.makeText(context, "Activity session ended!", Toast.LENGTH_SHORT).show()
            val dbHelper = ActivityDbHelper(thiscontext)

            // Invoke the SessionsClient to stop the session
            Fitness.getSessionsClient(requireContext(), GoogleSignIn.getAccountForExtension(requireActivity(), fitnessOptions))
                .stopSession(session.identifier) // Stopping the session
                .addOnSuccessListener {
                    Log.i(TAG, "Session stopped successfully!")

                    // Using record client to stop recording distance data
                    Fitness.getRecordingClient(
                        requireContext(),
                        GoogleSignIn.getAccountForExtension(requireActivity(), fitnessOptions)
                    )
                        .unsubscribe(DataType.TYPE_DISTANCE_DELTA) // Stop recording distance data
                        .addOnSuccessListener {
                            Log.i(TAG, "Successfully unsubscribed.")

                            // Creating a session read request
                            val readRequest = SessionReadRequest.Builder()
                                .setSessionId(session.identifier)
                                .setTimeInterval(
                                    session.getStartTime(TimeUnit.MILLISECONDS),
                                    System.currentTimeMillis(),
                                    TimeUnit.MILLISECONDS
                                )
                                .read(DataType.TYPE_DISTANCE_DELTA)
                                .build()

                            // Getting the session client to read the session data
                            Fitness.getSessionsClient(
                                requireContext(),
                                GoogleSignIn.getAccountForExtension(
                                    requireActivity(),
                                    fitnessOptions
                                )
                            )
                                .readSession(readRequest) // Reading session data
                                .addOnSuccessListener { response ->
                                    val sessions = response.sessions
                                    Log.i(TAG, "Number of returned sessions is: ${sessions.size}") // Logging the number of returned sessions (should be 1)

                                    // Start querying for distance data (where I believe issue is)
                                    for (session in sessions) {
                                        val dataSets = response.getDataSet(session)
                                        for (dataSet in dataSets) {
                                            for (dp in dataSet.dataPoints) {
                                                for (field in dp.dataType.fields) {
                                                    val fieldValue = dp.getValue(field)
                                                    distance += fieldValue.asFloat().toDouble()
                                                }
                                            }
                                        }
                                        Log.i(TAG, "Distance: $distance") // Logging the distance user traveled
                                    }

                                } .addOnFailureListener {e ->
                                    Log.w(TAG, "Failed to read Session", e)
                                }

                        }
                        .addOnFailureListener { e ->
                            Log.w(TAG, "Failed to unsubscribe.")
                            // Retry the unsubscribe request.
                        }
                }
                .addOnFailureListener { e ->
                    Log.w(TAG, "There was an error stopping the session", e)
                }

            // Get the time
            endTime = System.currentTimeMillis()
            val tDelta: Long = endTime - startTime
            val elapsedSeconds: Double = (tDelta / 1000.0) / 60
            val formattedMinutes = String.format("%.2f", elapsedSeconds)

            // Get the date
            val calendar: Calendar = Calendar.getInstance()
            val dateFormat = SimpleDateFormat("yyyy-MM-dd")
            val currentDate: String = dateFormat.format(calendar.time)

            // Add session info to the database
            dbHelper.insertData(distance.toString(), currentDate, formattedMinutes)
            //createFromDb()
        }
    }

I get all success logs for starting/ending session as well as subscribing/unsubscribing from data. I also get a "Number of returned sessions is: 1" log but when I try to log the distance after query it returns as 0.0. Thank you for your help!

Tay M
  • 1

0 Answers0