summaryrefslogtreecommitdiffhomepage
path: root/ui
diff options
context:
space:
mode:
Diffstat (limited to 'ui')
-rw-r--r--ui/build.gradle.kts4
-rw-r--r--ui/src/googleplay/AndroidManifest.xml8
-rw-r--r--ui/src/main/java/com/wireguard/android/updater/SnackbarUpdateShower.kt29
-rw-r--r--ui/src/main/java/com/wireguard/android/updater/Updater.kt29
-rw-r--r--ui/src/main/res/values/strings.xml2
5 files changed, 65 insertions, 7 deletions
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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools">
+
+ <uses-permission
+ android:name="android.permission.REQUEST_INSTALL_PACKAGES"
+ tools:node="remove" />
+</manifest>
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<Snackbar>() {
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>(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 @@
<string name="updater_download_progress_nototal">Downloading update: %s</string>
<string name="updater_installing">Installing update…</string>
<string name="updater_failure">Update failure: %s. Will retry momentarily…</string>
+ <string name="updater_corrupt">This application is corrupt. Please re-download it.</string>
+ <string name="updater_corrupt_navigate">Open Website</string>
<string name="version_summary">%1$s backend %2$s</string>
<string name="version_summary_checking">Checking %s backend version</string>
<string name="version_summary_unknown">Unknown %s version</string>