diff options
Diffstat (limited to 'ui')
18 files changed, 64 insertions, 81 deletions
diff --git a/ui/build.gradle b/ui/build.gradle index 936a95d8..26739f10 100644 --- a/ui/build.gradle +++ b/ui/build.gradle @@ -66,6 +66,7 @@ dependencies { implementation "androidx.databinding:databinding-runtime:$agpVersion" implementation "androidx.fragment:fragment-ktx:$fragmentVersion" implementation "androidx.preference:preference-ktx:$preferenceVersion" + implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycleRuntimeKtxVersion" implementation "com.github.material-components:material-components-android:$materialComponentsVersion" implementation "com.journeyapps:zxing-android-embedded:$zxingEmbeddedVersion" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion" diff --git a/ui/src/main/java/com/wireguard/android/activity/BaseActivity.kt b/ui/src/main/java/com/wireguard/android/activity/BaseActivity.kt index e663c1f2..8154624e 100644 --- a/ui/src/main/java/com/wireguard/android/activity/BaseActivity.kt +++ b/ui/src/main/java/com/wireguard/android/activity/BaseActivity.kt @@ -7,10 +7,10 @@ package com.wireguard.android.activity import android.os.Bundle import androidx.databinding.CallbackRegistry import androidx.databinding.CallbackRegistry.NotifierCallback +import androidx.lifecycle.lifecycleScope import com.wireguard.android.Application import com.wireguard.android.model.ObservableTunnel import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch /** @@ -39,7 +39,7 @@ abstract class BaseActivity : ThemeChangeAwareActivity() { else -> null } if (savedTunnelName != null) - GlobalScope.launch(Dispatchers.Main.immediate) { selectedTunnel = Application.getTunnelManager().getTunnels()[savedTunnelName] } + lifecycleScope.launch(Dispatchers.Main.immediate) { selectedTunnel = Application.getTunnelManager().getTunnels()[savedTunnelName] } // The selected tunnel must be set before the superclass method recreates fragments. super.onCreate(savedInstanceState) diff --git a/ui/src/main/java/com/wireguard/android/activity/LogViewerActivity.kt b/ui/src/main/java/com/wireguard/android/activity/LogViewerActivity.kt index e689f8ea..3408fc7b 100644 --- a/ui/src/main/java/com/wireguard/android/activity/LogViewerActivity.kt +++ b/ui/src/main/java/com/wireguard/android/activity/LogViewerActivity.kt @@ -26,6 +26,7 @@ import android.view.View import android.view.ViewGroup import androidx.appcompat.app.AppCompatActivity import androidx.core.app.ShareCompat +import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView @@ -40,10 +41,7 @@ import com.wireguard.android.widget.EdgeToEdge.setUpFAB import com.wireguard.android.widget.EdgeToEdge.setUpRoot import com.wireguard.android.widget.EdgeToEdge.setUpScrollingContent import com.wireguard.crypto.KeyPair -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.cancel import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.BufferedReader @@ -68,7 +66,6 @@ class LogViewerActivity : AppCompatActivity() { private var rawLogLines = StringBuffer() private var recyclerView: RecyclerView? = null private var saveButton: MenuItem? = null - private val logStreamingScope = CoroutineScope(Dispatchers.IO) private val year by lazy { val yearFormatter: DateFormat = SimpleDateFormat("yyyy", Locale.US) yearFormatter.format(Date()) @@ -115,7 +112,7 @@ class LogViewerActivity : AppCompatActivity() { addItemDecoration(DividerItemDecoration(context, LinearLayoutManager.VERTICAL)) } - logStreamingScope.launch { streamingLog() } + lifecycleScope.launch(Dispatchers.IO) { streamingLog() } binding.shareFab.setOnClickListener { revokeLastUri() @@ -136,7 +133,6 @@ class LogViewerActivity : AppCompatActivity() { override fun onDestroy() { super.onDestroy() - logStreamingScope.cancel() } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { @@ -159,7 +155,7 @@ class LogViewerActivity : AppCompatActivity() { true } R.id.save_log -> { - GlobalScope.launch { saveLog() } + lifecycleScope.launch(Dispatchers.IO) { saveLog() } true } else -> super.onOptionsItemSelected(item) 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 3abfe07c..de1417dd 100644 --- a/ui/src/main/java/com/wireguard/android/activity/SettingsActivity.kt +++ b/ui/src/main/java/com/wireguard/android/activity/SettingsActivity.kt @@ -12,6 +12,7 @@ import android.util.SparseArray import android.view.MenuItem import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat +import androidx.lifecycle.lifecycleScope import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat import com.wireguard.android.Application @@ -20,7 +21,6 @@ import com.wireguard.android.backend.WgQuickBackend import com.wireguard.android.util.AdminKnobs import com.wireguard.android.util.ModuleLoader import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.util.ArrayList @@ -102,7 +102,7 @@ class SettingsActivity : ThemeChangeAwareActivity() { preferenceManager.findPreference<Preference>("multiple_tunnels") ).filterNotNull() wgQuickOnlyPrefs.forEach { it.isVisible = false } - GlobalScope.launch(Dispatchers.Main.immediate) { + lifecycleScope.launch(Dispatchers.Main.immediate) { if (Application.getBackend() is WgQuickBackend) { ++preferenceScreen.initialExpandedChildrenCount wgQuickOnlyPrefs.forEach { it.isVisible = true } @@ -121,7 +121,7 @@ class SettingsActivity : ThemeChangeAwareActivity() { moduleInstaller?.parent?.removePreference(moduleInstaller) } else { kernelModuleDisabler?.parent?.removePreference(kernelModuleDisabler) - GlobalScope.launch(Dispatchers.Main.immediate) { + lifecycleScope.launch(Dispatchers.Main.immediate) { try { withContext(Dispatchers.IO) { Application.getRootShell().start() } moduleInstaller?.isVisible = true 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 004b10be..4ad1d484 100644 --- a/ui/src/main/java/com/wireguard/android/activity/TunnelToggleActivity.kt +++ b/ui/src/main/java/com/wireguard/android/activity/TunnelToggleActivity.kt @@ -12,13 +12,13 @@ import android.util.Log import android.widget.Toast import androidx.annotation.RequiresApi import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import com.wireguard.android.Application import com.wireguard.android.QuickTileService import com.wireguard.android.R import com.wireguard.android.backend.Tunnel import com.wireguard.android.util.ErrorMessages import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch @RequiresApi(Build.VERSION_CODES.N) @@ -26,7 +26,7 @@ class TunnelToggleActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val tunnel = Application.getTunnelManager().lastUsedTunnel ?: return - GlobalScope.launch(Dispatchers.Main.immediate) { + lifecycleScope.launch(Dispatchers.Main.immediate) { try { tunnel.setStateAsync(Tunnel.State.TOGGLE) } catch (e: Throwable) { diff --git a/ui/src/main/java/com/wireguard/android/fragment/AppListDialogFragment.kt b/ui/src/main/java/com/wireguard/android/fragment/AppListDialogFragment.kt index 966ba7d1..88701ec3 100644 --- a/ui/src/main/java/com/wireguard/android/fragment/AppListDialogFragment.kt +++ b/ui/src/main/java/com/wireguard/android/fragment/AppListDialogFragment.kt @@ -13,6 +13,7 @@ import androidx.appcompat.app.AlertDialog import androidx.databinding.Observable import androidx.fragment.app.DialogFragment import androidx.fragment.app.Fragment +import androidx.lifecycle.lifecycleScope import com.google.android.material.tabs.TabLayout import com.wireguard.android.BR import com.wireguard.android.R @@ -22,7 +23,6 @@ import com.wireguard.android.model.ApplicationData import com.wireguard.android.util.ErrorMessages import com.wireguard.android.util.requireTargetFragment import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -36,7 +36,7 @@ class AppListDialogFragment : DialogFragment() { private fun loadData() { val activity = activity ?: return val pm = activity.packageManager - GlobalScope.launch(Dispatchers.Default) { + lifecycleScope.launch(Dispatchers.Default) { try { val applicationData: MutableList<ApplicationData> = ArrayList() withContext(Dispatchers.IO) { diff --git a/ui/src/main/java/com/wireguard/android/fragment/BaseFragment.kt b/ui/src/main/java/com/wireguard/android/fragment/BaseFragment.kt index 997c2221..5cbfbaee 100644 --- a/ui/src/main/java/com/wireguard/android/fragment/BaseFragment.kt +++ b/ui/src/main/java/com/wireguard/android/fragment/BaseFragment.kt @@ -12,6 +12,7 @@ import android.widget.Toast import androidx.databinding.DataBindingUtil import androidx.databinding.ViewDataBinding import androidx.fragment.app.Fragment +import androidx.lifecycle.lifecycleScope import com.google.android.material.snackbar.Snackbar import com.wireguard.android.Application import com.wireguard.android.R @@ -24,7 +25,6 @@ import com.wireguard.android.databinding.TunnelListItemBinding import com.wireguard.android.model.ObservableTunnel import com.wireguard.android.util.ErrorMessages import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch /** @@ -72,7 +72,7 @@ abstract class BaseFragment : Fragment(), OnSelectedTunnelChangedListener { is TunnelListItemBinding -> binding.item else -> return } ?: return - GlobalScope.launch(Dispatchers.Main.immediate) { + lifecycleScope.launch(Dispatchers.Main.immediate) { if (Application.getBackend() is GoBackend) { val intent = GoBackend.VpnService.prepare(view.context) if (intent != null) { @@ -87,7 +87,7 @@ abstract class BaseFragment : Fragment(), OnSelectedTunnelChangedListener { } private fun setTunnelStateWithPermissionsResult(tunnel: ObservableTunnel, checked: Boolean) { - GlobalScope.launch(Dispatchers.Main.immediate) { + lifecycleScope.launch(Dispatchers.Main.immediate) { try { tunnel.setStateAsync(Tunnel.State.of(checked)) } catch (e: Throwable) { diff --git a/ui/src/main/java/com/wireguard/android/fragment/ConfigNamingDialogFragment.kt b/ui/src/main/java/com/wireguard/android/fragment/ConfigNamingDialogFragment.kt index 12406df2..6f9ff560 100644 --- a/ui/src/main/java/com/wireguard/android/fragment/ConfigNamingDialogFragment.kt +++ b/ui/src/main/java/com/wireguard/android/fragment/ConfigNamingDialogFragment.kt @@ -11,13 +11,13 @@ import android.os.Bundle import android.view.inputmethod.InputMethodManager import androidx.appcompat.app.AlertDialog import androidx.fragment.app.DialogFragment +import androidx.lifecycle.lifecycleScope import com.wireguard.android.Application import com.wireguard.android.R import com.wireguard.android.databinding.ConfigNamingDialogFragmentBinding import com.wireguard.config.BadConfigException import com.wireguard.config.Config import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import java.io.ByteArrayInputStream import java.io.IOException @@ -31,7 +31,7 @@ class ConfigNamingDialogFragment : DialogFragment() { private fun createTunnelAndDismiss() { binding?.let { val name = it.tunnelNameText.text.toString() - GlobalScope.launch(Dispatchers.Main.immediate) { + lifecycleScope.launch(Dispatchers.Main.immediate) { try { Application.getTunnelManager().create(name, config) dismiss() diff --git a/ui/src/main/java/com/wireguard/android/fragment/TunnelDetailFragment.kt b/ui/src/main/java/com/wireguard/android/fragment/TunnelDetailFragment.kt index e81b4e6d..fa0dbf82 100644 --- a/ui/src/main/java/com/wireguard/android/fragment/TunnelDetailFragment.kt +++ b/ui/src/main/java/com/wireguard/android/fragment/TunnelDetailFragment.kt @@ -11,6 +11,7 @@ import android.view.MenuInflater import android.view.View import android.view.ViewGroup import androidx.databinding.DataBindingUtil +import androidx.lifecycle.lifecycleScope import com.wireguard.android.R import com.wireguard.android.backend.Tunnel import com.wireguard.android.databinding.TunnelDetailFragmentBinding @@ -19,7 +20,6 @@ import com.wireguard.android.model.ObservableTunnel import com.wireguard.android.widget.EdgeToEdge.setUpRoot import com.wireguard.android.widget.EdgeToEdge.setUpScrollingContent import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import java.util.Timer import java.util.TimerTask @@ -82,7 +82,7 @@ class TunnelDetailFragment : BaseFragment() { override fun onSelectedTunnelChanged(oldTunnel: ObservableTunnel?, newTunnel: ObservableTunnel?) { binding ?: return binding!!.tunnel = newTunnel - if (newTunnel == null) binding!!.config = null else GlobalScope.launch(Dispatchers.Main.immediate) { + if (newTunnel == null) binding!!.config = null else lifecycleScope.launch(Dispatchers.Main.immediate) { try { binding!!.config = newTunnel.getConfigAsync() } catch (_: Throwable) { @@ -114,7 +114,7 @@ class TunnelDetailFragment : BaseFragment() { val state = tunnel.state if (state != Tunnel.State.UP && lastState == state) return lastState = state - GlobalScope.launch(Dispatchers.Main.immediate) { + lifecycleScope.launch(Dispatchers.Main.immediate) { try { val statistics = tunnel.getStatisticsAsync() for (i in 0 until binding!!.peersLayout.childCount) { diff --git a/ui/src/main/java/com/wireguard/android/fragment/TunnelEditorFragment.kt b/ui/src/main/java/com/wireguard/android/fragment/TunnelEditorFragment.kt index 5b556bc2..7b987c50 100644 --- a/ui/src/main/java/com/wireguard/android/fragment/TunnelEditorFragment.kt +++ b/ui/src/main/java/com/wireguard/android/fragment/TunnelEditorFragment.kt @@ -18,6 +18,7 @@ import android.view.WindowManager import android.view.inputmethod.InputMethodManager import android.widget.EditText import android.widget.Toast +import androidx.lifecycle.lifecycleScope import com.google.android.material.snackbar.Snackbar import com.wireguard.android.Application import com.wireguard.android.R @@ -33,7 +34,6 @@ import com.wireguard.android.widget.EdgeToEdge.setUpRoot import com.wireguard.android.widget.EdgeToEdge.setUpScrollingContent import com.wireguard.config.Config import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch /** @@ -141,7 +141,7 @@ class TunnelEditorFragment : BaseFragment(), AppSelectionListener { Snackbar.make(binding!!.mainContainer, error, Snackbar.LENGTH_LONG).show() return false } - GlobalScope.launch(Dispatchers.Main.immediate) { + lifecycleScope.launch(Dispatchers.Main.immediate) { when { tunnel == null -> { Log.d(TAG, "Attempting to create new tunnel " + binding!!.name) @@ -205,7 +205,7 @@ class TunnelEditorFragment : BaseFragment(), AppSelectionListener { binding!!.config = ConfigProxy() if (tunnel != null) { binding!!.name = tunnel!!.name - GlobalScope.launch(Dispatchers.Main.immediate) { + lifecycleScope.launch(Dispatchers.Main.immediate) { try { onConfigLoaded(tunnel!!.getConfigAsync()) } catch (_: Throwable) { @@ -242,7 +242,7 @@ class TunnelEditorFragment : BaseFragment(), AppSelectionListener { Log.d(TAG, message) // Now save the rest of configuration changes. Log.d(TAG, "Attempting to save config of renamed tunnel " + tunnel!!.name) - GlobalScope.launch(Dispatchers.Main.immediate) { + lifecycleScope.launch(Dispatchers.Main.immediate) { try { renamedTunnel.setConfigAsync(newConfig) onConfigSaved(renamedTunnel, null) diff --git a/ui/src/main/java/com/wireguard/android/fragment/TunnelListFragment.kt b/ui/src/main/java/com/wireguard/android/fragment/TunnelListFragment.kt index db2fcd77..16f632fa 100644 --- a/ui/src/main/java/com/wireguard/android/fragment/TunnelListFragment.kt +++ b/ui/src/main/java/com/wireguard/android/fragment/TunnelListFragment.kt @@ -21,6 +21,7 @@ import android.view.animation.Animation import android.view.animation.AnimationUtils import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.view.ActionMode +import androidx.lifecycle.lifecycleScope import com.google.android.material.snackbar.Snackbar import com.google.zxing.integration.android.IntentIntegrator import com.wireguard.android.Application @@ -38,7 +39,6 @@ import com.wireguard.android.widget.MultiselectableRelativeLayout import com.wireguard.config.Config import kotlinx.coroutines.Deferred import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll @@ -74,7 +74,7 @@ class TunnelListFragment : BaseFragment() { } private fun importTunnel(uri: Uri?) { - GlobalScope.launch(Dispatchers.Main.immediate) { + lifecycleScope.launch(Dispatchers.Main.immediate) { withContext(Dispatchers.IO) { val activity = activity if (activity == null || uri == null) { @@ -221,7 +221,7 @@ class TunnelListFragment : BaseFragment() { override fun onSelectedTunnelChanged(oldTunnel: ObservableTunnel?, newTunnel: ObservableTunnel?) { binding ?: return - GlobalScope.launch(Dispatchers.Main) { + lifecycleScope.launch(Dispatchers.Main) { val tunnels = Application.getTunnelManager().getTunnels() if (newTunnel != null) viewForTunnel(newTunnel, tunnels).setSingleSelected(true) if (oldTunnel != null) viewForTunnel(oldTunnel, tunnels).setSingleSelected(false) @@ -264,7 +264,7 @@ class TunnelListFragment : BaseFragment() { super.onViewStateRestored(savedInstanceState) binding ?: return binding!!.fragment = this - GlobalScope.launch(Dispatchers.Main.immediate) { binding!!.tunnels = Application.getTunnelManager().getTunnels() } + lifecycleScope.launch(Dispatchers.Main.immediate) { binding!!.tunnels = Application.getTunnelManager().getTunnels() } binding!!.rowConfigurationHandler = object : RowConfigurationHandler<TunnelListItemBinding, ObservableTunnel> { override fun onConfigureRow(binding: TunnelListItemBinding, item: ObservableTunnel, position: Int) { binding.fragment = this@TunnelListFragment @@ -316,7 +316,7 @@ class TunnelListFragment : BaseFragment() { scaleX = 1f scaleY = 1f } - GlobalScope.launch(Dispatchers.Main.immediate) { + lifecycleScope.launch(Dispatchers.Main.immediate) { try { val tunnels = Application.getTunnelManager().getTunnels() val tunnelsToDelete = ArrayList<ObservableTunnel>() @@ -332,7 +332,7 @@ class TunnelListFragment : BaseFragment() { true } R.id.menu_action_select_all -> { - GlobalScope.launch(Dispatchers.Main.immediate) { + lifecycleScope.launch(Dispatchers.Main.immediate) { val tunnels = Application.getTunnelManager().getTunnels() for (i in 0 until tunnels.size) { setItemChecked(i, true) diff --git a/ui/src/main/java/com/wireguard/android/preference/KernelModuleDisablerPreference.kt b/ui/src/main/java/com/wireguard/android/preference/KernelModuleDisablerPreference.kt index 6c289073..ad93efaa 100644 --- a/ui/src/main/java/com/wireguard/android/preference/KernelModuleDisablerPreference.kt +++ b/ui/src/main/java/com/wireguard/android/preference/KernelModuleDisablerPreference.kt @@ -15,8 +15,8 @@ import com.wireguard.android.R import com.wireguard.android.activity.SettingsActivity import com.wireguard.android.backend.Tunnel import com.wireguard.android.backend.WgQuickBackend +import com.wireguard.android.util.lifecycleScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll @@ -28,7 +28,7 @@ class KernelModuleDisablerPreference(context: Context, attrs: AttributeSet?) : P private var state = State.UNKNOWN init { isVisible = false - GlobalScope.launch(Dispatchers.Main.immediate) { + lifecycleScope.launch(Dispatchers.Main.immediate) { setState(if (Application.getBackend() is WgQuickBackend) State.ENABLED else State.DISABLED) } } @@ -46,7 +46,7 @@ class KernelModuleDisablerPreference(context: Context, attrs: AttributeSet?) : P setState(State.DISABLING) Application.getSharedPreferences().edit().putBoolean("disable_kernel_module", true).commit() } - GlobalScope.launch(Dispatchers.Main.immediate) { + lifecycleScope.launch(Dispatchers.Main.immediate) { val observableTunnels = Application.getTunnelManager().getTunnels() val downings = observableTunnels.map { async(SupervisorJob()) { it.setStateAsync(Tunnel.State.DOWN) } } try { diff --git a/ui/src/main/java/com/wireguard/android/preference/ModuleDownloaderPreference.kt b/ui/src/main/java/com/wireguard/android/preference/ModuleDownloaderPreference.kt index 6960733c..bf562c53 100644 --- a/ui/src/main/java/com/wireguard/android/preference/ModuleDownloaderPreference.kt +++ b/ui/src/main/java/com/wireguard/android/preference/ModuleDownloaderPreference.kt @@ -15,8 +15,8 @@ import com.wireguard.android.Application import com.wireguard.android.R import com.wireguard.android.activity.SettingsActivity import com.wireguard.android.util.ErrorMessages +import com.wireguard.android.util.lifecycleScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import kotlin.system.exitProcess @@ -30,21 +30,19 @@ class ModuleDownloaderPreference(context: Context, attrs: AttributeSet?) : Prefe @SuppressLint("ApplySharedPref") override fun onClick() { setState(State.WORKING) - GlobalScope.launch(Dispatchers.Main.immediate) { + lifecycleScope.launch(Dispatchers.Main.immediate) { try { when (withContext(Dispatchers.IO) { Application.getModuleLoader().download() }) { OsConstants.ENOENT -> setState(State.NOTFOUND) OsConstants.EXIT_SUCCESS -> { setState(State.SUCCESS) Application.getSharedPreferences().edit().remove("disable_kernel_module").commit() - GlobalScope.launch(Dispatchers.Main.immediate) { - withContext(Dispatchers.IO) { - val restartIntent = Intent(context, SettingsActivity::class.java) - restartIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) - restartIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - Application.get().startActivity(restartIntent) - exitProcess(0) - } + withContext(Dispatchers.IO) { + val restartIntent = Intent(context, SettingsActivity::class.java) + restartIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) + restartIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + Application.get().startActivity(restartIntent) + exitProcess(0) } } else -> setState(State.FAILURE) diff --git a/ui/src/main/java/com/wireguard/android/preference/ToolsInstallerPreference.kt b/ui/src/main/java/com/wireguard/android/preference/ToolsInstallerPreference.kt index f9edb6e1..42359df0 100644 --- a/ui/src/main/java/com/wireguard/android/preference/ToolsInstallerPreference.kt +++ b/ui/src/main/java/com/wireguard/android/preference/ToolsInstallerPreference.kt @@ -10,8 +10,8 @@ import androidx.preference.Preference import com.wireguard.android.Application import com.wireguard.android.R import com.wireguard.android.util.ToolsInstaller +import com.wireguard.android.util.lifecycleScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -27,7 +27,7 @@ class ToolsInstallerPreference(context: Context, attrs: AttributeSet?) : Prefere override fun onAttached() { super.onAttached() - GlobalScope.launch(Dispatchers.Main.immediate) { + lifecycleScope.launch(Dispatchers.Main.immediate) { try { val state = withContext(Dispatchers.IO) { Application.getToolsInstaller().areInstalled() } when { @@ -45,7 +45,7 @@ class ToolsInstallerPreference(context: Context, attrs: AttributeSet?) : Prefere override fun onClick() { setState(State.WORKING) - GlobalScope.launch(Dispatchers.Main.immediate) { + lifecycleScope.launch(Dispatchers.Main.immediate) { try { val result = withContext(Dispatchers.IO) { Application.getToolsInstaller().install() } when { diff --git a/ui/src/main/java/com/wireguard/android/preference/VersionPreference.kt b/ui/src/main/java/com/wireguard/android/preference/VersionPreference.kt index e3eb0f95..18d818f6 100644 --- a/ui/src/main/java/com/wireguard/android/preference/VersionPreference.kt +++ b/ui/src/main/java/com/wireguard/android/preference/VersionPreference.kt @@ -16,8 +16,8 @@ import com.wireguard.android.R import com.wireguard.android.backend.Backend import com.wireguard.android.backend.GoBackend import com.wireguard.android.backend.WgQuickBackend +import com.wireguard.android.util.lifecycleScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.util.Locale @@ -47,7 +47,7 @@ class VersionPreference(context: Context, attrs: AttributeSet?) : Preference(con } init { - GlobalScope.launch(Dispatchers.Main.immediate) { + lifecycleScope.launch(Dispatchers.Main.immediate) { val backend = Application.getBackend() versionSummary = getContext().getString(R.string.version_summary_checking, getBackendPrettyName(context, backend).toLowerCase(Locale.ENGLISH)) notifyChanged() diff --git a/ui/src/main/java/com/wireguard/android/preference/ZipExporterPreference.kt b/ui/src/main/java/com/wireguard/android/preference/ZipExporterPreference.kt index c1eaa9f6..8a9a4724 100644 --- a/ui/src/main/java/com/wireguard/android/preference/ZipExporterPreference.kt +++ b/ui/src/main/java/com/wireguard/android/preference/ZipExporterPreference.kt @@ -17,9 +17,9 @@ import com.wireguard.android.util.AdminKnobs import com.wireguard.android.util.BiometricAuthenticator import com.wireguard.android.util.DownloadsFileSaver import com.wireguard.android.util.ErrorMessages -import com.wireguard.android.util.FragmentUtils +import com.wireguard.android.util.activity +import com.wireguard.android.util.lifecycleScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll @@ -35,7 +35,7 @@ import java.util.zip.ZipOutputStream class ZipExporterPreference(context: Context, attrs: AttributeSet?) : Preference(context, attrs) { private var exportedFilePath: String? = null private fun exportZip() { - GlobalScope.launch(Dispatchers.Main.immediate) { + lifecycleScope.launch(Dispatchers.Main.immediate) { val tunnels = Application.getTunnelManager().getTunnels() try { exportedFilePath = withContext(Dispatchers.IO) { @@ -64,7 +64,7 @@ class ZipExporterPreference(context: Context, attrs: AttributeSet?) : Preference val message = context.getString(R.string.zip_export_error, error) Log.e(TAG, message, e) Snackbar.make( - FragmentUtils.getPrefActivity(this@ZipExporterPreference).findViewById(android.R.id.content), + activity.findViewById(android.R.id.content), message, Snackbar.LENGTH_LONG).show() isEnabled = true } @@ -77,13 +77,12 @@ class ZipExporterPreference(context: Context, attrs: AttributeSet?) : Preference override fun onClick() { if (AdminKnobs.disableConfigExport) return - val prefActivity = FragmentUtils.getPrefActivity(this) - val fragment = prefActivity.supportFragmentManager.fragments.first() + val fragment = activity.supportFragmentManager.fragments.first() BiometricAuthenticator.authenticate(R.string.biometric_prompt_zip_exporter_title, fragment) { when (it) { // When we have successful authentication, or when there is no biometric hardware available. is BiometricAuthenticator.Result.Success, is BiometricAuthenticator.Result.HardwareUnavailableOrDisabled -> { - prefActivity.ensurePermissions(arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { _, grantResults -> + activity.ensurePermissions(arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { _, grantResults -> if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { isEnabled = false exportZip() @@ -92,7 +91,7 @@ class ZipExporterPreference(context: Context, attrs: AttributeSet?) : Preference } is BiometricAuthenticator.Result.Failure -> { Snackbar.make( - prefActivity.findViewById(android.R.id.content), + activity.findViewById(android.R.id.content), it.message, Snackbar.LENGTH_SHORT ).show() diff --git a/ui/src/main/java/com/wireguard/android/util/Extensions.kt b/ui/src/main/java/com/wireguard/android/util/Extensions.kt index a705401f..9106ec77 100644 --- a/ui/src/main/java/com/wireguard/android/util/Extensions.kt +++ b/ui/src/main/java/com/wireguard/android/util/Extensions.kt @@ -9,6 +9,10 @@ import android.content.Context import android.util.TypedValue import androidx.annotation.AttrRes import androidx.fragment.app.Fragment +import androidx.lifecycle.lifecycleScope +import androidx.preference.Preference +import com.wireguard.android.activity.SettingsActivity +import kotlinx.coroutines.CoroutineScope fun Context.resolveAttribute(@AttrRes attrRes: Int): Int { val typedValue = TypedValue() @@ -19,3 +23,9 @@ fun Context.resolveAttribute(@AttrRes attrRes: Int): Int { fun Fragment.requireTargetFragment(): Fragment { return requireNotNull(targetFragment) { "A target fragment should always be set for $this" } } + +val Preference.activity: SettingsActivity + get() = if (this.context is SettingsActivity) this.context as SettingsActivity else throw IllegalStateException("Failed to resolve SettingsActivity") + +val Preference.lifecycleScope: CoroutineScope + get() = this.activity.lifecycleScope diff --git a/ui/src/main/java/com/wireguard/android/util/FragmentUtils.kt b/ui/src/main/java/com/wireguard/android/util/FragmentUtils.kt deleted file mode 100644 index 90e7ab0c..00000000 --- a/ui/src/main/java/com/wireguard/android/util/FragmentUtils.kt +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright © 2017-2019 WireGuard LLC. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 - */ -package com.wireguard.android.util - -import android.view.ContextThemeWrapper -import androidx.preference.Preference -import com.wireguard.android.activity.SettingsActivity - -object FragmentUtils { - fun getPrefActivity(preference: Preference): SettingsActivity { - val context = preference.context - if (context is ContextThemeWrapper) { - if (context is SettingsActivity) { - return context - } - } - throw IllegalStateException("Failed to resolve SettingsActivity") - } -} |