Include the voice network when determining the overall security. https://redmine...
authorSoren Stoutner <soren@stoutner.com>
Mon, 30 May 2022 22:23:43 +0000 (15:23 -0700)
committerSoren Stoutner <soren@stoutner.com>
Mon, 30 May 2022 22:23:43 +0000 (15:23 -0700)
app/src/main/java/com/stoutner/privacycell/activities/PrivacyCellActivity.kt
app/src/main/java/com/stoutner/privacycell/helpers/ProtocolHelper.kt [new file with mode: 0644]
app/src/main/java/com/stoutner/privacycell/services/RealtimeMonitoringService.kt
app/src/main/res/layout/privacy_cell_bottom_appbar.xml
app/src/main/res/layout/privacy_cell_top_appbar.xml
app/src/main/res/values-night/colors.xml
app/src/main/res/values/colors.xml

index 16772d2a5347092c00310811f435e80b50b8d2d0..b158e057db725a5dc2eaf778a32ad9d5081b0320 100644 (file)
@@ -55,16 +55,23 @@ import com.google.android.material.navigation.NavigationView
 import com.stoutner.privacycell.R
 import com.stoutner.privacycell.dialogs.PhonePermissionDialog
 import com.stoutner.privacycell.dialogs.WebViewDialog
+import com.stoutner.privacycell.helpers.ProtocolHelper
 import com.stoutner.privacycell.services.RealtimeMonitoringService
 
 class PrivacyCellActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener, PhonePermissionDialog.StoragePermissionDialogListener {
+    // Define the class variables.
+    private var voiceNetworkSecurityStatus = ProtocolHelper.UNPOPULATED
+    private var dataNetworkSecurityStatus = ProtocolHelper.UNPOPULATED
+
     // Declare the class variables.
-    private lateinit var actionBarDrawerToggle: ActionBarDrawerToggle
     private lateinit var phoneStateListener: PhoneStateListener  // The `PhoneStateListener` can be replaced by `TelephonyCallback` once the minimum API >= 31.
 
     // Declare the class views.
+    private lateinit var actionBarDrawerToggle: ActionBarDrawerToggle
     private lateinit var drawerLayout: DrawerLayout
-    private lateinit var summaryTextView: TextView
+    private lateinit var overallStatusLinearLayout: LinearLayout
+    private lateinit var overallStatusImageView: ImageView
+    private lateinit var overallStatusTextView: TextView
 
     override fun onCreate(savedInstanceState: Bundle?) {
         // Run the default commands.
@@ -88,9 +95,9 @@ class PrivacyCellActivity : AppCompatActivity(), NavigationView.OnNavigationItem
         // Get handles for the views.
         drawerLayout = findViewById(R.id.drawerlayout)
         val toolbar = findViewById<Toolbar>(R.id.toolbar)
-        val stingrayLinearLayout = findViewById<LinearLayout>(R.id.stingray_linearlayout)
-        val stingrayImageView = findViewById<ImageView>(R.id.stingray_imageview)
-        summaryTextView = findViewById(R.id.summary_textview)
+        overallStatusLinearLayout = findViewById(R.id.overall_status_linearlayout)
+        overallStatusImageView = findViewById(R.id.overall_status_imageview)
+        overallStatusTextView = findViewById(R.id.overall_status_textview)
         val voiceNetworkLinearLayout = findViewById<LinearLayout>(R.id.voice_network_linearlayout)
         val voiceNetworkTextView = findViewById<TextView>(R.id.voice_network)
         val voiceNetworkDetailsTextView = findViewById<TextView>(R.id.voice_network_details)
@@ -140,83 +147,40 @@ class PrivacyCellActivity : AppCompatActivity(), NavigationView.OnNavigationItem
             }
         })
 
