Ask for the home role after the launcher has finished resuming; keep failed background checks quiet

First run (PRD SI-1)
- The request to become the default home app never appeared. Started from onResume, it
  was still pending when the launcher finished resuming, and Quickstep cancels any
  pending request at that point. It now starts from onDeferredResumed, after that
  check, through Launcher3's own ApiWrapper.assignDefaultHomeRole.

Updater
- An automatic check that fails (phone offline, say) no longer leaves "couldn't reach
  the update server" on the About screen. The screen keeps what it showed before, and
  the check runs again in an hour. A check started by hand still reports the failure.

Checked on the Android 17 emulator with the 0.2.0 release build made before this commit:
swipe up and hold in gesture and in three-button navigation, the list darkening under
a wave that reaches in from the right edge, and the work profile tabs. The two changes
in this commit are not yet checked.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
This commit is contained in:
TMCandClaude Fable 5.2 committed 2026-11-11 23:35:14 +01:00
1 parent 9d444ae2d0
commit f92276da15
3 files changed
+21 -17

No files matched your search

+10 -10
View File
@@ -5,15 +5,15 @@ import android.app.role.RoleManager
import android.content.Context
import android.os.Build
import android.util.Log
import com.android.launcher3.LauncherConstants
import com.android.launcher3.util.ApiWrapper
/**
* First-run step (PRD SI-1): the first time the launcher is opened while another app is the
* phone's home app, ask Android to offer Flexera Launcher as the default.
*
* Android shows its own dialog for this, listing the installed home apps. It is asked once only.
* If the owner declines, the launcher's settings keep showing a reminder that leads to the same
* choice, so there is no need to ask again.
* Android shows its own dialog for this. It is asked once only. If the owner declines, Launcher3
* shows a short hint about Android's settings, and the launcher's own settings keep a reminder
* that leads to the same choice, so there is no need to ask again.
*/
object FlexeraFirstRun {
@@ -22,12 +22,10 @@ object FlexeraFirstRun {
private const val KEY_ASKED_DEFAULT_HOME = "asked_default_home"
/**
* Launcher3's own request code for this role request. Its result handler shows a short hint
* about Android's settings when the owner declines.
* Call once the launcher has finished resuming (its onDeferredResumed), not earlier: the
* launcher cancels any request for a result that is pending at that point. Does nothing
* after the first time.
*/
private const val REQUEST_DEFAULT_HOME = LauncherConstants.ActivityCodes.REQUEST_HOME_ROLE
/** Call when the launcher comes to the front. Does nothing after the first time. */
@JvmStatic
fun askToBecomeDefaultHome(activity: Activity) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) return
@@ -40,7 +38,9 @@ object FlexeraFirstRun {
if (roles.isRoleHeld(RoleManager.ROLE_HOME)) return
try {
activity.startActivityForResult(roles.createRequestRoleIntent(RoleManager.ROLE_HOME), REQUEST_DEFAULT_HOME)
// Launcher3's own way of asking: Android's consent dialog, then a short hint about
// Android's settings if the owner declines.
ApiWrapper.INSTANCE.get(activity).assignDefaultHomeRole(activity)
} catch (e: Exception) {
Log.w(TAG, "Could not ask to become the default home app", e)
}
@@ -188,8 +188,9 @@ object FlexeraUpdater {
val release = result.getOrElse { error ->
Log.w(TAG, "Update check failed", error)
// A failed background check must not wipe out an update that is already waiting.
mutableState.value = if (automatic && before.holdsRelease()) before else UpdateState.Failed(UpdateFailure.CHECK)
// A background check that fails stays quiet: the About screen keeps what it showed
// before, including an update that is already waiting. It tries again in an hour.
mutableState.value = if (automatic) before else UpdateState.Failed(UpdateFailure.CHECK)
return@launch
}
@@ -301,9 +302,6 @@ object FlexeraUpdater {
private fun isBusy(): Boolean =
mutableState.value.let { it is UpdateState.Checking || it is UpdateState.Downloading }
private fun UpdateState.holdsRelease(): Boolean =
this is UpdateState.Available || this is UpdateState.ReadyToInstall
/** Returns the latest published release, or null when nothing has been published yet. */
private fun fetchLatestRelease(context: Context): FlexeraRelease? {
val connection = open(context, LATEST_RELEASE_URL)
@@ -469,10 +469,16 @@ class LawnchairLauncher : QuickstepLauncher() {
return ActivityOptionsWrapper(options, callback)
}
override fun onDeferredResumed() {
super.onDeferredResumed()
// Flexera Launcher: on first run, ask to become the default home app (PRD SI-1). It has
// to wait until here. Quickstep cancels any request for a result that is already pending
// when the launcher finishes resuming, which is what the call above does.
app.flexera.FlexeraFirstRun.askToBecomeDefaultHome(this)
}
override fun onResume() {
super.onResume()
// Flexera Launcher: on first run, ask to become the default home app (PRD SI-1).
app.flexera.FlexeraFirstRun.askToBecomeDefaultHome(this)
restartIfPending()
refreshPredictionContainersFromModel()