Skip to content

Commit 8782c00

Browse files
committed
Skip Play in-app update check for non-Play installs
AndroidAppUpdate now resolves the installer package and, when it is not com.android.vending (sideloaded, adb, other stores, debug builds), short-circuits updateAvailable to NoUpdateAvailable without building the Play requestUpdateFlow() pipeline. This avoids the Play update API call and its 'update available' notification on builds that can't be updated through Play. Install source is read via getInstallSourceInfo() on API 30+ and the deprecated getInstallerPackageName() below it; any failure is treated as non-Play.
1 parent f6dbddd commit 8782c00

1 file changed

Lines changed: 22 additions & 2 deletions

File tree

util/src/androidMain/kotlin/AppUpdate.android.kt

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import com.russhwolf.settings.Settings
1919
import com.russhwolf.settings.set
2020
import coredevices.util.R
2121
import kotlinx.coroutines.GlobalScope
22+
import kotlinx.coroutines.flow.MutableStateFlow
2223
import kotlinx.coroutines.flow.SharingStarted
2324
import kotlinx.coroutines.flow.StateFlow
2425
import kotlinx.coroutines.flow.catch
@@ -42,7 +43,10 @@ class AndroidAppUpdate(
4243
) : AppUpdate {
4344
private val logger = Logger.withTag("AndroidAppUpdate")
4445

45-
override val updateAvailable: StateFlow<AppUpdateState> = appUpdateManager.requestUpdateFlow()
46+
override val updateAvailable: StateFlow<AppUpdateState> =
47+
if (isInstalledFromPlayStore()) playUpdateFlow() else MutableStateFlow(AppUpdateState.NoUpdateAvailable)
48+
49+
private fun playUpdateFlow(): StateFlow<AppUpdateState> = appUpdateManager.requestUpdateFlow()
4650
.onStart { emit(AppUpdateResult.NotAvailable) } // Emit a loading state initially
4751
.catch { exception ->
4852
Logger.w(exception) { "Failed to check for CoreApp updates" }
@@ -96,6 +100,21 @@ class AndroidAppUpdate(
96100
}
97101
}
98102

103+
private fun isInstalledFromPlayStore(): Boolean {
104+
val installer = try {
105+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
106+
context.packageManager.getInstallSourceInfo(context.packageName).installingPackageName
107+
} else {
108+
@Suppress("DEPRECATION")
109+
context.packageManager.getInstallerPackageName(context.packageName)
110+
}
111+
} catch (e: Exception) {
112+
logger.w(e) { "Failed to resolve install source" }
113+
null
114+
}
115+
return installer == PLAY_STORE_PACKAGE
116+
}
117+
99118
private fun createNotification(context: Context) {
100119
val playStoreIntent = getPlayStoreMarketIntent(context, context.packageName)
101120
if (playStoreIntent == null) {
@@ -132,7 +151,7 @@ class AndroidAppUpdate(
132151
private fun getPlayStoreMarketIntent(context: Context, packageName: String): Intent? {
133152
val marketIntent =
134153
Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=$packageName")).apply {
135-
setPackage("com.android.vending")
154+
setPackage(PLAY_STORE_PACKAGE)
136155
}
137156
return if (marketIntent.resolveActivity(context.packageManager) != null) {
138157
marketIntent
@@ -155,6 +174,7 @@ class AndroidAppUpdate(
155174

156175
companion object {
157176
const val REQUEST_CODE_APP_UPDATE = 12346
177+
private const val PLAY_STORE_PACKAGE = "com.android.vending"
158178
private const val LAST_PROMPTED_KEY = "last_prompted_app_update"
159179
private val NOTIFICATION_ALLOWED_PERIOD = 1.days
160180
private const val CHANNEL_ID = "app_update_channel"

0 commit comments

Comments
 (0)