]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/blobdiff - app/src/main/java/com/stoutner/privacybrowser/fragments/AboutVersionFragment.kt
Fix possibly blocking OutputStream calls. https://redmine.stoutner.com/issues/914
[PrivacyBrowserAndroid.git] / app / src / main / java / com / stoutner / privacybrowser / fragments / AboutVersionFragment.kt
index 7dfeda99553fd10c2e77d6ba3122417cbd014c2c..0078fcc1fab5039c533b07a05064234b4da77b3b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2016-2022 Soren Stoutner <soren@stoutner.com>.
+ * Copyright 2016-2022 Soren Stoutner <soren@stoutner.com>.
  *
  * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
  *
@@ -55,6 +55,11 @@ import com.stoutner.privacybrowser.R
 import com.stoutner.privacybrowser.BuildConfig
 import com.stoutner.privacybrowser.asynctasks.SaveAboutVersionImage
 
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
 import java.io.ByteArrayInputStream
 import java.io.InputStream
 import java.lang.Exception
@@ -155,7 +160,7 @@ 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: 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) {
             try {
@@ -165,11 +170,16 @@ 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))
+                // 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))
 
-                // Close the output stream.
-                outputStream.close()
+                        // Close the output stream.
+                        outputStream.close()
+                    }
+                }
 
                 // Initialize the file name string from the file URI last path segment.
                 var fileNameString = fileUri.lastPathSegment
@@ -199,7 +209,7 @@ class AboutVersionFragment : Fragment() {
     }
 
     // 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? ->
+    private val saveAboutVersionImageActivityResultLauncher = registerForActivityResult(ActivityResultContracts.CreateDocument("image/png")) { 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.
@@ -286,8 +296,8 @@ class AboutVersionFragment : Fragment() {
         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 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) + "  "
@@ -320,7 +330,8 @@ class AboutVersionFragment : Fragment() {
 
         // Get the Orbot version name if Orbot is installed.
         val orbot: String = try {
-            // Store the version name.
+            // Store the version name.  The newer `getPackageInfo()` may be used once the minimum API >= 33.
+            @Suppress("DEPRECATION")
             requireContext().packageManager.getPackageInfo("org.torproject.android", 0).versionName
         } catch (exception: PackageManager.NameNotFoundException) {  // Orbot is not installed.
             // Store an empty string.
@@ -329,16 +340,24 @@ 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.  The newer `getPackageInfo()` may be used once the minimum API >= 33.
+            @Suppress("DEPRECATION")
+            requireContext().packageManager.getPackageInfo("net.i2p.android.router", 0).versionName + " " + requireContext().getString(R.string.fdroid_flavor)
+        } catch (exception: PackageManager.NameNotFoundException) {  // The F-Droid flavor is not installed.
+            try {
+                // Check to see if the F-Droid flavor is installed.  The newer `getPackageInfo()` may be used once the minimum API >= 33.
+                @Suppress("DEPRECATION")
+                requireContext().packageManager.getPackageInfo("net.i2p.android", 0).versionName + " " + requireContext().getString(R.string.google_play_flavor)
+            } 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.
         val openKeychain: String = try {
-            // Store the version name.
+            // Store the version name.  The newer `getPackageInfo()` may be used once the minimum API >= 33.
+            @Suppress("DEPRECATION")
             requireContext().packageManager.getPackageInfo("org.sufficientlysecure.keychain", 0).versionName
         } catch (exception: PackageManager.NameNotFoundException) {  // OpenKeychain is not installed.
             // Store an empty string.
@@ -509,7 +528,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]
 
@@ -885,4 +905,4 @@ class AboutVersionFragment : Fragment() {
         // Return the string.
         return aboutVersionStringBuilder.toString()
     }
-}
\ No newline at end of file
+}