X-Git-Url: https://gitweb.stoutner.com/?a=blobdiff_plain;f=app%2Fsrc%2Fmain%2Fjava%2Fcom%2Fstoutner%2Fprivacybrowser%2Ffragments%2FAboutVersionFragment.kt;h=7dfeda99553fd10c2e77d6ba3122417cbd014c2c;hb=HEAD;hp=7fb52dac7c364597213315d6f8d19bc33766e401;hpb=9861d180b24c06317c6f42e50d759144528ee69d;p=PrivacyBrowserAndroid.git 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 7fb52dac..163e41d1 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/fragments/AboutVersionFragment.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/fragments/AboutVersionFragment.kt @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2022 Soren Stoutner . + * Copyright 2016-2024 Soren Stoutner . * * This file is part of Privacy Browser Android . * @@ -27,7 +27,6 @@ import android.content.ClipboardManager import android.content.Context import android.content.Intent import android.content.pm.PackageManager -import android.net.Uri import android.os.Build import android.os.Bundle import android.os.Handler @@ -47,13 +46,17 @@ import android.widget.TextView import androidx.activity.result.contract.ActivityResultContracts import androidx.fragment.app.Fragment -import androidx.webkit.WebViewCompat import com.google.android.material.snackbar.Snackbar -import com.stoutner.privacybrowser.R import com.stoutner.privacybrowser.BuildConfig -import com.stoutner.privacybrowser.asynctasks.SaveAboutVersionImage +import com.stoutner.privacybrowser.R +import com.stoutner.privacybrowser.coroutines.SaveAboutVersionImageCoroutine + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.ByteArrayInputStream import java.io.InputStream @@ -68,7 +71,8 @@ import java.text.NumberFormat import kotlin.text.StringBuilder // Define the class constants. -private const val BLOCKLIST_VERSIONS = "blocklist_versions" +private const val FILTERLISTS_VERSIONS = "A" +private const val SCROLL_Y = "B" private const val MEBIBYTE = 1048576 class AboutVersionFragment : Fragment() { @@ -76,72 +80,72 @@ class AboutVersionFragment : Fragment() { private var updateMemoryUsageBoolean = true // Declare the class variables. - private lateinit var blocklistVersions: Array private lateinit var aboutVersionLayout: View - private lateinit var appConsumedMemoryLabel: String + private lateinit var activityManager: ActivityManager private lateinit var appAvailableMemoryLabel: String - private lateinit var appTotalMemoryLabel: String + private lateinit var appConsumedMemoryLabel: String private lateinit var appMaximumMemoryLabel: String - private lateinit var systemConsumedMemoryLabel: String - private lateinit var systemAvailableMemoryLabel: String - private lateinit var systemTotalMemoryLabel: String - private lateinit var runtime: Runtime - private lateinit var activityManager: ActivityManager + private lateinit var appTotalMemoryLabel: String + private lateinit var blueColorSpan: ForegroundColorSpan + private lateinit var filterListsVersions: Array private lateinit var memoryInfo: ActivityManager.MemoryInfo private lateinit var numberFormat: NumberFormat - private lateinit var blueColorSpan: ForegroundColorSpan + private lateinit var runtime: Runtime + private lateinit var systemAvailableMemoryLabel: String + private lateinit var systemConsumedMemoryLabel: String + private lateinit var systemTotalMemoryLabel: String // Declare the class views. - private lateinit var privacyBrowserTextView: TextView - private lateinit var versionTextView: TextView - private lateinit var hardwareTextView: TextView - private lateinit var brandTextView: TextView - private lateinit var manufacturerTextView: TextView - private lateinit var modelTextView: TextView - private lateinit var deviceTextView: TextView - private lateinit var bootloaderTextView: TextView - private lateinit var radioTextView: TextView - private lateinit var softwareTextView: TextView private lateinit var androidTextView: TextView - private lateinit var securityPatchTextView: TextView - private lateinit var buildTextView: TextView - private lateinit var kernelTextView: TextView - private lateinit var webViewProviderTextView: TextView - private lateinit var webViewVersionTextView: TextView - private lateinit var orbotTextView: TextView - private lateinit var i2pTextView: TextView - private lateinit var openKeychainTextView: TextView - private lateinit var memoryUsageTextView: TextView - private lateinit var appConsumedMemoryTextView: TextView private lateinit var appAvailableMemoryTextView: TextView - private lateinit var appTotalMemoryTextView: TextView + private lateinit var appConsumedMemoryTextView: TextView private lateinit var appMaximumMemoryTextView: TextView - private lateinit var systemConsumedMemoryTextView: TextView - private lateinit var systemAvailableMemoryTextView: TextView - private lateinit var systemTotalMemoryTextView: TextView - private lateinit var blocklistsTextView: TextView + private lateinit var appTotalMemoryTextView: TextView + private lateinit var brandTextView: TextView + private lateinit var bootloaderTextView: TextView + private lateinit var certificateEndDateTextView: TextView + private lateinit var certificateIssuerDnTextView: TextView + private lateinit var certificateSerialNumberTextView: TextView + private lateinit var certificateSignatureAlgorithmTextView: TextView + private lateinit var certificateStartDateTextView: TextView + private lateinit var certificateSubjectDnTextView: TextView + private lateinit var certificateVersionTextView: TextView + private lateinit var buildTextView: TextView + private lateinit var deviceTextView: TextView private lateinit var easyListTextView: TextView private lateinit var easyPrivacyTextView: TextView private lateinit var fanboyAnnoyanceTextView: TextView private lateinit var fanboySocialTextView: TextView + private lateinit var filterListsTextView: TextView + private lateinit var hardwareTextView: TextView + private lateinit var i2pTextView: TextView + private lateinit var kernelTextView: TextView + private lateinit var manufacturerTextView: TextView + private lateinit var memoryUsageTextView: TextView + private lateinit var modelTextView: TextView + private lateinit var openKeychainTextView: TextView + private lateinit var orbotTextView: TextView + private lateinit var packageSignatureTextView: TextView + private lateinit var privacyBrowserTextView: TextView + private lateinit var radioTextView: TextView + private lateinit var securityPatchTextView: TextView + private lateinit var softwareTextView: TextView + private lateinit var systemAvailableMemoryTextView: TextView + private lateinit var systemConsumedMemoryTextView: TextView + private lateinit var systemTotalMemoryTextView: TextView + private lateinit var versionTextView: TextView private lateinit var ultraListTextView: TextView private lateinit var ultraPrivacyTextView: TextView - private lateinit var packageSignatureTextView: TextView - private lateinit var certificateIssuerDnTextView: TextView - private lateinit var certificateSubjectDnTextView: TextView - private lateinit var certificateStartDateTextView: TextView - private lateinit var certificateEndDateTextView: TextView - private lateinit var certificateVersionTextView: TextView - private lateinit var certificateSerialNumberTextView: TextView - private lateinit var certificateSignatureAlgorithmTextView: TextView + private lateinit var webViewProviderTextView: TextView + private lateinit var webViewVersionTextView: TextView companion object { - fun createTab(blocklistVersions: Array): AboutVersionFragment { + fun createTab(filterListsVersions: Array): AboutVersionFragment { // Create an arguments bundle. val argumentsBundle = Bundle() // Store the arguments in the bundle. - argumentsBundle.putStringArray(BLOCKLIST_VERSIONS, blocklistVersions) + argumentsBundle.putStringArray(FILTERLISTS_VERSIONS, filterListsVersions) // Create a new instance of the tab fragment. val aboutVersionFragment = AboutVersionFragment() @@ -155,9 +159,21 @@ class AboutVersionFragment : Fragment() { } // Define the save about version text activity result launcher. It must be defined before `onCreate()` is run or the app will crash. - private val saveAboutVersionTextActivityResultLauncher = registerForActivityResult(ActivityResultContracts.CreateDocument()) { fileUri: Uri? -> + private val saveAboutVersionTextActivityResultLauncher = registerForActivityResult(ActivityResultContracts.CreateDocument("text/plain")) { fileUri -> // Only save the file if the URI is not null, which happens if the user exited the file picker by pressing back. if (fileUri != null) { + // Get a cursor from the content resolver. + val contentResolverCursor = requireActivity().contentResolver.query(fileUri, null, null, null)!! + + // Move to the first row. + contentResolverCursor.moveToFirst() + + // Get the file name from the cursor. + val fileNameString = contentResolverCursor.getString(contentResolverCursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME)) + + // Close the cursor. + contentResolverCursor.close() + try { // Get the about version string. val aboutVersionString = getAboutVersionString() @@ -165,46 +181,31 @@ class AboutVersionFragment : Fragment() { // Open an output stream. val outputStream = requireActivity().contentResolver.openOutputStream(fileUri)!! - // Write the about version string to the output stream. - outputStream.write(aboutVersionString.toByteArray(StandardCharsets.UTF_8)) - - // Close the output stream. - outputStream.close() - - // Initialize the file name string from the file URI last path segment. - var fileNameString = fileUri.lastPathSegment - - // Query the exact file name if the API >= 26. - if (Build.VERSION.SDK_INT >= 26) { - // Get a cursor from the content resolver. - val contentResolverCursor = requireActivity().contentResolver.query(fileUri, null, null, null)!! - - // Move to the first row. - contentResolverCursor.moveToFirst() + // Save about version using a coroutine with Dispatchers.IO. + CoroutineScope(Dispatchers.Main).launch { + withContext(Dispatchers.IO) { + // Write the about version string to the output stream. + outputStream.write(aboutVersionString.toByteArray(StandardCharsets.UTF_8)) - // Get the file name from the cursor. - fileNameString = contentResolverCursor.getString(contentResolverCursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME)) - - // Close the cursor. - contentResolverCursor.close() + // Close the output stream. + outputStream.close() + } } // Display a snackbar with the saved logcat information. Snackbar.make(aboutVersionLayout, getString(R.string.saved, fileNameString), Snackbar.LENGTH_SHORT).show() } catch (exception: Exception) { // Display a snackbar with the error message. - Snackbar.make(aboutVersionLayout, getString(R.string.error_saving_file) + " " + exception.toString(), Snackbar.LENGTH_INDEFINITE).show() + Snackbar.make(aboutVersionLayout, getString(R.string.error_saving_file, fileNameString, exception.toString()), Snackbar.LENGTH_INDEFINITE).show() } } } // Define the save about version image activity result launcher. It must be defined before `onCreate()` is run or the app will crash. - private val saveAboutVersionImageActivityResultLauncher = registerForActivityResult(ActivityResultContracts.CreateDocument()) { fileUri: Uri? -> - // Only save the file if the URI is not null, which happens if the user exited the file picker by pressing back. - if (fileUri != null) { - // Save the about version image. - SaveAboutVersionImage(requireActivity(), fileUri, aboutVersionLayout.findViewById(R.id.about_version_linearlayout)).execute() - } + private val saveAboutVersionImageActivityResultLauncher = registerForActivityResult(ActivityResultContracts.CreateDocument("image/png")) { fileUri -> + // Save the file if the URI is not null, which happens if the user exits the file picker by pressing back. + if (fileUri != null) + SaveAboutVersionImageCoroutine.saveImage(requireActivity(), fileUri, aboutVersionLayout.findViewById(R.id.about_version_linearlayout)) } override fun onCreate(savedInstanceState: Bundle?) { @@ -212,7 +213,7 @@ class AboutVersionFragment : Fragment() { super.onCreate(savedInstanceState) // Store the arguments in class variables. - blocklistVersions = requireArguments().getStringArray(BLOCKLIST_VERSIONS)!! + filterListsVersions = requireArguments().getStringArray(FILTERLISTS_VERSIONS)!! // Enable the options menu for this fragment. setHasOptionsMenu(true) @@ -250,7 +251,7 @@ class AboutVersionFragment : Fragment() { systemConsumedMemoryTextView = aboutVersionLayout.findViewById(R.id.system_consumed_memory) systemAvailableMemoryTextView = aboutVersionLayout.findViewById(R.id.system_available_memory) systemTotalMemoryTextView = aboutVersionLayout.findViewById(R.id.system_total_memory) - blocklistsTextView = aboutVersionLayout.findViewById(R.id.blocklists) + filterListsTextView = aboutVersionLayout.findViewById(R.id.filterlists) easyListTextView = aboutVersionLayout.findViewById(R.id.easylist) easyPrivacyTextView = aboutVersionLayout.findViewById(R.id.easyprivacy) fanboyAnnoyanceTextView = aboutVersionLayout.findViewById(R.id.fanboy_annoyance) @@ -267,42 +268,41 @@ class AboutVersionFragment : Fragment() { certificateSignatureAlgorithmTextView = aboutVersionLayout.findViewById(R.id.certificate_signature_algorithm) // Setup the labels. - val version = getString(R.string.version) + " " + BuildConfig.VERSION_NAME + " (" + getString(R.string.version_code) + " " + BuildConfig.VERSION_CODE + ")" - val brandLabel = getString(R.string.brand) + " " - val manufacturerLabel = getString(R.string.manufacturer) + " " - val modelLabel = getString(R.string.model) + " " - val deviceLabel = getString(R.string.device) + " " - val bootloaderLabel = getString(R.string.bootloader) + " " - val androidLabel = getString(R.string.android) + " " - val buildLabel = getString(R.string.build) + " " - val kernelLabel = getString(R.string.kernel) + " " - val webViewVersionLabel = getString(R.string.webview_version) + " " - appConsumedMemoryLabel = getString(R.string.app_consumed_memory) + " " - appAvailableMemoryLabel = getString(R.string.app_available_memory) + " " - appTotalMemoryLabel = getString(R.string.app_total_memory) + " " - appMaximumMemoryLabel = getString(R.string.app_maximum_memory) + " " - systemConsumedMemoryLabel = getString(R.string.system_consumed_memory) + " " - systemAvailableMemoryLabel = getString(R.string.system_available_memory) + " " - systemTotalMemoryLabel = getString(R.string.system_total_memory) + " " - val easyListLabel = getString(R.string.easylist_label) + " " - val easyPrivacyLabel = getString(R.string.easyprivacy_label) + " " - val fanboyAnnoyanceLabel = getString(R.string.fanboy_annoyance_label) + " " - val fanboySocialLabel = getString(R.string.fanboy_social_label) + " " - val ultraListLabel = getString(R.string.ultralist_label) + " " - val ultraPrivacyLabel = getString(R.string.ultraprivacy_label) + " " - val issuerDNLabel = getString(R.string.issuer_dn) + " " - val subjectDNLabel = getString(R.string.subject_dn) + " " - val startDateLabel = getString(R.string.start_date) + " " - val endDateLabel = getString(R.string.end_date) + " " - val certificateVersionLabel = getString(R.string.certificate_version) + " " - val serialNumberLabel = getString(R.string.serial_number) + " " - val signatureAlgorithmLabel = getString(R.string.signature_algorithm) + " " - - // The WebView layout is only used to get the default user agent from `bare_webview`. It is not used to render content on the screen. - // Once the minimum API >= 26 this can be accomplished with the WebView package info. - val webViewLayout = layoutInflater.inflate(R.layout.bare_webview, container, false) - val tabLayoutWebView = webViewLayout.findViewById(R.id.bare_webview) - val userAgentString = tabLayoutWebView.settings.userAgentString + val version = getString(R.string.version_code, BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE) + val brandLabel = getString(R.string.brand) + val manufacturerLabel = getString(R.string.manufacturer) + val modelLabel = getString(R.string.model) + val deviceLabel = getString(R.string.device) + val bootloaderLabel = getString(R.string.bootloader) + val androidLabel = getString(R.string.android) + val securityPatchLabel = getString(R.string.security_patch) + val buildLabel = getString(R.string.build) + val kernelLabel = getString(R.string.kernel) + val webViewProviderLabel = getString(R.string.webview_provider) + val webViewVersionLabel = getString(R.string.webview_version) + appConsumedMemoryLabel = getString(R.string.app_consumed_memory) + appAvailableMemoryLabel = getString(R.string.app_available_memory) + appTotalMemoryLabel = getString(R.string.app_total_memory) + appMaximumMemoryLabel = getString(R.string.app_maximum_memory) + systemConsumedMemoryLabel = getString(R.string.system_consumed_memory) + systemAvailableMemoryLabel = getString(R.string.system_available_memory) + systemTotalMemoryLabel = getString(R.string.system_total_memory) + val easyListLabel = getString(R.string.easylist_label) + val easyPrivacyLabel = getString(R.string.easyprivacy_label) + val fanboyAnnoyanceLabel = getString(R.string.fanboys_annoyance_label) + val fanboySocialLabel = getString(R.string.fanboys_social_label) + val ultraListLabel = getString(R.string.ultralist_label) + val ultraPrivacyLabel = getString(R.string.ultraprivacy_label) + val issuerDNLabel = getString(R.string.issuer_dn) + val subjectDNLabel = getString(R.string.subject_dn) + val startDateLabel = getString(R.string.start_date) + val endDateLabel = getString(R.string.end_date) + val certificateVersionLabel = getString(R.string.certificate_version) + val serialNumberLabel = getString(R.string.serial_number) + val signatureAlgorithmLabel = getString(R.string.signature_algorithm) + + // Get the current WebView package info. + val webViewPackageInfo = WebView.getCurrentWebViewPackage()!! // Get the device's information and store it in strings. val brand = Build.BRAND @@ -311,12 +311,12 @@ class AboutVersionFragment : Fragment() { val device = Build.DEVICE val bootloader = Build.BOOTLOADER val radio = Build.getRadioVersion() - val android = Build.VERSION.RELEASE + " (" + getString(R.string.api) + " " + Build.VERSION.SDK_INT + ")" + val android = getString(R.string.api, Build.VERSION.RELEASE, Build.VERSION.SDK_INT) + val securityPatch = Build.VERSION.SECURITY_PATCH val build = Build.DISPLAY val kernel = System.getProperty("os.version") - - // Get the WebView version, selecting the substring that begins after `Chrome/` and goes until the next ` `. - val webView = userAgentString.substring(userAgentString.indexOf("Chrome/") + 7, userAgentString.indexOf(" ", userAgentString.indexOf("Chrome/"))) + val webViewPackageName = webViewPackageInfo.packageName + val webViewVersion = webViewPackageInfo.versionName // Get the Orbot version name if Orbot is installed. val orbot: String = try { @@ -329,11 +329,16 @@ class AboutVersionFragment : Fragment() { // Get the I2P version name if I2P is installed. val i2p: String = try { - // Store the version name. - requireContext().packageManager.getPackageInfo("net.i2p.android.router", 0).versionName - } catch (exception: PackageManager.NameNotFoundException) { // I2P is not installed. - // Store an empty string. - "" + // Check to see if the F-Droid flavor is installed. + getString(R.string.fdroid_flavor, requireContext().packageManager.getPackageInfo("net.i2p.android.router", 0).versionName) + } catch (exception: PackageManager.NameNotFoundException) { // The F-Droid flavor is not installed. + try { + // Check to see if the F-Droid flavor is installed. + getString(R.string.google_play_flavor, requireContext().packageManager.getPackageInfo("net.i2p.android", 0).versionName) + } catch (exception: PackageManager.NameNotFoundException) { // The Google Play flavor is not installed either. + // Store an empty string. + "" + } } // Get the OpenKeychain version name if it is installed. @@ -352,18 +357,20 @@ class AboutVersionFragment : Fragment() { val deviceStringBuilder = SpannableStringBuilder(deviceLabel + device) val bootloaderStringBuilder = SpannableStringBuilder(bootloaderLabel + bootloader) val androidStringBuilder = SpannableStringBuilder(androidLabel + android) + val securityPatchStringBuilder = SpannableStringBuilder(securityPatchLabel + securityPatch) val buildStringBuilder = SpannableStringBuilder(buildLabel + build) val kernelStringBuilder = SpannableStringBuilder(kernelLabel + kernel) - val webViewVersionStringBuilder = SpannableStringBuilder(webViewVersionLabel + webView) - val easyListStringBuilder = SpannableStringBuilder(easyListLabel + blocklistVersions[0]) - val easyPrivacyStringBuilder = SpannableStringBuilder(easyPrivacyLabel + blocklistVersions[1]) - val fanboyAnnoyanceStringBuilder = SpannableStringBuilder(fanboyAnnoyanceLabel + blocklistVersions[2]) - val fanboySocialStringBuilder = SpannableStringBuilder(fanboySocialLabel + blocklistVersions[3]) - val ultraListStringBuilder = SpannableStringBuilder(ultraListLabel + blocklistVersions[4]) - val ultraPrivacyStringBuilder = SpannableStringBuilder(ultraPrivacyLabel + blocklistVersions[5]) + val webViewProviderStringBuilder = SpannableStringBuilder(webViewProviderLabel + webViewPackageName) + val webViewVersionStringBuilder = SpannableStringBuilder(webViewVersionLabel + webViewVersion) + val easyListStringBuilder = SpannableStringBuilder(easyListLabel + filterListsVersions[0]) + val easyPrivacyStringBuilder = SpannableStringBuilder(easyPrivacyLabel + filterListsVersions[1]) + val fanboyAnnoyanceStringBuilder = SpannableStringBuilder(fanboyAnnoyanceLabel + filterListsVersions[2]) + val fanboySocialStringBuilder = SpannableStringBuilder(fanboySocialLabel + filterListsVersions[3]) + val ultraListStringBuilder = SpannableStringBuilder(ultraListLabel + filterListsVersions[4]) + val ultraPrivacyStringBuilder = SpannableStringBuilder(ultraPrivacyLabel + filterListsVersions[5]) // Set the blue color span according to the theme. The deprecated `getColor()` must be used until the minimum API >= 23. - blueColorSpan = ForegroundColorSpan(requireContext().getColor(R.color.about_version_blue_text)) + blueColorSpan = ForegroundColorSpan(requireContext().getColor(R.color.alt_blue_text)) // Set the spans to display the device information in blue. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction. brandStringBuilder.setSpan(blueColorSpan, brandLabel.length, brandStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE) @@ -372,8 +379,10 @@ class AboutVersionFragment : Fragment() { deviceStringBuilder.setSpan(blueColorSpan, deviceLabel.length, deviceStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE) bootloaderStringBuilder.setSpan(blueColorSpan, bootloaderLabel.length, bootloaderStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE) androidStringBuilder.setSpan(blueColorSpan, androidLabel.length, androidStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE) + securityPatchStringBuilder.setSpan(blueColorSpan, securityPatchLabel.length, securityPatchStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE) buildStringBuilder.setSpan(blueColorSpan, buildLabel.length, buildStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE) kernelStringBuilder.setSpan(blueColorSpan, kernelLabel.length, kernelStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE) + webViewProviderStringBuilder.setSpan(blueColorSpan, webViewProviderLabel.length, webViewProviderStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE) webViewVersionStringBuilder.setSpan(blueColorSpan, webViewVersionLabel.length, webViewVersionStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE) easyListStringBuilder.setSpan(blueColorSpan, easyListLabel.length, easyListStringBuilder.length, Spanned.SPAN_INCLUSIVE_EXCLUSIVE) easyPrivacyStringBuilder.setSpan(blueColorSpan, easyPrivacyLabel.length, easyPrivacyStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE) @@ -390,8 +399,10 @@ class AboutVersionFragment : Fragment() { deviceTextView.text = deviceStringBuilder bootloaderTextView.text = bootloaderStringBuilder androidTextView.text = androidStringBuilder + securityPatchTextView.text = securityPatchStringBuilder buildTextView.text = buildStringBuilder kernelTextView.text = kernelStringBuilder + webViewProviderTextView.text = webViewProviderStringBuilder webViewVersionTextView.text = webViewVersionStringBuilder easyListTextView.text = easyListStringBuilder easyPrivacyTextView.text = easyPrivacyStringBuilder @@ -404,7 +415,7 @@ class AboutVersionFragment : Fragment() { // Null must be checked because some Samsung tablets report a null value for the radio instead of an empty string. Grrrr. if (radio != null && radio.isNotEmpty()) { // Setup the label. - val radioLabel = getString(R.string.radio) + " " + val radioLabel = getString(R.string.radio) // Create a spannable string builder. val radioStringBuilder = SpannableStringBuilder(radioLabel + radio) @@ -419,43 +430,10 @@ class AboutVersionFragment : Fragment() { radioTextView.visibility = View.GONE } - // Setup the label. - val securityPatchLabel = getString(R.string.security_patch) + " " - - // Get the security patch version. - val securityPatch = Build.VERSION.SECURITY_PATCH - - // Create a spannable string builder. - val securityPatchStringBuilder = SpannableStringBuilder(securityPatchLabel + securityPatch) - - // Set the span to display the security patch version in blue. - securityPatchStringBuilder.setSpan(blueColorSpan, securityPatchLabel.length, securityPatchStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE) - - // Display the string in the text view. - securityPatchTextView.text = securityPatchStringBuilder - - // Create the WebView provider label. - val webViewProviderLabel = getString(R.string.webview_provider) + " " - - // Get the current WebView package info. - val webViewPackageInfo = WebViewCompat.getCurrentWebViewPackage(requireContext())!! - - // Get the WebView provider name. - val webViewPackageName = webViewPackageInfo.packageName - - // Create the spannable string builder. - val webViewProviderStringBuilder = SpannableStringBuilder(webViewProviderLabel + webViewPackageName) - - // Apply the coloration. - webViewProviderStringBuilder.setSpan(blueColorSpan, webViewProviderLabel.length, webViewProviderStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE) - - // Display the WebView provider. - webViewProviderTextView.text = webViewProviderStringBuilder - // Only populate the Orbot text view if it is installed. if (orbot.isNotEmpty()) { // Setup the label. - val orbotLabel = getString(R.string.orbot) + " " + val orbotLabel = getString(R.string.orbot) // Create a spannable string builder. val orbotStringBuilder = SpannableStringBuilder(orbotLabel + orbot) @@ -473,7 +451,7 @@ class AboutVersionFragment : Fragment() { // Only populate the I2P text view if it is installed. if (i2p.isNotEmpty()) { // Setup the label. - val i2pLabel = getString(R.string.i2p) + " " + val i2pLabel = getString(R.string.i2p) // Create a spannable string builder. val i2pStringBuilder = SpannableStringBuilder(i2pLabel + i2p) @@ -491,7 +469,7 @@ class AboutVersionFragment : Fragment() { // Only populate the OpenKeychain text view if it is installed. if (openKeychain.isNotEmpty()) { // Setup the label. - val openKeychainLabel = getString(R.string.openkeychain) + " " + val openKeychainLabel = getString(R.string.openkeychain) // Create a spannable string builder. val openKeychainStringBuilder = SpannableStringBuilder(openKeychainLabel + openKeychain) @@ -509,7 +487,8 @@ class AboutVersionFragment : Fragment() { // Display the package signature. try { // Get the first package signature. Suppress the lint warning about the need to be careful in implementing comparison of certificates for security purposes. - // Once the minimum API >= 28, `GET_SIGNING_CERTIFICATES` can be used instead. + // Once the minimum API >= 28, `GET_SIGNING_CERTIFICATES` can be used instead. Once the minimum API >= 33, the newer `getPackageInfo()` may be used. + @Suppress("DEPRECATION") @SuppressLint("PackageManagerGetSignatures") val packageSignature = requireContext().packageManager.getPackageInfo(requireContext().packageName,PackageManager.GET_SIGNATURES) .signatures[0] @@ -588,8 +567,7 @@ class AboutVersionFragment : Fragment() { // Scroll the tab if the saved instance state is not null. if (savedInstanceState != null) { aboutVersionLayout.post { - aboutVersionLayout.scrollX = savedInstanceState.getInt("scroll_x") - aboutVersionLayout.scrollY = savedInstanceState.getInt("scroll_y") + aboutVersionLayout.scrollY = savedInstanceState.getInt(SCROLL_Y) } } @@ -615,14 +593,15 @@ class AboutVersionFragment : Fragment() { // Get a handle for the clipboard manager. val clipboardManager = (requireActivity().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager) - // Save the about version string in a clip data. + // Place the about version string in a clip data. val aboutVersionClipData = ClipData.newPlainText(getString(R.string.about), aboutVersionString) // Place the clip data on the clipboard. clipboardManager.setPrimaryClip(aboutVersionClipData) - // Display a snackbar. - Snackbar.make(aboutVersionLayout, R.string.version_info_copied, Snackbar.LENGTH_SHORT).show() + // Display a snackbar if the API <= 32 (Android 12L). Beginning in Android 13 the OS displays a notification that covers up the snackbar. + if (Build.VERSION.SDK_INT <= 32) + Snackbar.make(aboutVersionLayout, R.string.version_info_copied, Snackbar.LENGTH_SHORT).show() // Consume the event. return true @@ -632,20 +611,20 @@ class AboutVersionFragment : Fragment() { // Get the about version string. val aboutString = getAboutVersionString() - // Create an email intent. - val emailIntent = Intent(Intent.ACTION_SEND) + // Create a share intent. + val shareIntent = Intent(Intent.ACTION_SEND) // Add the about version string to the intent. - emailIntent.putExtra(Intent.EXTRA_TEXT, aboutString) + shareIntent.putExtra(Intent.EXTRA_TEXT, aboutString) // Set the MIME type. - emailIntent.type = "text/plain" + shareIntent.type = "text/plain" // Set the intent to open in a new task. - emailIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + shareIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) // Make it so. - startActivity(Intent.createChooser(emailIntent, getString(R.string.share))) + startActivity(Intent.createChooser(shareIntent, getString(R.string.share))) // Consume the event. return true @@ -666,6 +645,7 @@ class AboutVersionFragment : Fragment() { // Consume the event. return true } + else -> { // The home button was selected. // Run the parents class on return. return super.onOptionsItemSelected(menuItem) @@ -677,9 +657,8 @@ class AboutVersionFragment : Fragment() { // Run the default commands. super.onSaveInstanceState(savedInstanceState) - // Save the scroll positions. - savedInstanceState.putInt("scroll_x", aboutVersionLayout.scrollX) - savedInstanceState.putInt("scroll_y", aboutVersionLayout.scrollY) + // Save the scroll position. + savedInstanceState.putInt(SCROLL_Y, aboutVersionLayout.scrollY) } override fun onPause() { @@ -698,7 +677,7 @@ class AboutVersionFragment : Fragment() { updateMemoryUsageBoolean = true } - fun updateMemoryUsage(activity: Activity) { + private fun updateMemoryUsage(activity: Activity) { try { // Update the memory usage if enabled. if (updateMemoryUsageBoolean) { @@ -779,7 +758,7 @@ class AboutVersionFragment : Fragment() { } } - fun getAboutVersionString(): String { + private fun getAboutVersionString(): String { // Initialize an about version string builder. val aboutVersionStringBuilder = StringBuilder() @@ -852,7 +831,7 @@ class AboutVersionFragment : Fragment() { aboutVersionStringBuilder.append("\n") aboutVersionStringBuilder.append(systemTotalMemoryTextView.text) aboutVersionStringBuilder.append("\n\n") - aboutVersionStringBuilder.append(blocklistsTextView.text) + aboutVersionStringBuilder.append(filterListsTextView.text) aboutVersionStringBuilder.append("\n") aboutVersionStringBuilder.append(easyListTextView.text) aboutVersionStringBuilder.append("\n") @@ -885,4 +864,4 @@ class AboutVersionFragment : Fragment() { // Return the string. return aboutVersionStringBuilder.toString() } -} \ No newline at end of file +}