diff options
| author | 2025-09-20 12:14:21 +0200 | |
|---|---|---|
| committer | 2025-10-20 18:22:47 +0200 | |
| commit | 6727b078e75793d12fed266675f1564d763250ed (patch) | |
| tree | 682cda853361e2e08cd7d46ed6617ab04185646c | |
| parent | build: set up and check in a baseline for Lint warnings (diff) | |
| download | wireguard-android-hs/build-upgrades.tar.xz wireguard-android-hs/build-upgrades.zip | |
ui: remove use of SYSTEM_ALERT_WINDOW for QS tilehs/build-upgrades
Harsh: massage codestyle and commit message
Signed-off-by: felix <Felix.nuesse@t-online.de>
Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
| -rw-r--r-- | ui/src/main/AndroidManifest.xml | 3 | ||||
| -rw-r--r-- | ui/src/main/java/com/wireguard/android/QuickTileService.kt | 41 | ||||
| -rw-r--r-- | ui/src/main/java/com/wireguard/android/activity/TunnelToggleActivity.kt | 37 | ||||
| -rw-r--r-- | ui/src/main/res/layout/loading_activity.xml | 44 | ||||
| -rw-r--r-- | ui/src/main/res/values/strings.xml | 2 | ||||
| -rw-r--r-- | ui/src/main/res/values/styles.xml | 4 |
6 files changed, 101 insertions, 30 deletions
diff --git a/ui/src/main/AndroidManifest.xml b/ui/src/main/AndroidManifest.xml index 86c989b3..99bd23db 100644 --- a/ui/src/main/AndroidManifest.xml +++ b/ui/src/main/AndroidManifest.xml @@ -11,9 +11,6 @@ <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" /> <uses-permission - android:name="android.permission.SYSTEM_ALERT_WINDOW" - android:minSdkVersion="34" /> - <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" tools:ignore="ScopedStorage" /> diff --git a/ui/src/main/java/com/wireguard/android/QuickTileService.kt b/ui/src/main/java/com/wireguard/android/QuickTileService.kt index a849c481..ee94b055 100644 --- a/ui/src/main/java/com/wireguard/android/QuickTileService.kt +++ b/ui/src/main/java/com/wireguard/android/QuickTileService.kt @@ -4,15 +4,14 @@ */ package com.wireguard.android +import android.annotation.SuppressLint import android.app.PendingIntent import android.content.Intent import android.graphics.Bitmap import android.graphics.Canvas import android.graphics.drawable.Icon -import android.net.Uri import android.os.Build import android.os.IBinder -import android.provider.Settings import android.service.quicksettings.Tile import android.service.quicksettings.TileService import android.util.Log @@ -21,6 +20,7 @@ import androidx.databinding.Observable import androidx.databinding.Observable.OnPropertyChangedCallback import com.wireguard.android.activity.MainActivity import com.wireguard.android.activity.TunnelToggleActivity +import com.wireguard.android.activity.TunnelToggleActivity.Companion.SHOW_PROGRESS import com.wireguard.android.backend.Tunnel import com.wireguard.android.model.ObservableTunnel import com.wireguard.android.util.applicationScope @@ -52,9 +52,9 @@ class QuickTileService : TileService() { override fun onClick() { applicationScope.launch { + updateTile() if (tunnel == null) { Application.getTunnelManager().getTunnels() - updateTile() } when (val tunnel = tunnel) { null -> { @@ -64,7 +64,7 @@ class QuickTileService : TileService() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { startActivityAndCollapse(PendingIntent.getActivity(this@QuickTileService, 0, intent, PendingIntent.FLAG_IMMUTABLE)) } else { - @Suppress("DEPRECATION") + @Suppress("DEPRECATION", "StartActivityAndCollapseDeprecated") startActivityAndCollapse(intent) } } @@ -76,24 +76,15 @@ class QuickTileService : TileService() { tunnel.setStateAsync(Tunnel.State.TOGGLE) updateTile() } catch (e: Throwable) { - Log.d(TAG, "Failed to set state, so falling back", e) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE && !Settings.canDrawOverlays(this@QuickTileService)) { - Log.d(TAG, "Need overlay permissions") - val permissionIntent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:$packageName")) - permissionIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - startActivityAndCollapse( - PendingIntent.getActivity( - this@QuickTileService, - 0, - permissionIntent, - PendingIntent.FLAG_IMMUTABLE - ) - ) - return@launch + val intent = Intent(this@QuickTileService, TunnelToggleActivity::class.java) + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + intent.putExtra(SHOW_PROGRESS, true) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + startActivityAndCollapse(PendingIntent.getActivity(this@QuickTileService, 0, intent, PendingIntent.FLAG_IMMUTABLE)) + } else { + @Suppress("DEPRECATION") + startActivity(intent) } - val toggleIntent = Intent(this@QuickTileService, TunnelToggleActivity::class.java) - toggleIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - startActivity(toggleIntent) } } } @@ -149,7 +140,7 @@ class QuickTileService : TileService() { isAdded = false } - private fun updateTile() { + private fun updateTile(isConnecting: Boolean = false) { // Update the tunnel. val newTunnel = Application.getTunnelManager().lastUsedTunnel if (newTunnel != tunnel) { @@ -164,6 +155,12 @@ class QuickTileService : TileService() { null -> { tile.label = getString(R.string.app_name) tile.state = Tile.STATE_INACTIVE + if (isConnecting) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + tile.subtitle = getString(R.string.quick_settings_tile_connecting) + tile.state = Tile.STATE_ACTIVE + } + } tile.icon = iconOff } else -> { diff --git a/ui/src/main/java/com/wireguard/android/activity/TunnelToggleActivity.kt b/ui/src/main/java/com/wireguard/android/activity/TunnelToggleActivity.kt index a0e9aa06..6eb877fa 100644 --- a/ui/src/main/java/com/wireguard/android/activity/TunnelToggleActivity.kt +++ b/ui/src/main/java/com/wireguard/android/activity/TunnelToggleActivity.kt @@ -5,13 +5,13 @@ package com.wireguard.android.activity import android.content.ComponentName -import android.os.Build import android.os.Bundle +import android.os.Handler +import android.os.Looper import android.service.quicksettings.TileService import android.util.Log import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts -import androidx.annotation.RequiresApi import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.lifecycleScope import com.wireguard.android.Application @@ -23,6 +23,9 @@ import com.wireguard.android.util.ErrorMessages import kotlinx.coroutines.launch class TunnelToggleActivity : AppCompatActivity() { + + private var isVisible = false + private val permissionActivityResultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { toggleTunnelWithPermissionsResult() } @@ -37,16 +40,23 @@ class TunnelToggleActivity : AppCompatActivity() { val message = getString(R.string.toggle_error, error) Log.e(TAG, message, e) Toast.makeText(this@TunnelToggleActivity, message, Toast.LENGTH_LONG).show() - finishAffinity() + exitActivity() return@launch } TileService.requestListeningState(this@TunnelToggleActivity, ComponentName(this@TunnelToggleActivity, QuickTileService::class.java)) - finishAffinity() + exitActivity() } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + + if (intent.getBooleanExtra(SHOW_PROGRESS, false)) { + isVisible = true + title = "" // Otherwise the app title will be shown above the spinner. + setContentView(R.layout.loading_activity) + } + lifecycleScope.launch { if (Application.getBackend() is GoBackend) { try { @@ -61,9 +71,28 @@ class TunnelToggleActivity : AppCompatActivity() { } toggleTunnelWithPermissionsResult() } + exitActivity() + } + + private fun exitActivity() { + /* + We add this delay, so that the user gets the impression we are actually doing something. + This is to make the transition of the closing quick tile menu more palatable, + because startActivityAndCollapse() will immediately close that menu. + This can be jarring, so we show this placeholder spinner and close it after a second. + */ + + if (isVisible) { + Handler(Looper.getMainLooper()).postDelayed({ + finishAffinity() + }, 1000L) + } else { + finishAffinity() + } } companion object { private const val TAG = "WireGuard/TunnelToggleActivity" + const val SHOW_PROGRESS = "ShowLoadingbar" } } diff --git a/ui/src/main/res/layout/loading_activity.xml b/ui/src/main/res/layout/loading_activity.xml new file mode 100644 index 00000000..6c530f99 --- /dev/null +++ b/ui/src/main/res/layout/loading_activity.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<layout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools"> + + <androidx.constraintlayout.widget.ConstraintLayout + android:layout_width="match_parent" + android:layout_height="match_parent"> + + + <com.google.android.material.card.MaterialCardView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:checkable="true" + android:focusable="true" + app:contentPadding="32dp" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <TextView + android:id="@+id/textView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="24dp" + android:text="@string/preparing_tunnel" /> + + <ProgressBar + android:id="@+id/progressBar" + style="?android:attr/progressBarStyle" + android:layout_width="match_parent" + android:layout_height="match_parent" /> + </LinearLayout> + + </com.google.android.material.card.MaterialCardView> + + </androidx.constraintlayout.widget.ConstraintLayout> +</layout> diff --git a/ui/src/main/res/values/strings.xml b/ui/src/main/res/values/strings.xml index 32e797e6..178f131e 100644 --- a/ui/src/main/res/values/strings.xml +++ b/ui/src/main/res/values/strings.xml @@ -260,4 +260,6 @@ <string name="biometric_prompt_private_key_title">Authenticate to view private key</string> <string name="biometric_auth_error">Authentication failure</string> <string name="biometric_auth_error_reason">Authentication failure: %s</string> + <string name="quick_settings_tile_connecting">Connecting…</string> + <string name="preparing_tunnel">Preparing tunnel…</string> </resources> diff --git a/ui/src/main/res/values/styles.xml b/ui/src/main/res/values/styles.xml index 28e9fc2f..3b7bfdf6 100644 --- a/ui/src/main/res/values/styles.xml +++ b/ui/src/main/res/values/styles.xml @@ -37,9 +37,11 @@ <item name="android:windowBackground">@android:color/transparent</item> <item name="android:background">@android:color/transparent</item> <item name="colorPrimaryDark">@android:color/transparent</item> - <item name="android:backgroundDimEnabled">true</item> + <item name="android:backgroundDimEnabled">false</item> <item name="android:windowEnterAnimation">@android:anim/fade_in</item> <item name="android:windowExitAnimation">@android:anim/fade_out</item> + <item name="android:windowIsFloating">true</item> + <item name="android:colorBackgroundCacheHint">@null</item> </style> <style name="TvTheme" parent="AppTheme"> |