+        // Instantiate the protocol helper.
+        val protocolHelper = ProtocolHelper()
+
         // Define the phone state listener.  The `PhoneStateListener` can be replaced by `TelephonyCallback` once the minimum API >= 31.
         phoneStateListener = object : PhoneStateListener() {
             @Deprecated("Deprecated in Java")
-            @SuppressLint("SwitchIntDef")
-            override fun onDisplayInfoChanged(telephonyDisplayInfo: TelephonyDisplayInfo) {
-                // Declare the stingray dialog type integer.
-                val summaryDialogTypeInteger: Int
-
-                // Populate the stingray security information.  <https://source.android.com/devices/tech/connect/acts-5g-testing>
-                if ((telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_NR) || (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_IWLAN) ||
-                    (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_UNKNOWN)) {  // This is a secure network.
-                    // Populate the image view.
-                    stingrayImageView.setImageDrawable(AppCompatResources.getDrawable(applicationContext, R.drawable.secure))
-
-                    // Set the text.
-                    summaryTextView.text = getString(R.string.secure_protocols)
-
-                    // Set the text color.
-                    summaryTextView.setTextColor(getColor(R.color.blue_text))
-
-                    // Set the stingray dialog type integer.
-                    summaryDialogTypeInteger = WebViewDialog.STINGRAY
-                } else if ((telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_LTE) || (!consider3gAntiquated && (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_1xRTT ||
-                            (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_EVDO_0) || (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_EVDO_A) ||
-                            (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_EVDO_B) || (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_EHRPD) ||
-                            (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_UMTS) || (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_TD_SCDMA) ||
-                            (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_HSDPA) || (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_HSUPA) ||
-                            (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_HSPA) || (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_HSPAP)))) {
-                            // This is an insecure network.
-                    // Populate the image view.
-                    stingrayImageView.setImageDrawable(AppCompatResources.getDrawable(applicationContext, R.drawable.insecure))
-
-                    // Set the text.
-                    summaryTextView.text = getString(R.string.insecure_protocols)
-
-                    // Set the text color.
-                    summaryTextView.setTextColor(getColor(R.color.yellow_900))
-
-                    // Set the stingray dialog type integer.
-                    summaryDialogTypeInteger = WebViewDialog.STINGRAY
-                } else {  // This is an antiquated network.
-                    // Populate the image view.
-                    stingrayImageView.setImageDrawable(AppCompatResources.getDrawable(applicationContext, R.drawable.antiquated))
-
-                    // Set the text.
-                    summaryTextView.text = getString(R.string.antiquated_protocols)
-
-                    // Set the text color.
-                    summaryTextView.setTextColor(getColor(R.color.red_text))
-
-                    // Set the stingray dialog type integer.
-                    summaryDialogTypeInteger = WebViewDialog.ANTIQUATED_NETWORK
-                }
+            override fun onServiceStateChanged(serviceState: ServiceState) {  // Update the voice network.
+                // Get the network registration info for the voice network, which is the second of the three entries (the first appears to be Wi-Fi and the third appears to be the cell data network).
+                val networkRegistrationInfo = serviceState.networkRegistrationInfoList[1]
 
-                // Get the strings that correspond to the network information.
-                val dataNetworkType = getNetworkType(telephonyDisplayInfo.networkType)
-                val additionalNetworkInfo = getAdditionalNetworkInfo(telephonyDisplayInfo.overrideNetworkType)
+                // Get the voice network type int.
+                val voiceNetworkTypeInt = networkRegistrationInfo.accessNetworkTechnology
 
-                // Populate the data network text views.
-                dataNetworkTextView.text = getString(R.string.data_network, dataNetworkType[0])
-                dataNetworkDetailsTextView.text = dataNetworkType[1]
-                additionalNetworkInfoTextView.text = getString(R.string.additional_network_info, additionalNetworkInfo[0])
-                additionalNetworkInfoDetailsTextView.text = additionalNetworkInfo[1]
+                // Get the voice network security status.
+                voiceNetworkSecurityStatus = protocolHelper.checkNetwork(voiceNetworkTypeInt, consider3gAntiquated)
 
-                // Set the stingray click listener.
-                stingrayLinearLayout.setOnClickListener {
-                    // Instantiate the stingray dialog fragment.
-                    val stingrayDialogFragment = WebViewDialog().type(summaryDialogTypeInteger)
+                // Get the voice network type.
+                val voiceNetworkStringArray = protocolHelper.getNetworkTypeStringArray(voiceNetworkTypeInt, applicationContext)
 
-                    // Show the alert dialog.
-                    stingrayDialogFragment.show(supportFragmentManager, getString(R.string.stingrays))
+                // Populate the voice network text views.
+                voiceNetworkTextView.text = getString(R.string.voice_network, voiceNetworkStringArray[0])
+                voiceNetworkDetailsTextView.text = voiceNetworkStringArray[1]
+
+                // Set the color of the voice network.
+                when (voiceNetworkSecurityStatus) {
+                    ProtocolHelper.SECURE -> voiceNetworkTextView.setTextColor(getColor(R.color.blue_text))
+                    ProtocolHelper.INSECURE -> voiceNetworkTextView.setTextColor(getColor(R.color.yellow_text))
+                    ProtocolHelper.ANTIQUATED -> voiceNetworkTextView.setTextColor(getColor(R.color.red_text))
                 }
 
-                // Set the data network click listener.
-                dataNetworkLinearLayout.setOnClickListener {
-                    // Instantiate the data network dialog fragment according to the network type.
-                    val dataNetworkDialogFragment = when (telephonyDisplayInfo.networkType) {
+                // Set the voice network click listener.
+                voiceNetworkLinearLayout.setOnClickListener {
+                    // Instantiate the voice network dialog fragment according to the network type.
+                    val voiceNetworkDialogFragment = when (voiceNetworkTypeInt) {
                         TelephonyManager.NETWORK_TYPE_UNKNOWN -> WebViewDialog().type(WebViewDialog.NETWORK_UNKNOWN)
                         TelephonyManager.NETWORK_TYPE_GPRS -> WebViewDialog().type(WebViewDialog.NETWORK_GPRS)
                         TelephonyManager.NETWORK_TYPE_EDGE -> WebViewDialog().type(WebViewDialog.NETWORK_EDGE)
@@ -241,43 +205,51 @@ class PrivacyCellActivity : AppCompatActivity(), NavigationView.OnNavigationItem
                     }
 
                     // Show the alert dialog.
-                    dataNetworkDialogFragment.show(supportFragmentManager, getString(R.string.voice_network))
+                    voiceNetworkDialogFragment.show(supportFragmentManager, getString(R.string.voice_network))
                 }
 
-                // Set the additional network info click listener.
-                additionalNetworkInfoLinearLayout.setOnClickListener {
-                    // Instantiate the initial network info dialog fragment according to the network type.
-                    val additionalNetworkInfoDialogFragment = when (telephonyDisplayInfo.overrideNetworkType) {
-                        TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NONE)
-                        TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_LTE_CA)
-                        TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_LTE_ADVANCED_PRO)
-                        TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NR_NSA)
-                        TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NR_NSA_MMWAVE)  // Can be removed once the minimum API >= 31.
-                        TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NR_ADVANCED)
-                        else -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NONE)
-                    }
-
-                    // Show the alert dialog.
-                    additionalNetworkInfoDialogFragment.show(supportFragmentManager, getString(R.string.voice_network))
-                }
+                // Populate the overall security status.
+                populateOverallSecurityStatus()
             }
 
             @Deprecated("Deprecated in Java")
