Skip to content
This repository was archived by the owner on Jul 2, 2025. It is now read-only.

Commit 964684b

Browse files
interaction between runFragment and Forestore
1 parent 849d656 commit 964684b

File tree

10 files changed

+337
-130
lines changed

10 files changed

+337
-130
lines changed

android/canonical/app/src/main/java/com/google/samples/quickstart/canonical/MainActivity.kt

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import androidx.activity.viewModels
77
import androidx.constraintlayout.widget.ConstraintLayout
88
import androidx.fragment.app.FragmentTransaction
99
import com.google.android.material.bottomnavigation.BottomNavigationView
10+
import java.lang.Exception
1011

1112
class MainActivity : AppCompatActivity() {
1213

@@ -22,36 +23,41 @@ class MainActivity : AppCompatActivity() {
2223

2324
val bottomNavigation : BottomNavigationView = findViewById(R.id.bottom_navigation_view)
2425
bottomNavigation.setOnNavigationItemSelectedListener { item ->
25-
when (item.itemId) {
26+
try {
27+
when (item.itemId) {
2628

27-
R.id.bottom_navigation_item_run -> {
28-
supportFragmentManager
29-
.beginTransaction()
30-
.replace(R.id.fragment_container, RunFragment())
31-
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
32-
.commit()
33-
true
34-
}
29+
R.id.bottom_navigation_item_run -> {
30+
supportFragmentManager
31+
.beginTransaction()
32+
.replace(R.id.fragment_container, RunFragment())
33+
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
34+
.commit()
35+
true
36+
}
3537

36-
R.id.bottom_navigation_item_map -> {
37-
supportFragmentManager
38-
.beginTransaction()
39-
.replace(R.id.fragment_container, MapsFragment())
40-
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
41-
.commit()
42-
true
43-
}
38+
R.id.bottom_navigation_item_map -> {
39+
supportFragmentManager
40+
.beginTransaction()
41+
.replace(R.id.fragment_container, MapsFragment())
42+
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
43+
.commit()
44+
true
45+
}
4446

45-
R.id.bottom_navigation_item_profile -> {
46-
supportFragmentManager
47-
.beginTransaction()
48-
.replace(R.id.fragment_container, ProfileFragment())
49-
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
50-
.commit()
51-
true
52-
}
47+
R.id.bottom_navigation_item_profile -> {
48+
supportFragmentManager
49+
.beginTransaction()
50+
.replace(R.id.fragment_container, ProfileFragment())
51+
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
52+
.commit()
53+
true
54+
}
5355

54-
else -> false
56+
else -> false
57+
}
58+
} catch (e:Exception) {
59+
Log.e(MAIN_ACTIVITY_TAG, "setOnNavigationItemSelectedListener failed", e)
60+
false
5561
}
5662
}
5763
}

android/canonical/app/src/main/java/com/google/samples/quickstart/canonical/MapsFragment.kt

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import com.google.android.libraries.places.api.model.RectangularBounds
3131
import com.google.android.libraries.places.api.net.PlacesClient
3232
import com.google.android.libraries.places.widget.AutocompleteSupportFragment
3333
import com.google.android.libraries.places.widget.listener.PlaceSelectionListener
34+
import java.lang.Exception
3435

3536
class MapsFragment : Fragment() {
3637

@@ -101,26 +102,31 @@ class MapsFragment : Fragment() {
101102

102103
fusedLocationClient.lastLocation.addOnSuccessListener { location ->
103104
// Got last known location. In some rare situations this can be null.
104-
location?.let {
105-
Log.d(FRAGMENT_TAG, "Locating Success ${location.latitude}, ${location.longitude}")
106-
lastLocation = location
107-
currentLatLng = LatLng(location.latitude, location.longitude)
108-
map.animateCamera(CameraUpdateFactory.newLatLngZoom(
109-
currentLatLng,
110-
ZOOM_VALUE
111-
))
112-
map.addMarker(MarkerOptions()
113-
.position(currentLatLng!!)
114-
.title(getString(R.string.my_location_title)))
115-
map.moveCamera(CameraUpdateFactory.newLatLngZoom(
116-
currentLatLng,
117-
ZOOM_VALUE
118-
))
119-
setPlacesSearchBias()
120-
} ?: run{
121-
Log.d(FRAGMENT_TAG, "Locating Failed")
122-
Toast.makeText(this.context, getString(R.string.cannot_access_location), Toast.LENGTH_LONG).show()
105+
try {
106+
location?.let {
107+
Log.d(FRAGMENT_TAG, "Locating Success ${location.latitude}, ${location.longitude}")
108+
lastLocation = location
109+
currentLatLng = LatLng(location.latitude, location.longitude)
110+
map.animateCamera(CameraUpdateFactory.newLatLngZoom(
111+
currentLatLng,
112+
ZOOM_VALUE
113+
))
114+
map.addMarker(MarkerOptions()
115+
.position(currentLatLng!!)
116+
.title(getString(R.string.my_location_title)))
117+
map.moveCamera(CameraUpdateFactory.newLatLngZoom(
118+
currentLatLng,
119+
ZOOM_VALUE
120+
))
121+
setPlacesSearchBias()
122+
} ?: run{
123+
Log.d(FRAGMENT_TAG, "Locating Failed")
124+
Toast.makeText(this.context, getString(R.string.cannot_access_location), Toast.LENGTH_LONG).show()
125+
}
126+
} catch (e : Exception) {
127+
Log.e(FRAGMENT_TAG, "Map generation failed", e)
123128
}
129+
124130
}
125131
}
126132

android/canonical/app/src/main/java/com/google/samples/quickstart/canonical/ProfileFragment.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ class ProfileFragment : Fragment() {
4141
}
4242
// set LifeCycle owner with MeFragment. Observe will be destroyed when MeFragment is destroyed
4343
signInVM.getFirebaseAuthLogStatusLiveData().observe(this, observer)
44-
profileVM.initAppUserStatistic()
4544
}
4645

4746
override fun onCreateView(
@@ -51,8 +50,7 @@ class ProfileFragment : Fragment() {
5150
// Inflate the layout for this fragment
5251
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_profile, container, false)
5352
binding.lifecycleOwner = this
54-
binding.userName = profileVM.getUserName()
55-
binding.userEmail = profileVM.getUserEmail()
53+
binding.profileViewModel = profileVM
5654
return binding.root
5755
}
5856

android/canonical/app/src/main/java/com/google/samples/quickstart/canonical/ProfileViewModel.kt

Lines changed: 74 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@ import android.widget.ImageView
88
import androidx.lifecycle.MutableLiveData
99
import androidx.lifecycle.ViewModel
1010
import com.google.firebase.auth.FirebaseUser
11+
import com.google.firebase.firestore.DocumentReference
12+
import com.google.firebase.firestore.FieldValue
1113
import com.google.firebase.firestore.ktx.firestore
1214
import com.google.firebase.ktx.Firebase
1315
import java.io.InputStream
1416
import java.net.URL
17+
import java.util.concurrent.TimeUnit
1518

1619

1720
class ProfileViewModel : ViewModel() {
@@ -27,11 +30,17 @@ class ProfileViewModel : ViewModel() {
2730
)
2831

2932
private lateinit var curAppUser: AppUser
33+
private var timeHMSString: MutableLiveData<String> = MutableLiveData(DEFAULT_TIME)
34+
private lateinit var runUserDocRef : DocumentReference
3035

3136
private fun getUid() : String {
3237
return curAppUser.uid
3338
}
3439

40+
private fun getTotalTimeMillisecond() : Long? {
41+
return curAppUser.totalTimeMillisecond.value
42+
}
43+
3544
private fun setTotalDistanceMeters(totalDistanceMeters : Long) {
3645
curAppUser.totalDistanceMeters.value = totalDistanceMeters
3746
}
@@ -48,6 +57,40 @@ class ProfileViewModel : ViewModel() {
4857
curAppUser.singleRunIDList.value = singleRunIDList
4958
}
5059

60+
private fun convertMStoStringHMS(millionSeconds : Long) : String {
61+
return "%02d:%02d:%02d".format(
62+
TimeUnit.MILLISECONDS.toHours(millionSeconds),
63+
TimeUnit.MILLISECONDS.toMinutes(millionSeconds) % TimeUnit.HOURS.toMinutes(1),
64+
TimeUnit.MILLISECONDS.toSeconds(millionSeconds) % TimeUnit.MINUTES.toSeconds(1)
65+
)
66+
}
67+
68+
private fun setTimeHMSString() {
69+
val ms = getTotalTimeMillisecond()
70+
val hms = ms ?.let{convertMStoStringHMS(ms)} ?: run { DEFAULT_TIME }
71+
timeHMSString.value = hms
72+
Log.d(PROFILE_VM_TAG, "setTimeHMSString hms: $hms")
73+
}
74+
75+
private fun getNewSingleRunningRecordRef(singleRunningTimeMillionSeconds : Long, time: String) {
76+
77+
}
78+
79+
private fun syncAppUserStatistic() {
80+
runUserDocRef.get()
81+
.addOnSuccessListener {document ->
82+
Log.d(PROFILE_VM_TAG, "Get doc successfully")
83+
setTotalDistanceMeters(document.data!![KEY_TOTAL_DIS_M] as Long)
84+
setTotalEnergyCalories(document.data!![KEY_TOTAL_EN_CAL] as Long)
85+
setTotalTimeMillisecond(document.data!![KEY_TOTAL_TIME_MS] as Long)
86+
setSingleRunIDList(document.data!![KEY_SINGLE_RUN_ID_LIST] as ArrayList<String>)
87+
setTimeHMSString()
88+
}
89+
.addOnFailureListener {
90+
Log.w(PROFILE_VM_TAG, "Get doc Failed")
91+
}
92+
}
93+
5194
fun getUserName() : String {
5295
return curAppUser.userName
5396
}
@@ -60,28 +103,45 @@ class ProfileViewModel : ViewModel() {
60103
return curAppUser.googleAccountProfileUrl
61104
}
62105

106+
fun getTimeHMSStringMutableLiveData() : MutableLiveData<String> {
107+
return timeHMSString
108+
}
109+
63110
fun initAppUser(curFirebaseUser : FirebaseUser) {
64111
Log.d(PROFILE_VM_TAG, "initAppUser")
65112
curAppUser = AppUser(curFirebaseUser.displayName ?: "", curFirebaseUser.email ?: "",
66113
curFirebaseUser.uid, curFirebaseUser.photoUrl.toString())
114+
runUserDocRef = Firebase.firestore.collection(USER_COLLECTION_NAME).document(getUid())
115+
syncAppUserStatistic()
67116
}
68117

69-
fun initAppUserStatistic() {
70-
val uid = getUid()
71-
val ref = Firebase.firestore.collection(USER_COLLECTION_NAME).document(uid)
72-
ref.get()
73-
.addOnSuccessListener {document ->
74-
Log.d(PROFILE_VM_TAG, "Get doc successfully")
75-
setTotalDistanceMeters(document.data!![KEY_TOTAL_DIS_M] as Long)
76-
setTotalEnergyCalories(document.data!![KEY_TOTAL_EN_CAL] as Long)
77-
setTotalTimeMillisecond(document.data!![KEY_TOTAL_TIME_MS] as Long)
78-
setSingleRunIDList(document.data!![KEY_SINGLE_RUN_ID_LIST] as ArrayList<String>)
79-
}
80-
.addOnFailureListener {
81-
Log.w(PROFILE_VM_TAG, "Get doc Failed")
118+
fun uploadNewRecord(singleRunningTimeMillionSeconds : Long, time : String) {
119+
120+
val newTotalTimeMillisecond = getTotalTimeMillisecond()?.plus(
121+
singleRunningTimeMillionSeconds
122+
)
123+
Log.d(PROFILE_VM_TAG, "newTotalTimeMillisecond $newTotalTimeMillisecond")
124+
125+
// val singleRunDocRef = Firebase.firestore.collection(RUN_COLLECTION_NAME).document()
126+
127+
Firebase.firestore.runBatch { batch ->
128+
// TODO update single run list
129+
130+
// update total time
131+
val updateRunUserData = hashMapOf(
132+
KEY_TOTAL_TIME_MS to newTotalTimeMillisecond,
133+
KEY_SINGLE_RUN_ID_LIST to FieldValue.arrayUnion("This is test")
134+
)
135+
batch.update(runUserDocRef, updateRunUserData)
136+
137+
}
138+
.addOnSuccessListener {
139+
Log.d(PROFILE_VM_TAG, "")
140+
syncAppUserStatistic()
82141
}
83142
}
84143

144+
85145
companion object {
86146
const val PROFILE_VM_TAG = "ProfileVM"
87147
const val USER_COLLECTION_NAME = "RunUser"
@@ -92,6 +152,7 @@ class ProfileViewModel : ViewModel() {
92152
const val KEY_TOTAL_EN_CAL = "TotalEnergyCalories"
93153
const val KEY_TOTAL_TIME_MS = "TotalTimeMillisecond"
94154
const val KEY_SINGLE_RUN_ID_LIST = "SingleRunIDList"
155+
const val DEFAULT_TIME = "00:00:00"
95156
}
96157
}
97158

0 commit comments

Comments
 (0)