Skip to content

Commit 7a76c5c

Browse files
committed
Merge branch 'github/master'
2 parents 69e7a10 + ce22be5 commit 7a76c5c

2 files changed

Lines changed: 51 additions & 18 deletions

File tree

PlayCoreKtx/app/src/main/java/com/google/android/samples/dynamicfeatures/state/UpdateViewModel.kt

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import androidx.lifecycle.ViewModel
2121
import androidx.lifecycle.ViewModelProvider
2222
import androidx.lifecycle.asLiveData
2323
import androidx.lifecycle.viewModelScope
24+
import com.google.android.play.core.appupdate.AppUpdateInfo
2425
import com.google.android.play.core.appupdate.AppUpdateManager
2526
import com.google.android.play.core.ktx.AppUpdateResult
2627
import com.google.android.play.core.ktx.clientVersionStalenessDays
@@ -34,20 +35,32 @@ import kotlinx.coroutines.channels.BroadcastChannel
3435
import kotlinx.coroutines.channels.Channel
3536
import kotlinx.coroutines.flow.asFlow
3637
import kotlinx.coroutines.flow.catch
38+
import kotlinx.coroutines.flow.onEach
3739
import kotlinx.coroutines.launch
3840

3941
/**
4042
* ViewModel for InAppUpdates.
4143
*/
4244
@OptIn(ExperimentalCoroutinesApi::class, FlowPreview::class)
4345
class UpdateViewModel @Keep constructor(manager: AppUpdateManager) : ViewModel() {
44-
val updateStatus = manager.requestUpdateFlow().catch {
45-
_events.send(Event.ToastEvent("Update info not available"))
46-
}.asLiveData()
46+
val updateStatus = manager.requestUpdateFlow()
47+
.catch {
48+
_events.send(Event.ToastEvent("Update info not available"))
49+
}
50+
.asLiveData()
4751

4852
private val _events = BroadcastChannel<Event>(Channel.BUFFERED)
4953
val events = _events.asFlow()
5054

55+
fun shouldLaunchImmediateUpdate(updateInfo: AppUpdateInfo): Boolean {
56+
with(updateInfo) {
57+
return isImmediateUpdateAllowed
58+
&&
59+
(clientVersionStalenessDays ?: 0 > 30
60+
|| updatePriority > 4)
61+
}
62+
}
63+
5164
fun invokeUpdate() {
5265
when (val updateResult = updateStatus.value) {
5366
AppUpdateResult.NotAvailable -> viewModelScope.launch {
@@ -56,20 +69,20 @@ class UpdateViewModel @Keep constructor(manager: AppUpdateManager) : ViewModel()
5669
is AppUpdateResult.Available -> {
5770
with(updateResult.updateInfo) {
5871
Log.d(TAG, "Update priority: $updatePriority")
59-
if (isImmediateUpdateAllowed
60-
&&
61-
(clientVersionStalenessDays ?: 0 > 7
62-
|| updatePriority > 4)
63-
) {
64-
viewModelScope.launch {
65-
_events.send(Event.StartUpdateEvent(updateResult.updateInfo, true))
72+
when {
73+
shouldLaunchImmediateUpdate(this) -> {
74+
viewModelScope.launch {
75+
_events.send(Event.StartUpdateEvent(updateResult.updateInfo, true))
76+
}
77+
}
78+
isFlexibleUpdateAllowed -> {
79+
viewModelScope.launch {
80+
_events.send(Event.StartUpdateEvent(updateResult.updateInfo, false))
81+
}
6682
}
67-
} else if (isFlexibleUpdateAllowed) {
68-
viewModelScope.launch {
69-
_events.send(Event.StartUpdateEvent(updateResult.updateInfo, false))
83+
else -> {
84+
throw IllegalStateException("Not implemented: Handling for $this")
7085
}
71-
} else {
72-
throw IllegalStateException("Not implemented: Handling for $this")
7386
}
7487
}
7588
}

PlayCoreKtx/app/src/main/java/com/google/android/samples/dynamicfeatures/ui/MainFragment.kt

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import androidx.fragment.app.activityViewModels
2828
import androidx.fragment.app.viewModels
2929
import androidx.lifecycle.Observer
3030
import androidx.lifecycle.lifecycleScope
31+
import androidx.lifecycle.viewModelScope
3132
import com.google.android.material.snackbar.Snackbar
3233
import com.google.android.play.core.appupdate.AppUpdateManager
3334
import com.google.android.play.core.appupdate.AppUpdateManagerFactory
@@ -63,6 +64,7 @@ import kotlinx.coroutines.flow.collect
6364
import kotlinx.coroutines.flow.drop
6465
import kotlinx.coroutines.flow.launchIn
6566
import kotlinx.coroutines.flow.onEach
67+
import kotlinx.coroutines.launch
6668

6769
@OptIn(ExperimentalCoroutinesApi::class)
6870
@Keep
@@ -184,9 +186,27 @@ class MainFragment : Fragment(R.layout.fragment_main) {
184186
private fun addUpdateViewModelObservers() {
185187
with(updateViewModel) {
186188
updateStatus.observe(
187-
viewLifecycleOwner, Observer { updateResult: AppUpdateResult ->
188-
updateUpdateButton(updateResult)
189-
})
189+
viewLifecycleOwner,
190+
{ updateResult: AppUpdateResult ->
191+
updateUpdateButton(updateResult)
192+
193+
// If it's an immediate update, launch it immediately and finish Activity
194+
// to prevent the user from using the app until they update.
195+
if (updateResult is Available) {
196+
if (shouldLaunchImmediateUpdate(updateResult.updateInfo)) {
197+
if (appUpdateManager.startUpdateFlowForResult(
198+
updateResult.updateInfo,
199+
AppUpdateType.IMMEDIATE,
200+
this@MainFragment,
201+
UPDATE_CONFIRMATION_REQ_CODE
202+
)) {
203+
// only exit if update flow really started
204+
requireActivity().finish()
205+
}
206+
}
207+
}
208+
}
209+
)
190210
events.onEach { event ->
191211
when (event) {
192212
is Event.ToastEvent -> toastAndLog(event.message)

0 commit comments

Comments
 (0)