<package android:name="net.i2p.android" /> <!-- Google Play flavor. -->
<package android:name="net.i2p.android.router" /> <!-- F-Droid flavor. -->
- <!-- Orbot. -->
- <package android:name="org.torproject.android" />
+ <!-- Tor. -->
+ <package android:name="org.torproject.android" /> <!-- Orbot. -->
+ <package android:name="org.torproject.torservices" /> <!-- TorServices. -->
<!-- OpenKeyChain. -->
<package android:name="org.sufficientlysecure.keychain" />
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)))
+ }
}
}
}
/* SPDX-License-Identifier: GPL-3.0-or-later
- * SPDX-FileCopyrightText: 2019-2023 Soren Stoutner <soren@stoutner.com>
+ * SPDX-FileCopyrightText: 2019-2023, 2026 Soren Stoutner <soren@stoutner.com>
*
* This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
*
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 -> {
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
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)
// 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.
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.
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")
<!--
SPDX-License-Identifier: GPL-3.0-or-later
- SPDX-FileCopyrightText: 2016-2018, 2020, 2022-2023, 2025 Soren Stoutner <soren@stoutner.com>
+ SPDX-FileCopyrightText: 2016-2018, 2020, 2022-2023, 2025-2026 Soren Stoutner <soren@stoutner.com>
This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
android:layout_width="wrap_content"
android:textIsSelectable="true" />
+ <TextView
+ android:id="@+id/tor_services"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textIsSelectable="true" />
+
<TextView
android:id="@+id/i2p"
android:layout_height="wrap_content"
<string name="gui">Benutzer-Oberfläche</string>
<!-- Proxy. -->
- <string name="orbot_not_installed_title">Orbot ist nicht installiert</string>
- <string name="orbot_not_installed_message">Der Orbot-Proxy kann erst nach Installation der Orbot-App genutzt werden.</string>
<string name="i2p_not_installed_title">I2P ist nicht installiert</string>
<string name="i2p_not_installed_message">Der I2P-Proxy kann erst nach Installation der I2P-App genutzt werden.</string>
<string name="custom_proxy_invalid">Die benutzerdefinierte Proxy-URL ist ungültig.</string>
<string name="webview_provider">WebView-Anbieter: \u0020</string>
<string name="webview_version">WebView-Version: \u0020</string>
<string name="orbot">Orbot: \u0020</string>
+ <string name="tor_services">TorServices: \u0020</string>
<string name="i2p">I2P: \u0020</string>
<string name="fdroid_flavor">%1$s (F-Droid-Version)</string>
<string name="google_play_flavor">%1$s (Google-Play-Version)</string>
<string name="gui">Interfaz</string>
<!-- Proxy. -->
- <string name="orbot_not_installed_title">Orbot No Instalado</string>
- <string name="orbot_not_installed_message">El proxy a través de Orbot no funcionará a menos que la aplicación Orbot esté instalada.</string>
<string name="i2p_not_installed_title">I2P No Instalado</string>
<string name="i2p_not_installed_message">El proxy a través de I2P no funcionará a menos que la aplicación I2P esté instalada.</string>
<string name="custom_proxy_invalid">La URL del proxy personalizado no es válida.</string>
<string name="webview_provider">Proveedor de WebView: \u0020</string>
<string name="webview_version">Versión de WebView: \u0020</string>
<string name="orbot">Orbot: \u0020</string>
+ <string name="tor_services">TorServices: \u0020</string>
<string name="i2p">I2P: \u0020</string>
<string name="fdroid_flavor">%1$s (variante de F-Droid)</string>
<string name="google_play_flavor">%1$s (variante de Google Play)</string>
<string name="gui">Interface</string>
<!-- Proxy. -->
- <string name="orbot_not_installed_title">Orbot non installé</string>
- <string name="orbot_not_installed_message">Le proxy via Orbot ne fonctionnera que si l\'application Orbot est installée.</string>
<string name="i2p_not_installed_title">I2P non installé</string>
<string name="i2p_not_installed_message">Le proxy via I2P ne fonctionnera que si l\'application I2P est installée.</string>
<string name="custom_proxy_invalid">L\'URL du proxy personnalisé n\'est pas valide.</string>
<string name="webview_provider">Fournisseur WebView :\u0020</string>
<string name="webview_version">Version WebView :\u0020</string>
<string name="orbot">Orbot :\u0020</string>
+ <string name="tor_services">TorServices :\u0020</string>
<string name="i2p">I2P :\u0020</string>
<string name="fdroid_flavor">%1$s (Version F-Droid)</string>
<string name="google_play_flavor">%1$s (Version Google Play)</string>
<string name="gui">Interfaccia</string>
<!-- Proxy. -->
- <string name="orbot_not_installed_title">Orbot Non Installato</string>
- <string name="orbot_not_installed_message">Il Proxy con Orbot non funziona se non è installata la app Orbot.</string>
<string name="i2p_not_installed_title">I2P Non Installato</string>
<string name="i2p_not_installed_message">Il Proxy con I2P non funziona se non è installata la app I2P.</string>
<string name="custom_proxy_invalid">La URL del proxy personalizzato non è valida.</string>
<string name="webview_provider">Provider di WebView: \u0020</string>
<string name="webview_version">Versione di WebView: \u0020</string>
<string name="orbot">Orbot: \u0020</string>
+ <string name="tor_services">TorServices: \u0020</string>
<string name="i2p">I2P: \u0020</string>
<string name="fdroid_flavor">%1$s (Versione F-Droid)</string>
<string name="google_play_flavor">%1$s (Versione Google Play)</string>
<string name="gui">Interface</string>
<!-- Proxy. -->
- <string name="orbot_not_installed_title">Orbot Não Instalado</string>
- <string name="orbot_not_installed_message">O proxy através do Orbot não funcionará a menos que o aplicativo Orbot esteja instalado.</string>
- <string name="i2p_not_installed_title">I2P Não Instalado</string>
+ <string name="i2p_not_installed_title">I2P Não Instalado</string>
<string name="i2p_not_installed_message">O proxy através do I2P não funcionará a menos que o aplicativo I2P esteja instalado.</string>
<string name="custom_proxy_invalid">O URL do proxy personalizado é inválido.</string>
<string name="webview_provider">Fornecedor WebView: \u0020</string>
<string name="webview_version">Versão do WebView: \u0020</string>
<string name="orbot">Orbot: \u0020</string>
+ <string name="tor_services">TorServices: \u0020</string>
<string name="i2p">I2P: \u0020</string>
<string name="fdroid_flavor">%1$s (Derivação do F-Droid)</string>
<string name="google_play_flavor">%1$s (Derivação do Google Play)</string>
<string name="gui">Интерфейс</string>
<!-- Proxy. -->
- <string name="orbot_not_installed_title">Orbot не установлен</string>
- <string name="orbot_not_installed_message">Прокси через Orbot работать не будет, если приложение Orbot не установлено.</string>
<string name="i2p_not_installed_title">I2P не установлен</string>
<string name="i2p_not_installed_message">Прокси через I2P работать не будет, если приложение I2P не установлено.</string>
<string name="custom_proxy_invalid">URL пользовательского прокси недействителен.</string>
<string name="webview_provider">Провайдер WebView: \u0020</string>
<string name="webview_version">Версия WebView: \u0020</string>
<string name="orbot">Orbot: \u0020</string>
+ <string name="tor_services">TorServices: \u0020</string>
<string name="i2p">I2P: \u0020</string>
<string name="fdroid_flavor">%1$s (F-Droid-версия)</string>
<string name="google_play_flavor">%1$s (Google Play-версия)</string>
<string name="build">Derleme: \u0020</string>
<string name="webview_provider">WebView Sağlayıcısı: \u0020</string>
<string name="webview_version">WebView Versiyonu: \u0020</string>
- <string name="orbot">Orbot:</string>
+ <string name="orbot">Orbot: \u0020</string>
+ <string name="tor_services">TorServices: \u0020</string>
<string name="openkeychain">OpenKeychain: \u0020</string>
<string name="ultraprivacy_label">UltraPrivacy: \u0020</string>
<string name="ultralist_label">UltraList: \u0020</string>
<string name="gui">界面</string>
<!-- Proxy. -->
- <string name="orbot_not_installed_title">Orbot 未下载</string>
- <string name="orbot_not_installed_message">Orbot应用被安装Orbot才会工作.</string>
<string name="i2p_not_installed_title">I2P 未下载</string>
<string name="i2p_not_installed_message">I2P应用被安装I2P才会工作.</string>
<string name="custom_proxy_invalid">自定义代理无效.</string>
<string name="webview_provider">WebView Provider: \u0020</string>
<string name="webview_version">WebView Version: \u0020</string>
<string name="orbot">Orbot: \u0020</string>
+ <string name="tor_services">TorServices: \u0020</string>
<string name="i2p">I2P: \u0020</string>
<string name="fdroid_flavor">%1$s (F-Droid flavor)</string>
<string name="google_play_flavor">%1$s (Google Play flavor)</string>
<!-- Proxy. -->
<string name="proxy_not_installed_dialog" translatable="false">Proxy not installed dialog</string> <!-- This string is used to tag the proxy not installed dialog. It is never displayed to the user. -->
- <string name="orbot_not_installed_title">Orbot Not Installed</string>
- <string name="orbot_not_installed_message">Proxying through Orbot will not work unless the Orbot app is installed.</string>
+ <string name="orbot_or_tor_services_not_installed_title">Orbot or TorServices Not Installed</string>
+ <string name="orbot_or_tor_services_not_installed_message">Proxying through Tor will not work unless either the Orbot or TorServices app is installed.</string>
<string name="i2p_not_installed_title">I2P Not Installed</string>
<string name="i2p_not_installed_message">Proxying through I2P will not work unless the I2P app is installed.</string>
<string name="custom_proxy_invalid">The custom proxy URL is invalid.</string>
<string name="webview_provider">WebView Provider: \u0020</string>
<string name="webview_version">WebView Version: \u0020</string>
<string name="orbot">Orbot: \u0020</string>
+ <string name="tor_services">TorServices: \u0020</string>
<string name="i2p">I2P: \u0020</string>
<string name="fdroid_flavor">%1$s (F-Droid flavor)</string>
<string name="google_play_flavor">%1$s (Google Play flavor)</string>