From 4156b83b841eb920217f6a3a0da1c6513ca9491e Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Wed, 10 May 2023 18:34:21 +0200 Subject: [PATCH] ui: bifurcate only parts of release but nag about wrong context Signed-off-by: Jason A. Donenfeld --- ui/build.gradle.kts | 4 +++ ui/src/googleplay/AndroidManifest.xml | 8 +++++ .../android/updater/SnackbarUpdateShower.kt | 29 +++++++++++++++---- .../com/wireguard/android/updater/Updater.kt | 29 ++++++++++++++++++- ui/src/main/res/values/strings.xml | 2 ++ 5 files changed, 65 insertions(+), 7 deletions(-) create mode 100644 ui/src/googleplay/AndroidManifest.xml diff --git a/ui/build.gradle.kts b/ui/build.gradle.kts index 178fda60..94cdf746 100644 --- a/ui/build.gradle.kts +++ b/ui/build.gradle.kts @@ -49,6 +49,10 @@ android { applicationIdSuffix = ".debug" versionNameSuffix = "-debug" } + create("googleplay") { + initWith(getByName("release")) + matchingFallbacks += "release" + } } lint { disable += "LongLogTag" diff --git a/ui/src/googleplay/AndroidManifest.xml b/ui/src/googleplay/AndroidManifest.xml new file mode 100644 index 00000000..6d64f732 --- /dev/null +++ b/ui/src/googleplay/AndroidManifest.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/ui/src/main/java/com/wireguard/android/updater/SnackbarUpdateShower.kt b/ui/src/main/java/com/wireguard/android/updater/SnackbarUpdateShower.kt index b566a0cf..8c1a8124 100644 --- a/ui/src/main/java/com/wireguard/android/updater/SnackbarUpdateShower.kt +++ b/ui/src/main/java/com/wireguard/android/updater/SnackbarUpdateShower.kt @@ -5,7 +5,10 @@ package com.wireguard.android.updater +import android.content.Intent +import android.net.Uri import android.view.View +import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope @@ -27,10 +30,11 @@ class SnackbarUpdateShower(private val fragment: Fragment) { } private class SwapableSnackbar(fragment: Fragment, view: View, anchor: View?) { - val actionSnackbar = makeSnackbar(fragment, view, anchor) - val statusSnackbar = makeSnackbar(fragment, view, anchor) - var showingAction: Boolean = false - var showingStatus: Boolean = false + private val actionSnackbar = makeSnackbar(fragment, view, anchor) + private val statusSnackbar = makeSnackbar(fragment, view, anchor) + private var showingAction: Boolean = false + private var showingStatus: Boolean = false + private var permanentAction: Boolean = false private fun makeSnackbar(fragment: Fragment, view: View, anchor: View?): Snackbar { val snackbar = Snackbar.make(fragment.requireContext(), view, "", Snackbar.LENGTH_INDEFINITE) @@ -45,7 +49,7 @@ class SnackbarUpdateShower(private val fragment: Fragment) { snackbar.addCallback(object : BaseTransientBottomBar.BaseCallback() { override fun onDismissed(snackbar: Snackbar?, @DismissEvent event: Int) { super.onDismissed(snackbar, event) - if (event == DISMISS_EVENT_MANUAL || event == DISMISS_EVENT_ACTION || + if (event == DISMISS_EVENT_MANUAL || (event == DISMISS_EVENT_ACTION && !permanentAction) || (snackbar == actionSnackbar && !showingAction) || (snackbar == statusSnackbar && !showingStatus) ) return @@ -58,11 +62,12 @@ class SnackbarUpdateShower(private val fragment: Fragment) { return snackbar } - fun showAction(text: String, action: String, listener: View.OnClickListener) { + fun showAction(text: String, action: String, permanent: Boolean = false, listener: View.OnClickListener) { if (showingStatus) { showingStatus = false statusSnackbar.dismiss() } + permanentAction = permanent actionSnackbar.setText(text) actionSnackbar.setAction(action, listener) if (!showingAction) { @@ -141,6 +146,18 @@ class SnackbarUpdateShower(private val fragment: Fragment) { delay(5.seconds) progress.retry() } + + is Updater.Progress.Corrupt -> { + snackbar.showAction(context.getString(R.string.updater_corrupt), context.getString(R.string.updater_corrupt_navigate), true) { + val intent = Intent(Intent.ACTION_VIEW) + intent.data = Uri.parse(progress.downloadUrl) + try { + context.startActivity(intent) + } catch (e: Throwable) { + Toast.makeText(context, ErrorMessages[e], Toast.LENGTH_SHORT).show() + } + } + } } }.launchIn(fragment.lifecycleScope) } diff --git a/ui/src/main/java/com/wireguard/android/updater/Updater.kt b/ui/src/main/java/com/wireguard/android/updater/Updater.kt index fabfae92..928028fd 100644 --- a/ui/src/main/java/com/wireguard/android/updater/Updater.kt +++ b/ui/src/main/java/com/wireguard/android/updater/Updater.kt @@ -4,12 +4,14 @@ */ package com.wireguard.android.updater +import android.Manifest import android.app.PendingIntent import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter import android.content.pm.PackageInstaller +import android.content.pm.PackageManager import android.os.Build import android.util.Base64 import android.util.Log @@ -116,6 +118,11 @@ object Updater { } } } + + class Corrupt(private val betterFile: String?) : Progress() { + val downloadUrl: String + get() = UPDATE_URL_FMT.format(betterFile ?: "") + } } private val mutableState = MutableStateFlow(Progress.Complete) @@ -357,9 +364,29 @@ object Updater { } fun monitorForUpdates() { - if (installerIsGooglePlay(Application.get())) + val context = Application.get() + + if (installerIsGooglePlay(context)) return + if (!if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { + @Suppress("DEPRECATION") + context.packageManager.getPackageInfo(context.packageName, PackageManager.GET_PERMISSIONS) + } else { + context.packageManager.getPackageInfo(context.packageName, PackageManager.PackageInfoFlags.of(PackageManager.GET_PERMISSIONS.toLong())) + }.requestedPermissions.contains(Manifest.permission.REQUEST_INSTALL_PACKAGES) + ) { + updaterScope.launch { + val update = try { + checkForUpdates() + } catch (_: Throwable) { + null + } + emitProgress(Progress.Corrupt(update?.fileName)) + } + return + } + updaterScope.launch { if (UserKnobs.updaterNewerVersionSeen.firstOrNull()?.let { Version(it) > CURRENT_VERSION } == true) return@launch diff --git a/ui/src/main/res/values/strings.xml b/ui/src/main/res/values/strings.xml index 66e35c98..7d7456bc 100644 --- a/ui/src/main/res/values/strings.xml +++ b/ui/src/main/res/values/strings.xml @@ -236,6 +236,8 @@ Downloading update: %s Installing update… Update failure: %s. Will retry momentarily… + This application is corrupt. Please re-download it. + Open Website %1$s backend %2$s Checking %s backend version Unknown %s version