-            override fun onServiceStateChanged(serviceState: ServiceState) {
-                // Get the network registration info for the voice network, which is the second of the three entries (the first appears to be Wi-Fi and the third appears to be the cell data network).
-                val networkRegistrationInfo = serviceState.networkRegistrationInfoList[1]
+            @SuppressLint("SwitchIntDef")
+            override fun onDisplayInfoChanged(telephonyDisplayInfo: TelephonyDisplayInfo) {  // Update the data network.
+                // Get the network type integers.  <https://source.android.com/devices/tech/connect/acts-5g-testing>
+                val dataNetworkTypeInt = telephonyDisplayInfo.networkType
+                val additionalNetworkInfoTypeInt = telephonyDisplayInfo.overrideNetworkType
 
-                // Get the voice network type.
-                val voiceNetworkType = getNetworkType(networkRegistrationInfo.accessNetworkTechnology)
+                // Get the data network security status.
+                dataNetworkSecurityStatus = protocolHelper.checkNetwork(dataNetworkTypeInt, consider3gAntiquated)
 
-                // Populate the voice network text views.
-                voiceNetworkTextView.text = getString(R.string.voice_network, voiceNetworkType[0])
-                voiceNetworkDetailsTextView.text = voiceNetworkType[1]
+                // Get the strings that correspond to the network information.
+                val dataNetworkStringArray = protocolHelper.getNetworkTypeStringArray(dataNetworkTypeInt, applicationContext)
+                val additionalNetworkInfoStringArray = protocolHelper.getAdditionalNetworkInfoStringArray(additionalNetworkInfoTypeInt, applicationContext)
 
-                // Set the voice network click listener.
-                voiceNetworkLinearLayout.setOnClickListener {
-                    // Instantiate the voice network dialog fragment according to the network type.
-                    val voiceNetworkDialogFragment = when (networkRegistrationInfo.accessNetworkTechnology) {
+                // Populate the data network text views.
+                dataNetworkTextView.text = getString(R.string.data_network, dataNetworkStringArray[0])
+                dataNetworkDetailsTextView.text = dataNetworkStringArray[1]
+                additionalNetworkInfoTextView.text = getString(R.string.additional_network_info, additionalNetworkInfoStringArray[0])
+                additionalNetworkInfoDetailsTextView.text = additionalNetworkInfoStringArray[1]
+
+                // Set the color of the data network.
+                when (dataNetworkSecurityStatus) {
+                    ProtocolHelper.SECURE -> dataNetworkTextView.setTextColor(getColor(R.color.blue_text))
+                    ProtocolHelper.INSECURE -> dataNetworkTextView.setTextColor(getColor(R.color.yellow_text))
+                    ProtocolHelper.ANTIQUATED -> dataNetworkTextView.setTextColor(getColor(R.color.red_text))
+                }
+
+                // Set the color of the additional network info.
+                when (protocolHelper.checkAdditionalNetworkInfo(additionalNetworkInfoTypeInt)) {
+                    ProtocolHelper.SECURE -> additionalNetworkInfoTextView.setTextColor(getColor(R.color.blue_text))
+                    ProtocolHelper.INSECURE -> additionalNetworkInfoTextView.setTextColor(getColor(R.color.yellow_text))
+                    ProtocolHelper.ANTIQUATED -> additionalNetworkInfoTextView.setTextColor(getColor(R.color.red_text))
+                }
+
+                // Set the data network click listener.
+                dataNetworkLinearLayout.setOnClickListener {
+                    // Instantiate the data network dialog fragment according to the network type.
+                    val dataNetworkDialogFragment = when (dataNetworkTypeInt) {
                         TelephonyManager.NETWORK_TYPE_UNKNOWN -> WebViewDialog().type(WebViewDialog.NETWORK_UNKNOWN)
                         TelephonyManager.NETWORK_TYPE_GPRS -> WebViewDialog().type(WebViewDialog.NETWORK_GPRS)
                         TelephonyManager.NETWORK_TYPE_EDGE -> WebViewDialog().type(WebViewDialog.NETWORK_EDGE)
@@ -302,8 +274,28 @@ class PrivacyCellActivity : AppCompatActivity(), NavigationView.OnNavigationItem
                     }
 
                     // Show the alert dialog.
-                    voiceNetworkDialogFragment.show(supportFragmentManager, getString(R.string.voice_network))
+                    dataNetworkDialogFragment.show(supportFragmentManager, getString(R.string.voice_network))
                 }
+
+                // Set the additional network info click listener.
+                additionalNetworkInfoLinearLayout.setOnClickListener {
+                    // Instantiate the initial network info dialog fragment according to the network type.
+                    val additionalNetworkInfoDialogFragment = when (telephonyDisplayInfo.overrideNetworkType) {
+                        TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NONE)
+                        TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_LTE_CA)
+                        TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_LTE_ADVANCED_PRO)
+                        TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NR_NSA)
+                        TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NR_NSA_MMWAVE)  // Can be removed once the minimum API >= 31.
+                        TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NR_ADVANCED)
+                        else -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NONE)
+                    }
+
+                    // Show the alert dialog.
+                    additionalNetworkInfoDialogFragment.show(supportFragmentManager, getString(R.string.voice_network))
+                }
+
+                // Populate the overall security status.
+                populateOverallSecurityStatus()
             }
         }
 
@@ -514,7 +506,7 @@ class PrivacyCellActivity : AppCompatActivity(), NavigationView.OnNavigationItem
                 registerTelephonyManagerListener()
             } else {  // The read phone state permission was denied.
                 // Display the phone permission text on the main activity.
-                summaryTextView.text = getString(R.string.phone_permission_text)
+               overallStatusTextView.text = getString(R.string.phone_permission_text)
             }
         }
     }
@@ -524,46 +516,59 @@ class PrivacyCellActivity : AppCompatActivity(), NavigationView.OnNavigationItem
         val telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
 
         // Listen to changes in the cell network state.  The `PhoneStateListener` can be replaced by `TelephonyCallback` once the minimum API >= 31.
-        telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED or PhoneStateListener.LISTEN_SERVICE_STATE)
+        telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE or PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED)
     }
 
