diff --git a/ui/src/main/java/com/wireguard/android/QuickTileService.kt b/ui/src/main/java/com/wireguard/android/QuickTileService.kt index ed208c50..d1bad2bd 100644 --- a/ui/src/main/java/com/wireguard/android/QuickTileService.kt +++ b/ui/src/main/java/com/wireguard/android/QuickTileService.kt @@ -75,6 +75,7 @@ class QuickTileService : TileService() { } override fun onCreate() { + isAdded = true if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { iconOn = Icon.createWithResource(this, R.drawable.ic_tile) iconOff = iconOn @@ -98,6 +99,11 @@ class QuickTileService : TileService() { iconOff = Icon.createWithBitmap(b) } + override fun onDestroy() { + super.onDestroy() + isAdded = false + } + override fun onStartListening() { Application.getTunnelManager().addOnPropertyChangedCallback(onTunnelChangedCallback) if (tunnel != null) tunnel!!.addOnPropertyChangedCallback(onStateChangedCallback) @@ -109,6 +115,14 @@ class QuickTileService : TileService() { Application.getTunnelManager().removeOnPropertyChangedCallback(onTunnelChangedCallback) } + override fun onTileAdded() { + isAdded = true + } + + override fun onTileRemoved() { + isAdded = false + } + private fun updateTile() { // Update the tunnel. val newTunnel = Application.getTunnelManager().lastUsedTunnel @@ -157,5 +171,7 @@ class QuickTileService : TileService() { companion object { private const val TAG = "WireGuard/QuickTileService" + var isAdded: Boolean = false + private set } } diff --git a/ui/src/main/java/com/wireguard/android/activity/SettingsActivity.kt b/ui/src/main/java/com/wireguard/android/activity/SettingsActivity.kt index 2b1acf56..bd6e1f78 100644 --- a/ui/src/main/java/com/wireguard/android/activity/SettingsActivity.kt +++ b/ui/src/main/java/com/wireguard/android/activity/SettingsActivity.kt @@ -4,9 +4,11 @@ */ package com.wireguard.android.activity +import android.content.ComponentName import android.content.Intent import android.os.Build import android.os.Bundle +import android.service.quicksettings.TileService import android.view.MenuItem import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.commit @@ -14,6 +16,7 @@ import androidx.lifecycle.lifecycleScope import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat import com.wireguard.android.Application +import com.wireguard.android.QuickTileService import com.wireguard.android.R import com.wireguard.android.backend.WgQuickBackend import com.wireguard.android.preference.PreferencesPreferenceDataStore @@ -47,7 +50,13 @@ class SettingsActivity : AppCompatActivity() { override fun onCreatePreferences(savedInstanceState: Bundle?, key: String?) { preferenceManager.preferenceDataStore = PreferencesPreferenceDataStore(lifecycleScope, Application.getPreferencesDataStore()) addPreferencesFromResource(R.xml.preferences) - preferenceScreen.initialExpandedChildrenCount = 4 + preferenceScreen.initialExpandedChildrenCount = 5 + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU || QuickTileService.isAdded) { + val quickTile = preferenceManager.findPreference("quick_tile") + quickTile?.parent?.removePreference(quickTile) + --preferenceScreen.initialExpandedChildrenCount + } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { val darkTheme = preferenceManager.findPreference("dark_theme") darkTheme?.parent?.removePreference(darkTheme) diff --git a/ui/src/main/java/com/wireguard/android/preference/QuickTilePreference.kt b/ui/src/main/java/com/wireguard/android/preference/QuickTilePreference.kt new file mode 100644 index 00000000..9081818b --- /dev/null +++ b/ui/src/main/java/com/wireguard/android/preference/QuickTilePreference.kt @@ -0,0 +1,50 @@ +/* + * Copyright © 2017-2023 WireGuard LLC. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.wireguard.android.preference + +import android.app.StatusBarManager +import android.content.ComponentName +import android.content.Context +import android.graphics.drawable.Icon +import android.os.Build +import android.util.AttributeSet +import android.widget.Toast +import androidx.annotation.RequiresApi +import androidx.preference.Preference +import com.wireguard.android.QuickTileService +import com.wireguard.android.R + +@RequiresApi(Build.VERSION_CODES.TIRAMISU) +class QuickTilePreference(context: Context, attrs: AttributeSet?) : Preference(context, attrs) { + override fun getSummary() = context.getString(R.string.quick_settings_tile_add_summary) + + override fun getTitle() = context.getString(R.string.quick_settings_tile_add_title) + + override fun onClick() { + val statusBarManager = context.getSystemService(StatusBarManager::class.java) + statusBarManager.requestAddTileService( + ComponentName(context, QuickTileService::class.java), + context.getString(R.string.quick_settings_tile_action), + Icon.createWithResource(context, R.drawable.ic_tile), + context.mainExecutor + ) { + when (it) { + StatusBarManager.TILE_ADD_REQUEST_RESULT_TILE_ALREADY_ADDED, + StatusBarManager.TILE_ADD_REQUEST_RESULT_TILE_ADDED -> { + parent?.removePreference(this) + --preferenceManager.preferenceScreen.initialExpandedChildrenCount + } + StatusBarManager.TILE_ADD_REQUEST_ERROR_MISMATCHED_PACKAGE, + StatusBarManager.TILE_ADD_REQUEST_ERROR_REQUEST_IN_PROGRESS, + StatusBarManager.TILE_ADD_REQUEST_ERROR_BAD_COMPONENT, + StatusBarManager.TILE_ADD_REQUEST_ERROR_NOT_CURRENT_USER, + StatusBarManager.TILE_ADD_REQUEST_ERROR_APP_NOT_IN_FOREGROUND, + StatusBarManager.TILE_ADD_REQUEST_ERROR_NO_STATUS_BAR_SERVICE -> + Toast.makeText(context, context.getString(R.string.quick_settings_tile_add_failure, it), Toast.LENGTH_SHORT).show() + } + } + } +} diff --git a/ui/src/main/res/values/strings.xml b/ui/src/main/res/values/strings.xml index 7d7456bc..acaa9dcc 100644 --- a/ui/src/main/res/values/strings.xml +++ b/ui/src/main/res/values/strings.xml @@ -185,6 +185,10 @@ Private key Public key Tip: generate with `qrencode -t ansiutf8 < tunnel.conf`. + Add tile to quick settings panel + The shortcut tile toggles the most recent tunnel + Unable to add shortcut tile: error %d + Toggle tunnel Will not bring up enabled tunnels at boot Will bring up enabled tunnels at boot Restore on boot diff --git a/ui/src/main/res/xml/preferences.xml b/ui/src/main/res/xml/preferences.xml index fd3ff396..a8b66df7 100644 --- a/ui/src/main/res/xml/preferences.xml +++ b/ui/src/main/res/xml/preferences.xml @@ -12,6 +12,7 @@ android:summaryOn="@string/restore_on_boot_summary_on" android:title="@string/restore_on_boot_title" /> +