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!