-    private fun getNetworkType(networkType: Int) : Array<String> {
-        // Return the string that corresponds to the network type.
-        return when(networkType) {
-            TelephonyManager.NETWORK_TYPE_UNKNOWN -> arrayOf(getString(R.string.unknown), "")
-            TelephonyManager.NETWORK_TYPE_GPRS -> arrayOf(getString(R.string.gprs), getString(R.string.gprs_detail))
-            TelephonyManager.NETWORK_TYPE_EDGE -> arrayOf(getString(R.string.edge), getString(R.string.edge_detail))
-            TelephonyManager.NETWORK_TYPE_UMTS -> arrayOf(getString(R.string.umts), getString(R.string.umts_detail))
-            TelephonyManager.NETWORK_TYPE_CDMA -> arrayOf(getString(R.string.cdma), getString(R.string.cdma_detail))
-            TelephonyManager.NETWORK_TYPE_EVDO_0 -> arrayOf(getString(R.string.evdo_0), getString(R.string.evdo_0_detail))
-            TelephonyManager.NETWORK_TYPE_EVDO_A -> arrayOf(getString(R.string.evdo_a), getString(R.string.evdo_a_detail))
-            TelephonyManager.NETWORK_TYPE_1xRTT -> arrayOf(getString(R.string.rtt), getString(R.string.rtt_detail))
-            TelephonyManager.NETWORK_TYPE_HSDPA -> arrayOf(getString(R.string.hsdpa), getString(R.string.hsdpa_detail))
-            TelephonyManager.NETWORK_TYPE_HSUPA -> arrayOf(getString(R.string.hsupa), getString(R.string.hsupa_detail))
-            TelephonyManager.NETWORK_TYPE_HSPA -> arrayOf(getString(R.string.hspa), getString(R.string.hspa_detail))
-            TelephonyManager.NETWORK_TYPE_IDEN -> arrayOf(getString(R.string.iden), getString(R.string.iden_detail))
-            TelephonyManager.NETWORK_TYPE_EVDO_B -> arrayOf(getString(R.string.evdo_b), getString(R.string.evdo_b_detail))
-            TelephonyManager.NETWORK_TYPE_LTE -> arrayOf(getString(R.string.lte), getString(R.string.lte_detail))
-            TelephonyManager.NETWORK_TYPE_EHRPD -> arrayOf(getString(R.string.ehrpd), getString(R.string.ehrpd_detail))
-            TelephonyManager.NETWORK_TYPE_HSPAP -> arrayOf(getString(R.string.hspap), getString(R.string.hspap_detail))
-            TelephonyManager.NETWORK_TYPE_GSM -> arrayOf(getString(R.string.gsm), getString(R.string.gsm_detail))
-            TelephonyManager.NETWORK_TYPE_TD_SCDMA -> arrayOf(getString(R.string.td_scdma), getString(R.string.td_scdma_detail))
-            TelephonyManager.NETWORK_TYPE_IWLAN -> arrayOf(getString(R.string.iwlan), getString(R.string.iwlan_detail))
-            TelephonyManager.NETWORK_TYPE_NR -> arrayOf(getString(R.string.nr), getString(R.string.nr_detail))
-            else -> arrayOf(getString(R.string.error), "")
+    private fun populateOverallSecurityStatus() {
+        // Create an overall status dialog type integer.
+        val overallStatusDialogTypeInt: Int
+
+        // Populate the over security status.
+        if ((voiceNetworkSecurityStatus == ProtocolHelper.ANTIQUATED) || (dataNetworkSecurityStatus == ProtocolHelper.ANTIQUATED)) {  // This is an antiquated network.
+            // Populate the image view.
+            overallStatusImageView.setImageDrawable(AppCompatResources.getDrawable(applicationContext, R.drawable.antiquated))
+
+            // Set the text.
+            overallStatusTextView.text = getString(R.string.antiquated_protocols)
+
+            // Set the text color.
+            overallStatusTextView.setTextColor(getColor(R.color.red_text))
+
+            // Set the stingray dialog type integer.
+            overallStatusDialogTypeInt = WebViewDialog.ANTIQUATED_NETWORK
+        } else if ((voiceNetworkSecurityStatus == ProtocolHelper.INSECURE) || (dataNetworkSecurityStatus == ProtocolHelper.INSECURE)) {  // This is an insecure network.
+            // Populate the image view.
+            overallStatusImageView.setImageDrawable(AppCompatResources.getDrawable(applicationContext, R.drawable.insecure))
+
+            // Set the text.
+            overallStatusTextView.text = getString(R.string.insecure_protocols)
+
+            // Set the text color.
+            overallStatusTextView.setTextColor(getColor(R.color.yellow_text))
+
+            // Set the stingray dialog type integer.
+            overallStatusDialogTypeInt = WebViewDialog.STINGRAY
+        } else {  // This is a secure network.
+            // Populate the image view.
+            overallStatusImageView.setImageDrawable(AppCompatResources.getDrawable(applicationContext, R.drawable.secure))
+
+            // Set the text.
+            overallStatusTextView.text = getString(R.string.secure_protocols)
+
+            // Set the text color.
+            overallStatusTextView.setTextColor(getColor(R.color.blue_text))
+
+            // Set the stingray dialog type integer.
+            overallStatusDialogTypeInt = WebViewDialog.STINGRAY
         }
-    }
 
-    private fun getAdditionalNetworkInfo(overrideNetworkType: Int) : Array<String> {
-        // Return the string that corresponds to the override network type.
-        return when(overrideNetworkType) {
-            TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE -> arrayOf(getString(R.string.none), "")
-            TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA -> arrayOf(getString(R.string.lte_ca), getString(R.string.lte_ca_detail))
-            TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO -> arrayOf(getString(R.string.lte_advanced_pro), getString(R.string.lte_advanced_pro_detail))
-            TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA -> arrayOf(getString(R.string.nr_nsa), getString(R.string.nr_nsa_detail))
-            TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE -> arrayOf(getString(R.string.nr_nsa_mmwave), getString(R.string.nr_nsa_mmwave_detail))  // Can be removed once the minimum API >= 31.
-            TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED -> arrayOf(getString(R.string.nr_advanced), getString(R.string.nr_advanced_detail))
-            else -> arrayOf(getString(R.string.error), "")
+        // Set the overall status click listener.
+        overallStatusLinearLayout.setOnClickListener {
+            // Instantiate the stingray dialog fragment.
+            val stingrayDialogFragment = WebViewDialog().type(overallStatusDialogTypeInt)
+
+            // Show the alert dialog.
+            stingrayDialogFragment.show(supportFragmentManager, getString(R.string.stingrays))
         }
     }
 }
\ No newline at end of file
diff --git a/app/src/main/java/com/stoutner/privacycell/helpers/ProtocolHelper.kt b/app/src/main/java/com/stoutner/privacycell/helpers/ProtocolHelper.kt
new file mode 100644 (file)
index 0000000..dcbc9ad
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
+ *
+ * This file is part of Privacy Cell <https://www.stoutner.com/privacy-cell>.
+ *
+ * Privacy Cell is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Privacy Cell is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Privacy Cell.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.stoutner.privacycell.helpers
+
+import android.content.Context
+import android.telephony.TelephonyDisplayInfo
+import android.telephony.TelephonyManager
+
+import com.stoutner.privacycell.R
+
+class ProtocolHelper {
+    companion object {
+        // Define the public static companion object constants.
+        const val UNPOPULATED = -1
+        const val SECURE = 0
+        const val INSECURE = 1
+        const val ANTIQUATED = 2
+    }
+
+    fun checkNetwork(networkType: Int, consider3gAntiquated: Boolean): Int {
+        if ((networkType == TelephonyManager.NETWORK_TYPE_NR) ||
+            (networkType == TelephonyManager.NETWORK_TYPE_IWLAN) ||
+            (networkType == TelephonyManager.NETWORK_TYPE_UNKNOWN)) {
+            // The network is secure.
+            return SECURE
+        } else if (networkType == TelephonyManager.NETWORK_TYPE_LTE) {
+            // The network is insecure.
+            return INSECURE
+        } else if (!consider3gAntiquated &&
+                  ((networkType == TelephonyManager.NETWORK_TYPE_1xRTT) ||
+                   (networkType == TelephonyManager.NETWORK_TYPE_EVDO_0) ||
+                   (networkType == TelephonyManager.NETWORK_TYPE_EVDO_A) ||
+                   (networkType == TelephonyManager.NETWORK_TYPE_EVDO_B) ||
+                   (networkType == TelephonyManager.NETWORK_TYPE_EHRPD) ||
+                   (networkType == TelephonyManager.NETWORK_TYPE_UMTS) ||
+                   (networkType == TelephonyManager.NETWORK_TYPE_TD_SCDMA) ||
+                   (networkType == TelephonyManager.NETWORK_TYPE_HSDPA) ||
+                   (networkType == TelephonyManager.NETWORK_TYPE_HSUPA) ||
+                   (networkType == TelephonyManager.NETWORK_TYPE_HSPA) ||
+                   (networkType == TelephonyManager.NETWORK_TYPE_HSPAP))) {
+            // The network is insecure.
+            return INSECURE
+        } else {
+            // Either 3G networks are considered antiquated, or this is a 2G network.
+            // TelephonyManager.NETWORK_TYPE_GPRS
+            // TelephonyManager.NETWORK_TYPE_EDGE
+            // TelephonyManager.NETWORK_TYPE_CDMA
+            // TelephonyManager.NETWORK_TYPE_IDEN
+            // TelephonyManager.NETWORK_TYPE_GSM
+            return ANTIQUATED
+        }
+    }
+
+    fun checkAdditionalNetworkInfo(additionalNetworkInfoType: Int): Int {
+        if ((additionalNetworkInfoType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE) ||
+            (additionalNetworkInfoType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED)) {
+            // The additional network info is secure.
+            return SECURE
+        } else {
+            // The additional network info is insecure.
+            // TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA
+            // TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO
+            // TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA
+            // TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE -- Can be removed once the minimum API >= 31.
+            return INSECURE
+        }
+    }
+
+    fun getNetworkTypeStringArray(networkType: Int, context: Context) : Array<String> {
+        // Return the string array that corresponds to the network type.
+        return when(networkType) {
+            TelephonyManager.NETWORK_TYPE_UNKNOWN -> arrayOf(context.getString(R.string.unknown), "")
+            TelephonyManager.NETWORK_TYPE_GPRS -> arrayOf(context.getString(R.string.gprs), context.getString(R.string.gprs_detail))
+            TelephonyManager.NETWORK_TYPE_EDGE -> arrayOf(context.getString(R.string.edge), context.getString(R.string.edge_detail))
+            TelephonyManager.NETWORK_TYPE_UMTS -> arrayOf(context.getString(R.string.umts), context.getString(R.string.umts_detail))
+            TelephonyManager.NETWORK_TYPE_CDMA -> arrayOf(context.getString(R.string.cdma), context.getString(R.string.cdma_detail))
+            TelephonyManager.NETWORK_TYPE_EVDO_0 -> arrayOf(context.getString(R.string.evdo_0), context.getString(R.string.evdo_0_detail))
+            TelephonyManager.NETWORK_TYPE_EVDO_A -> arrayOf(context.getString(R.string.evdo_a), context.getString(R.string.evdo_a_detail))
+            TelephonyManager.NETWORK_TYPE_1xRTT -> arrayOf(context.getString(R.string.rtt), context.getString(R.string.rtt_detail))
+            TelephonyManager.NETWORK_TYPE_HSDPA -> arrayOf(context.getString(R.string.hsdpa), context.getString(R.string.hsdpa_detail))
+            TelephonyManager.NETWORK_TYPE_HSUPA -> arrayOf(context.getString(R.string.hsupa), context.getString(R.string.hsupa_detail))
+            TelephonyManager.NETWORK_TYPE_HSPA -> arrayOf(context.getString(R.string.hspa), context.getString(R.string.hspa_detail))
+            TelephonyManager.NETWORK_TYPE_IDEN -> arrayOf(context.getString(R.string.iden), context.getString(R.string.iden_detail))
+            TelephonyManager.NETWORK_TYPE_EVDO_B -> arrayOf(context.getString(R.string.evdo_b), context.getString(R.string.evdo_b_detail))
+            TelephonyManager.NETWORK_TYPE_LTE -> arrayOf(context.getString(R.string.lte), context.getString(R.string.lte_detail))
+            TelephonyManager.NETWORK_TYPE_EHRPD -> arrayOf(context.getString(R.string.ehrpd), context.getString(R.string.ehrpd_detail))
+            TelephonyManager.NETWORK_TYPE_HSPAP -> arrayOf(context.getString(R.string.hspap), context.getString(R.string.hspap_detail))
+            TelephonyManager.NETWORK_TYPE_GSM -> arrayOf(context.getString(R.string.gsm), context.getString(R.string.gsm_detail))
+            TelephonyManager.NETWORK_TYPE_TD_SCDMA -> arrayOf(context.getString(R.string.td_scdma), context.getString(R.string.td_scdma_detail))
+            TelephonyManager.NETWORK_TYPE_IWLAN -> arrayOf(context.getString(R.string.iwlan), context.getString(R.string.iwlan_detail))
+            TelephonyManager.NETWORK_TYPE_NR -> arrayOf(context.getString(R.string.nr), context.getString(R.string.nr_detail))
+            else -> arrayOf(context.getString(R.string.error), "")
+        }
+    }
+
+    fun getAdditionalNetworkInfoStringArray(overrideNetworkType: Int, context: Context) : Array<String> {
+        // Return the string array that corresponds to the override network type.
+        return when(overrideNetworkType) {
+            TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE -> arrayOf(context.getString(R.string.none), "")
+            TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA -> arrayOf(context.getString(R.string.lte_ca), context.getString(R.string.lte_ca_detail))
+            TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO -> arrayOf(context.getString(R.string.lte_advanced_pro), context.getString(R.string.lte_advanced_pro_detail))
+            TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA -> arrayOf(context.getString(R.string.nr_nsa), context.getString(R.string.nr_nsa_detail))
+            TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE -> arrayOf(context.getString(R.string.nr_nsa_mmwave), context.getString(R.string.nr_nsa_mmwave_detail))  // Can be removed once the minimum API >= 31.
+            TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED -> arrayOf(context.getString(R.string.nr_advanced), context.getString(R.string.nr_advanced_detail))
+            else -> arrayOf(context.getString(R.string.error), "")
+        }
+    }
+}
\ No newline at end of file
index 68f92284ac0194557aa22cfa4348fb3a905b6187..5d9ad3a4a76f6f7d746c9dfc6148e0ebb7fe8467 100644 (file)
@@ -35,6 +35,7 @@ import android.content.pm.PackageManager
 import android.os.Binder
 import android.os.IBinder
 import android.telephony.PhoneStateListener  // This can be replaced by `TelephonyCallback` once the minimum API >= 31.
+import android.telephony.ServiceState
 import android.telephony.TelephonyDisplayInfo
 import android.telephony.TelephonyManager
 
@@ -46,6 +47,7 @@ import androidx.work.WorkManager
 
 import com.stoutner.privacycell.R
 import com.stoutner.privacycell.activities.PrivacyCellActivity
+import com.stoutner.privacycell.helpers.ProtocolHelper
 import com.stoutner.privacycell.workers.RegisterRealtimeListenerWorker
 
 import java.util.concurrent.TimeUnit
@@ -65,7 +67,13 @@ class RealtimeMonitoringService : Service() {
 
     // Define the class variables.
     private var currentStatus = ""
+    private var voiceNetworkSecurityStatus = ProtocolHelper.UNPOPULATED
+    private var dataNetworkSecurityStatus = ProtocolHelper.UNPOPULATED
+
+    // Declare the class variables.
+    private lateinit var notificationManager: NotificationManager
     private lateinit var phoneStateListener: PhoneStateListener  // The `PhoneStateListener` can be replaced by `TelephonyCallback` once the minimum API >= 31.
+    private lateinit var privacyCellPendingIntent: PendingIntent
 
     inner class ServiceBinder : Binder() {
         // Get a copy of this service as a binder.
@@ -85,7 +93,7 @@ class RealtimeMonitoringService : Service() {
         // So, the default value is set to true, which is the safest value if the shared preferences can't be queried.
         if (sharedPreferences.getBoolean(applicationContext.getString(R.string.realtime_monitoring_key), true)) {  // Realtime monitoring is enabled.
             // Get a handle for the notification manager.
-            val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+            notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
 
             // Create a notification channel group.
             notificationManager.createNotificationChannelGroup(NotificationChannelGroup(REALTIME_MONITORING, getString(R.string.realtime_monitoring)))
@@ -126,7 +134,7 @@ class RealtimeMonitoringService : Service() {
             val privacyCellIntent = Intent(this, PrivacyCellActivity::class.java)
 
             // Create a pending intent from the Privacy Cell intent.
-            val privacyCellPendingIntent = PendingIntent.getActivity(this, 0, privacyCellIntent, PendingIntent.FLAG_IMMUTABLE)
+            privacyCellPendingIntent = PendingIntent.getActivity(this, 0, privacyCellIntent, PendingIntent.FLAG_IMMUTABLE)
 
             // Set the notification to open Privacy Cell.
             notificationBuilder.setContentIntent(privacyCellPendingIntent)
@@ -143,94 +151,36 @@ class RealtimeMonitoringService : Service() {
             // Start the foreground notification.
             startForeground(NOTIFICATION_ID, notificationBuilder.build())
 
+            // Instantiate the protocol helper.
+            val protocolHelper = ProtocolHelper()
+
             // Define the phone state listener.  The `PhoneStateListener` can be replaced by `TelephonyCallback` once the minimum API >= 31.
             phoneStateListener = object : PhoneStateListener() {
                 @Deprecated("Deprecated in Java")
-                override fun onDisplayInfoChanged(telephonyDisplayInfo: TelephonyDisplayInfo) {
+                override fun onServiceStateChanged(serviceState: ServiceState) {  // Update the voice network status.
+                    // Get the network registration info for the voice network, which is the second of the three entries (the first appears to be Wi-Fi and the third appears to be the cell data network).
+                    val networkRegistrationInfo = serviceState.networkRegistrationInfoList[1]
+
+                    // Get the consider 3G antiquated preference.
+                    val consider3gAntiquated = sharedPreferences.getBoolean(getString(R.string.consider_3g_antiquated_key), false)
+
+                    // Update the voice network security status.
+                    voiceNetworkSecurityStatus = protocolHelper.checkNetwork(networkRegistrationInfo.accessNetworkTechnology, consider3gAntiquated)
+
+                    // Populate the notification.
+                    populateNotification()
+                }
+
+                @Deprecated("Deprecated in Java")
+                override fun onDisplayInfoChanged(telephonyDisplayInfo: TelephonyDisplayInfo) {  // Update the data network status.
                     // Get the consider 3G antiquated preference.
                     val consider3gAntiquated = sharedPreferences.getBoolean(getString(R.string.consider_3g_antiquated_key), false)
 
-                    // Populate the notification according to the network type.
-                    if ((telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_NR) || (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_IWLAN) ||
-                        (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_UNKNOWN)) {  // This is a secure network.
-                        // Only update the notification if the network status has changed.
-                        if (currentStatus != SECURE_NETWORK) {
-                            // Create a secure network notification builder.
-                            val secureNetworkNotificationBuilder = Notification.Builder(applicationContext, SECURE_NETWORK)
-
-                            // Set the notification to open Privacy Cell.
-                            secureNetworkNotificationBuilder.setContentIntent(privacyCellPendingIntent)
-
-                            // Set the notification text.
-                            secureNetworkNotificationBuilder.setContentText(getString(R.string.secure_network))
-
-                            // Set the notification icon.
-                            secureNetworkNotificationBuilder.setSmallIcon(R.drawable.secure_notification_enabled)
-
-                            // Set the color.
-                            secureNetworkNotificationBuilder.setColor(getColor(R.color.blue_icon))
-
-                            // Update the notification.
-                            notificationManager.notify(NOTIFICATION_ID, secureNetworkNotificationBuilder.build())
-
-                            // Store the new network status.
-                            currentStatus = SECURE_NETWORK
-                        }
-                    } else if ((telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_LTE) || (!consider3gAntiquated && (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_1xRTT ||
-                                (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_EVDO_0) || (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_EVDO_A) ||
-                                (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_EVDO_B) || (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_EHRPD) ||
-                                (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_UMTS) || (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_TD_SCDMA) ||
-                                (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_HSDPA) || (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_HSUPA) ||
-                                (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_HSPA) || (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_HSPAP)))) {
-                                // This is an insecure network.
-                        // Only update the notification if the network status has changed.
-                        if (currentStatus != INSECURE_NETWORK) {
-                            // Create an insecure network notification builder.
-                            val insecureNetworkNotificationBuilder = Notification.Builder(applicationContext, INSECURE_NETWORK)
-
-                            // Set the notification to open Privacy Cell.
-                            insecureNetworkNotificationBuilder.setContentIntent(privacyCellPendingIntent)
-
-                            // Set the notification text.
-                            insecureNetworkNotificationBuilder.setContentText(getString(R.string.insecure_network))
-
-                            // Set the notification icon.
-                            insecureNetworkNotificationBuilder.setSmallIcon(R.drawable.insecure_notification_enabled)
-
-                            // Set the color.
-                            insecureNetworkNotificationBuilder.setColor(getColor(R.color.yellow_notification_icon))
-
-                            // Update the notification.
-                            notificationManager.notify(NOTIFICATION_ID, insecureNetworkNotificationBuilder.build())
-
-                            // Store the new network status.
-                            currentStatus = INSECURE_NETWORK
-                        }
-                    } else {  // This is an antiquated network.
-                        // Only update the notification if the network status has changed.
-                        if (currentStatus != ANTIQUATED_NETWORK) {
-                            // Create an antiquated network notification builder.
-                            val antiquatedNetworkNotificationBuilder = Notification.Builder(applicationContext, ANTIQUATED_NETWORK)
-
-                            // Set the notification to open Privacy Cell.
-                            antiquatedNetworkNotificationBuilder.setContentIntent(privacyCellPendingIntent)
-
-                            // Set the notification text.
-                            antiquatedNetworkNotificationBuilder.setContentText(getString(R.string.antiquated_network))
-
-                            // Set the notification icon.
-                            antiquatedNetworkNotificationBuilder.setSmallIcon(R.drawable.antiquated_notification_enabled)
-
-                            // Set the color.
-                            antiquatedNetworkNotificationBuilder.setColor(getColor(R.color.red_notification_icon))
-
-                            // Update the notification.
-                            notificationManager.notify(NOTIFICATION_ID, antiquatedNetworkNotificationBuilder.build())
-
-                            // Store the new network status.
-                            currentStatus = ANTIQUATED_NETWORK
-                        }
-                    }
+                    // Update the data network security status.
+                    dataNetworkSecurityStatus = protocolHelper.checkNetwork(telephonyDisplayInfo.networkType, consider3gAntiquated)
+
+                    // Populate the notification.
+                    populateNotification()
                 }
             }
 
@@ -262,7 +212,84 @@ class RealtimeMonitoringService : Service() {
             telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE)
 
             // Listen for changes to the phone state.  The `PhoneStateListener` can be replaced by `TelephonyCallback` once the minimum API >= 31.
-            telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED)
+            telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE or PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED)
+        }
+    }
+
+    fun populateNotification() {
+        // Populate the notification according to the security status.
+        if ((voiceNetworkSecurityStatus == ProtocolHelper.ANTIQUATED) || (dataNetworkSecurityStatus == ProtocolHelper.ANTIQUATED)) {  // This is an antiquated network.
+            // Only update the notification if the network status has changed.
+            if (currentStatus != ANTIQUATED_NETWORK) {
+                // Create an antiquated network notification builder.
+                val antiquatedNetworkNotificationBuilder = Notification.Builder(applicationContext, ANTIQUATED_NETWORK)
+
+                // Set the notification to open Privacy Cell.
+                antiquatedNetworkNotificationBuilder.setContentIntent(privacyCellPendingIntent)
+
+                // Set the notification text.
+                antiquatedNetworkNotificationBuilder.setContentText(getString(R.string.antiquated_network))
+
+                // Set the notification icon.
+                antiquatedNetworkNotificationBuilder.setSmallIcon(R.drawable.antiquated_notification_enabled)
+
+                // Set the color.
+                antiquatedNetworkNotificationBuilder.setColor(getColor(R.color.red_notification_icon))
+
+                // Update the notification.
+                notificationManager.notify(NOTIFICATION_ID, antiquatedNetworkNotificationBuilder.build())
+
+                // Store the new network status.
+                currentStatus = ANTIQUATED_NETWORK
+            }
+        } else if ((voiceNetworkSecurityStatus == ProtocolHelper.INSECURE) || (dataNetworkSecurityStatus == ProtocolHelper.INSECURE)) {  // This is an insecure network.
+            // Only update the notification if the network status has changed.
+            if (currentStatus != INSECURE_NETWORK) {
+                // Create an insecure network notification builder.
+                val insecureNetworkNotificationBuilder = Notification.Builder(applicationContext, INSECURE_NETWORK)
+
+                // Set the notification to open Privacy Cell.
+                insecureNetworkNotificationBuilder.setContentIntent(privacyCellPendingIntent)
+
+                // Set the notification text.
+                insecureNetworkNotificationBuilder.setContentText(getString(R.string.insecure_network))
+
+                // Set the notification icon.
+                insecureNetworkNotificationBuilder.setSmallIcon(R.drawable.insecure_notification_enabled)
+
+                // Set the color.
+                insecureNetworkNotificationBuilder.setColor(getColor(R.color.yellow_notification_icon))
+
+                // Update the notification.
+                notificationManager.notify(NOTIFICATION_ID, insecureNetworkNotificationBuilder.build())
+
+                // Store the new network status.
+                currentStatus = INSECURE_NETWORK
+            }
+        } else {  // This is a secure network.
+            // Only update the notification if the network status has changed.
+            if (currentStatus != SECURE_NETWORK) {
+                // Create a secure network notification builder.
+                val secureNetworkNotificationBuilder = Notification.Builder(applicationContext, SECURE_NETWORK)
+
+                // Set the notification to open Privacy Cell.
+                secureNetworkNotificationBuilder.setContentIntent(privacyCellPendingIntent)
+
+                // Set the notification text.
+                secureNetworkNotificationBuilder.setContentText(getString(R.string.secure_network))
+
+                // Set the notification icon.
+                secureNetworkNotificationBuilder.setSmallIcon(R.drawable.secure_notification_enabled)
+
+                // Set the color.
+                secureNetworkNotificationBuilder.setColor(getColor(R.color.blue_icon))
+
+                // Update the notification.
+                notificationManager.notify(NOTIFICATION_ID, secureNetworkNotificationBuilder.build())
+
+                // Store the new network status.
+                currentStatus = SECURE_NETWORK
+            }
         }
     }
 }
\ No newline at end of file
index cdc285018434f5bff387ff7049772437e529b117..b4720dc3ee2006f86065f346e92bf3b856efc0d3 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-  Copyright © 2021 Soren Stoutner <soren@stoutner.com>.
+  Copyright © 2021-2022 Soren Stoutner <soren@stoutner.com>.
 
   This file is part of Privacy Cell <https://www.stoutner.com/privacy-cell>.
 
@@ -48,9 +48,9 @@
                     android:orientation="vertical"
                     android:padding="15dp" >
 
-                    <!-- Stingray. -->
+                    <!-- Overall status. -->
                     <LinearLayout
-                        android:id="@+id/stingray_linearlayout"
+                        android:id="@+id/overall_status_linearlayout"
                         android:layout_height="wrap_content"
                         android:layout_width="wrap_content"
                         android:layout_gravity="center_horizontal"
@@ -58,7 +58,7 @@
                         tools:ignore="UseCompoundDrawables" >
 
                         <ImageView
-                            android:id="@+id/stingray_imageview"
+                            android:id="@+id/overall_status_imageview"
                             android:layout_width="wrap_content"
                             android:layout_height="wrap_content"
                             android:layout_gravity="center_horizontal"
@@ -67,7 +67,7 @@
                         <!-- The text color primary is only displayed if the read phone state permission is not granted.
                             The default text is replaced if the permission is not granted or the device is connected to a cell phone network. -->
                         <TextView
-                            android:id="@+id/summary_textview"
+                            android:id="@+id/overall_status_textview"
                             android:layout_height="wrap_content"
                             android:layout_width="wrap_content"
                             android:layout_gravity="center_horizontal"
@@ -94,7 +94,6 @@
                             android:layout_gravity="center_horizontal"
                             android:textAlignment="center"
                             android:layout_marginTop="30dp"
-                            android:textColor="@color/blue_text"
                             android:textSize="18sp"
                             android:textStyle="bold" />
 
                             android:layout_width="wrap_content"
                             android:layout_gravity="center_horizontal"
                             android:textAlignment="center"
-                            android:textColor="@color/blue_text"
                             android:textSize="18sp"
                             android:textStyle="bold" />
 
                             android:layout_width="wrap_content"
                             android:layout_gravity="center_horizontal"
                             android:textAlignment="center"
-                            android:textColor="@color/blue_text"
                             android:textSize="18sp"
                             android:textStyle="bold" />
 
index 356f084f126c4c036f441a637ef5ffb5ff170b04..b9d92b7e6093811b39e09a1a32019e0bba3bbabd 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-  Copyright © 2021 Soren Stoutner <soren@stoutner.com>.
+  Copyright © 2021-2022 Soren Stoutner <soren@stoutner.com>.
 
   This file is part of Privacy Cell <https://www.stoutner.com/privacy-cell>.
 
@@ -60,9 +60,9 @@
                     android:orientation="vertical"
                     android:padding="15dp" >
 
-                    <!-- Stingray. -->
+                    <!-- Overall status. -->
                     <LinearLayout
-                        android:id="@+id/stingray_linearlayout"
+                        android:id="@+id/overall_status_linearlayout"
                         android:layout_height="wrap_content"
                         android:layout_width="wrap_content"
                         android:layout_gravity="center_horizontal"
@@ -70,7 +70,7 @@
                         tools:ignore="UseCompoundDrawables" >
 
                         <ImageView
-                            android:id="@+id/stingray_imageview"
+                            android:id="@+id/overall_status_imageview"
                             android:layout_width="wrap_content"
                             android:layout_height="wrap_content"
                             android:layout_gravity="center_horizontal"
@@ -79,7 +79,7 @@
                         <!-- The text color primary is only displayed if the read phone state permission is not granted.
                             The default text is replaced if the permission is not granted or the device is connected to a cell phone network. -->
                         <TextView
-                            android:id="@+id/summary_textview"
+                            android:id="@+id/overall_status_textview"
                             android:layout_height="wrap_content"
                             android:layout_width="wrap_content"
                             android:layout_gravity="center_horizontal"
                             android:layout_gravity="center_horizontal"
                             android:textAlignment="center"
                             android:layout_marginTop="30dp"
-                            android:textColor="@color/blue_text"
                             android:textSize="18sp"
                             android:textStyle="bold" />
 
                             android:layout_width="wrap_content"
                             android:layout_gravity="center_horizontal"
                             android:textAlignment="center"
-                            android:textColor="@color/blue_text"
                             android:textSize="18sp"
                             android:textStyle="bold" />
 
                             android:layout_width="wrap_content"
                             android:layout_gravity="center_horizontal"
                             android:textAlignment="center"
-                            android:textColor="@color/blue_text"
                             android:textSize="18sp"
                             android:textStyle="bold" />
 
index fe387b11358d68dd0ff26a9e59b24e735a4586c4..ef40f915f36894351a483cceee75e9ce97f31c5f 100644 (file)
@@ -31,4 +31,5 @@
     <color name="red_notification_icon">@color/red_900</color>
     <color name="red_text">@color/salmon</color>
     <color name="yellow_notification_icon">@color/yellow_700</color>
+    <color name="yellow_text">@color/yellow_900</color>
 </resources>
\ No newline at end of file
index a26fc5cd5036c6ea56f08212f38000d2173fb254..b70bf7b2264933d9686734c7fc9d247cc5f73409 100644 (file)
@@ -31,6 +31,7 @@
     <color name="red_notification_icon">@color/red_700</color>
     <color name="red_text">@color/red_700</color>
     <color name="yellow_notification_icon">@color/yellow_700</color>
+    <color name="yellow_text">@color/yellow_900</color>
 
     <!-- Raw colors. -->
     <color name="amber_300">#FFFFD54F</color>