From: Soren Stoutner Date: Thu, 7 May 2026 21:23:43 +0000 (-0700) Subject: Add support for TorServices. https://redmine.stoutner.com/issues/1324 X-Git-Url: https://gitweb.stoutner.com/?a=commitdiff_plain;h=3ae32119207f61137aa5def1a7041bb35ee40519;p=PrivacyBrowserAndroid.git Add support for TorServices. https://redmine.stoutner.com/issues/1324 --- diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 82ea7e29..f2e3cffc 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -40,8 +40,9 @@ - - + + + diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.kt b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.kt index c70b2c15..846aef5e 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.kt @@ -3602,23 +3602,28 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook if (Build.VERSION.SDK_INT < 35) window.statusBarColor = getColor(R.color.blue_background) - // Check to see if Orbot is installed. + // Check to see if Orbot or TorServices is installed. try { - // Check to see if Orbot is in the list. This will throw an error and drop to the catch section if it isn't installed. + // Check to see if Orbot is installed. This will throw an error and drop to the catch section if it isn't installed. packageManager.getPackageInfo("org.torproject.android", 0) } catch (_: PackageManager.NameNotFoundException) { // Orbot is not installed. - // Show the Orbot not installed dialog if it is not already displayed. - if (supportFragmentManager.findFragmentByTag(getString(R.string.proxy_not_installed_dialog)) == null) { - // Get a handle for the Orbot not installed alert dialog. - val orbotNotInstalledDialogFragment = ProxyNotInstalledDialog.displayDialog(proxyMode) + try { + // Check to see if TorServices is installed. This will throw an error and drop to the catch section if it isn't installed. + packageManager.getPackageInfo("org.torproject.torservices", 0) + } catch (_: PackageManager.NameNotFoundException) { // TorServices is not installed. + // Show the Orbot not installed dialog if it is not already displayed. + if (supportFragmentManager.findFragmentByTag(getString(R.string.proxy_not_installed_dialog)) == null) { + // Get a handle for the Orbot or Tor Services not installed alert dialog. + val orbotOrTorServicesNotInstalledDialogFragment = ProxyNotInstalledDialog.displayDialog(proxyMode) - // Try to show the dialog. Sometimes the window is not yet active if returning from Settings. - try { - // Display the Orbot not installed alert dialog. - orbotNotInstalledDialogFragment.show(supportFragmentManager, getString(R.string.proxy_not_installed_dialog)) - } catch (_: Exception) { - // Add the dialog to the pending dialog array list. It will be displayed in `onStart()`. - pendingDialogsArrayList.add(PendingDialogDataClass(orbotNotInstalledDialogFragment, getString(R.string.proxy_not_installed_dialog))) + // Try to show the dialog. Sometimes the window is not yet active if returning from Settings. + try { + // Display the Orbot not installed alert dialog. + orbotOrTorServicesNotInstalledDialogFragment.show(supportFragmentManager, getString(R.string.proxy_not_installed_dialog)) + } catch (_: Exception) { + // Add the dialog to the pending dialog array list. It will be displayed in `onStart()`. + pendingDialogsArrayList.add(PendingDialogDataClass(orbotOrTorServicesNotInstalledDialogFragment, getString(R.string.proxy_not_installed_dialog))) + } } } } diff --git a/app/src/main/java/com/stoutner/privacybrowser/dialogs/ProxyNotInstalledDialog.kt b/app/src/main/java/com/stoutner/privacybrowser/dialogs/ProxyNotInstalledDialog.kt index 0d9df133..f19e8b70 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/dialogs/ProxyNotInstalledDialog.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/dialogs/ProxyNotInstalledDialog.kt @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * SPDX-FileCopyrightText: 2019-2023 Soren Stoutner + * SPDX-FileCopyrightText: 2019-2023, 2026 Soren Stoutner * * This file is part of Privacy Browser Android . * @@ -67,10 +67,10 @@ class ProxyNotInstalledDialog : DialogFragment() { when (proxyMode) { ProxyHelper.TOR -> { // Set the title. - dialogBuilder.setTitle(R.string.orbot_not_installed_title) + dialogBuilder.setTitle(R.string.orbot_or_tor_services_not_installed_title) // Set the message. - dialogBuilder.setMessage(R.string.orbot_not_installed_message) + dialogBuilder.setMessage(R.string.orbot_or_tor_services_not_installed_message) } ProxyHelper.I2P -> { diff --git a/app/src/main/java/com/stoutner/privacybrowser/fragments/AboutVersionFragment.kt b/app/src/main/java/com/stoutner/privacybrowser/fragments/AboutVersionFragment.kt index cc3dcf5f..43d6c342 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/fragments/AboutVersionFragment.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/fragments/AboutVersionFragment.kt @@ -138,6 +138,7 @@ class AboutVersionFragment : Fragment() { private lateinit var systemAvailableMemoryTextView: TextView private lateinit var systemConsumedMemoryTextView: TextView private lateinit var systemTotalMemoryTextView: TextView + private lateinit var torServicesTextView: TextView private lateinit var versionTextView: TextView private lateinit var ultraListTextView: TextView private lateinit var ultraPrivacyTextView: TextView @@ -295,6 +296,7 @@ class AboutVersionFragment : Fragment() { webViewProviderTextView = aboutVersionLayout.findViewById(R.id.webview_provider) webViewVersionTextView = aboutVersionLayout.findViewById(R.id.webview_version) orbotTextView = aboutVersionLayout.findViewById(R.id.orbot) + torServicesTextView = aboutVersionLayout.findViewById(R.id.tor_services) i2pTextView = aboutVersionLayout.findViewById(R.id.i2p) openKeychainTextView = aboutVersionLayout.findViewById(R.id.open_keychain) memoryUsageTextView = aboutVersionLayout.findViewById(R.id.memory_usage) @@ -372,13 +374,22 @@ class AboutVersionFragment : Fragment() { // Get the Orbot version name if Orbot is installed. val orbot: String = try { - // If the safe call (`?.`) is null, the Elvis operator (`?"`) returns the following value instead, which is an empty string. + // If the safe call is null, the Elvis operator (`?:`) returns the following value instead, which is an empty string. requireContext().packageManager.getPackageInfo("org.torproject.android", 0).versionName ?: "" } catch (_: PackageManager.NameNotFoundException) { // Store an empty string. "" } + // Get the TorServices version name if TorServices is installed. + val torServices: String = try { + // If the safe call is null, the Elvis operator (`?:`) returns the following value instead, which is an empty string. + requireContext().packageManager.getPackageInfo("org.torproject.torservices", 0).versionName ?: "" + } catch (_: PackageManager.NameNotFoundException) { + // Store an empty string. + "" + } + // Get the I2P version name if I2P is installed. val i2p: String = try { // Check to see if the F-Droid flavor is installed. @@ -497,6 +508,24 @@ class AboutVersionFragment : Fragment() { orbotTextView.visibility = View.GONE } + // Only populate the TorServices text view if it is installed. + if (torServices.isNotEmpty()) { + // Set up the label. + val torServicesLabel = getString(R.string.tor_services) + + // Create a spannable string builder. + val torServicesStringBuilder = SpannableStringBuilder(torServicesLabel + torServices) + + // Set the span to display the TorServices version. + torServicesStringBuilder.setSpan(blueColorSpan, torServicesLabel.length, torServicesStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE) + + // Display the string in the text view. + torServicesTextView.text = torServicesStringBuilder + } else { // TorServices is not installed. + // Hide the TorServices text view. + torServicesTextView.visibility = View.GONE + } + // Only populate the I2P text view if it is installed. if (i2p.isNotEmpty()) { // Set up the label. @@ -774,6 +803,10 @@ class AboutVersionFragment : Fragment() { aboutVersionStringBuilder.append(orbotTextView.text) aboutVersionStringBuilder.append("\n") } + if (torServicesTextView.isVisible) { + aboutVersionStringBuilder.append(torServicesTextView.text) + aboutVersionStringBuilder.append("\n") + } if (i2pTextView.isVisible) { aboutVersionStringBuilder.append(i2pTextView.text) aboutVersionStringBuilder.append("\n") diff --git a/app/src/main/res/layout/about_version_scrollview.xml b/app/src/main/res/layout/about_version_scrollview.xml index 3bde58b2..6504831b 100644 --- a/app/src/main/res/layout/about_version_scrollview.xml +++ b/app/src/main/res/layout/about_version_scrollview.xml @@ -2,7 +2,7 @@ - Orbot ist nicht installiert - Der Orbot-Proxy kann erst nach Installation der Orbot-App genutzt werden. I2P ist nicht installiert Der I2P-Proxy kann erst nach Installation der I2P-App genutzt werden. Die benutzerdefinierte Proxy-URL ist ungültig. @@ -507,6 +505,7 @@ WebView-Anbieter: \u0020 WebView-Version: \u0020 Orbot: \u0020 + TorServices: \u0020 I2P: \u0020 %1$s (F-Droid-Version) %1$s (Google-Play-Version) diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 9067174d..7967a23c 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -479,8 +479,6 @@ Interfaz - Orbot No Instalado - El proxy a través de Orbot no funcionará a menos que la aplicación Orbot esté instalada. I2P No Instalado El proxy a través de I2P no funcionará a menos que la aplicación I2P esté instalada. La URL del proxy personalizado no es válida. @@ -506,6 +504,7 @@ Proveedor de WebView: \u0020 Versión de WebView: \u0020 Orbot: \u0020 + TorServices: \u0020 I2P: \u0020 %1$s (variante de F-Droid) %1$s (variante de Google Play) diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 37fc2a7f..1c54d750 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -455,8 +455,6 @@ Interface - Orbot non installé - Le proxy via Orbot ne fonctionnera que si l\'application Orbot est installée. I2P non installé Le proxy via I2P ne fonctionnera que si l\'application I2P est installée. L\'URL du proxy personnalisé n\'est pas valide. @@ -482,6 +480,7 @@ Fournisseur WebView :\u0020 Version WebView :\u0020 Orbot :\u0020 + TorServices :\u0020 I2P :\u0020 %1$s (Version F-Droid) %1$s (Version Google Play) diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 279f2a79..09e33bcf 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -478,8 +478,6 @@ Interfaccia - Orbot Non Installato - Il Proxy con Orbot non funziona se non è installata la app Orbot. I2P Non Installato Il Proxy con I2P non funziona se non è installata la app I2P. La URL del proxy personalizzato non è valida. @@ -505,6 +503,7 @@ Provider di WebView: \u0020 Versione di WebView: \u0020 Orbot: \u0020 + TorServices: \u0020 I2P: \u0020 %1$s (Versione F-Droid) %1$s (Versione Google Play) diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index d69e9cf5..b5f864f5 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -362,9 +362,7 @@ Interface - Orbot Não Instalado - O proxy através do Orbot não funcionará a menos que o aplicativo Orbot esteja instalado. - I2P Não Instalado + I2P Não Instalado O proxy através do I2P não funcionará a menos que o aplicativo I2P esteja instalado. O URL do proxy personalizado é inválido. @@ -389,6 +387,7 @@ Fornecedor WebView: \u0020 Versão do WebView: \u0020 Orbot: \u0020 + TorServices: \u0020 I2P: \u0020 %1$s (Derivação do F-Droid) %1$s (Derivação do Google Play) diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 384bf562..4baf0c5c 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -475,8 +475,6 @@ Интерфейс - Orbot не установлен - Прокси через Orbot работать не будет, если приложение Orbot не установлено. I2P не установлен Прокси через I2P работать не будет, если приложение I2P не установлено. URL пользовательского прокси недействителен. @@ -502,6 +500,7 @@ Провайдер WebView: \u0020 Версия WebView: \u0020 Orbot: \u0020 + TorServices: \u0020 I2P: \u0020 %1$s (F-Droid-версия) %1$s (Google Play-версия) diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index d07e2962..ed25d925 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -338,7 +338,8 @@ Derleme: \u0020 WebView Sağlayıcısı: \u0020 WebView Versiyonu: \u0020 - Orbot: + Orbot: \u0020 + TorServices: \u0020 OpenKeychain: \u0020 UltraPrivacy: \u0020 UltraList: \u0020 diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index d7eed555..85fa4a59 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -367,8 +367,6 @@ 界面 - Orbot 未下载 - Orbot应用被安装Orbot才会工作. I2P 未下载 I2P应用被安装I2P才会工作. 自定义代理无效. @@ -394,6 +392,7 @@ WebView Provider: \u0020 WebView Version: \u0020 Orbot: \u0020 + TorServices: \u0020 I2P: \u0020 %1$s (F-Droid flavor) %1$s (Google Play flavor) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0b76134f..3b07303c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -487,8 +487,8 @@ Proxy not installed dialog - Orbot Not Installed - Proxying through Orbot will not work unless the Orbot app is installed. + Orbot or TorServices Not Installed + Proxying through Tor will not work unless either the Orbot or TorServices app is installed. I2P Not Installed Proxying through I2P will not work unless the I2P app is installed. The custom proxy URL is invalid. @@ -514,6 +514,7 @@ WebView Provider: \u0020 WebView Version: \u0020 Orbot: \u0020 + TorServices: \u0020 I2P: \u0020 %1$s (F-Droid flavor) %1$s (Google Play flavor)