Fix problems with the realtime notifications. https://redmine.stoutner.com/issues/764
authorSoren Stoutner <soren@stoutner.com>
Fri, 15 Oct 2021 17:24:54 +0000 (10:24 -0700)
committerSoren Stoutner <soren@stoutner.com>
Fri, 15 Oct 2021 17:24:54 +0000 (10:24 -0700)
app/src/main/java/com/stoutner/privacycell/activities/PrivacyCellActivity.kt
app/src/main/java/com/stoutner/privacycell/services/RealtimeMonitoringService.kt
app/src/main/java/com/stoutner/privacycell/workers/RegisterRealtimeListener.kt
app/src/main/res/values-es/strings.xml
app/src/main/res/values-it/strings.xml
app/src/main/res/values/strings.xml

index 618ef569cd052a79ca5cb67ff85cf119675a60d5..13cfe7bda17cd00a996ae16b5303fb76b3160e91 100644 (file)
@@ -56,21 +56,11 @@ import com.stoutner.privacycell.services.RealtimeMonitoringService
 class PrivacyCellActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener, PhonePermissionDialog.StoragePermissionDialogListener {
     // Declare the class variables.
     private lateinit var actionBarDrawerToggle: ActionBarDrawerToggle
+    private lateinit var phoneStateListener: PhoneStateListener
 
-    // Declare the views.
+    // Declare the class views.
     private lateinit var drawerLayout: DrawerLayout
-    private lateinit var stingrayLinearLayout: LinearLayout
-    private lateinit var stingrayImageView: ImageView
     private lateinit var stingrayTextView: TextView
-    private lateinit var voiceNetworkLinearLayout: LinearLayout
-    private lateinit var voiceNetworkTextView: TextView
-    private lateinit var voiceNetworkDetailsTextView: TextView
-    private lateinit var dataNetworkLinearLayout: LinearLayout
-    private lateinit var dataNetworkTextView: TextView
-    private lateinit var dataNetworkDetailsTextView: TextView
-    private lateinit var additionalNetworkInfoLinearLayout: LinearLayout
-    private lateinit var additionalNetworkInfoTextView: TextView
-    private lateinit var additionalNetworkInfoDetailsTextView: TextView
 
     override fun onCreate(savedInstanceState: Bundle?) {
         // Run the default commands.
@@ -93,18 +83,18 @@ class PrivacyCellActivity : AppCompatActivity(), NavigationView.OnNavigationItem
         // Get handles for the views.
         drawerLayout = findViewById(R.id.drawerlayout)
         val toolbar = findViewById<Toolbar>(R.id.toolbar)
-        stingrayLinearLayout = findViewById(R.id.stingray_linearlayout)
-        stingrayImageView = findViewById(R.id.stingray_imageview)
+        val stingrayLinearLayout = findViewById<LinearLayout>(R.id.stingray_linearlayout)
+        val stingrayImageView = findViewById<ImageView>(R.id.stingray_imageview)
         stingrayTextView = findViewById(R.id.stingray_textview)
-        voiceNetworkLinearLayout = findViewById(R.id.voice_network_linearlayout)
-        voiceNetworkTextView = findViewById(R.id.voice_network)
-        voiceNetworkDetailsTextView = findViewById(R.id.voice_network_details)
-        dataNetworkLinearLayout = findViewById(R.id.data_network_linearlayout)
-        dataNetworkTextView = findViewById(R.id.data_network)
-        dataNetworkDetailsTextView = findViewById(R.id.data_network_details)
-        additionalNetworkInfoLinearLayout = findViewById(R.id.additional_network_info_linearlayout)
-        additionalNetworkInfoTextView = findViewById(R.id.additional_network_info)
-        additionalNetworkInfoDetailsTextView = findViewById(R.id.additional_network_info_details)
+        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)
+        val dataNetworkLinearLayout = findViewById<LinearLayout>(R.id.data_network_linearlayout)
+        val dataNetworkTextView = findViewById<TextView>(R.id.data_network)
+        val dataNetworkDetailsTextView = findViewById<TextView>(R.id.data_network_details)
+        val additionalNetworkInfoLinearLayout = findViewById<LinearLayout>(R.id.additional_network_info_linearlayout)
+        val additionalNetworkInfoTextView = findViewById<TextView>(R.id.additional_network_info)
+        val additionalNetworkInfoDetailsTextView = findViewById<TextView>(R.id.additional_network_info_details)
         val navigationView = findViewById<NavigationView>(R.id.navigationview)
 
         // Set the support action bar.
@@ -145,6 +135,141 @@ class PrivacyCellActivity : AppCompatActivity(), NavigationView.OnNavigationItem
             }
         })
 
+        // Define the phone state listener.
+        phoneStateListener = object : PhoneStateListener() {
+            override fun onDisplayInfoChanged(telephonyDisplayInfo: TelephonyDisplayInfo) {
+                // Populate the stingray security information.  <https://source.android.com/devices/tech/connect/acts-5g-testing>
+                if (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_NR) {  // This is a secure 5G NR SA network.
+                    // Populate the image view.
+                    stingrayImageView.setImageDrawable(AppCompatResources.getDrawable(applicationContext, R.drawable.secure_5g_nr_sa))
+
+                    // Set the text.
+                    stingrayTextView.text = getString(R.string.secure_from_stingray)
+
+                    // Set the text color.
+                    stingrayTextView.setTextColor(getColor(R.color.blue_text))
+                } else {  // This is not a secure 5G NR SA network.
+                    // Populate the image view.
+                    stingrayImageView.setImageDrawable(AppCompatResources.getDrawable(applicationContext, R.drawable.not_secure))
+
+                    // Set the text.
+                    stingrayTextView.text = getString(R.string.not_secure_from_stingray)
+
+                    // Set the text color.
+                    stingrayTextView.setTextColor(getColor(R.color.red_text))
+                }
+
+                // Get the strings that correspond to the network information.
+                val dataNetworkType = getNetworkType(telephonyDisplayInfo.networkType)
+                val additionalNetworkInfo = getAdditionalNetworkInfo(telephonyDisplayInfo.overrideNetworkType)
+
+                // 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]
+
+                // Set the stingray click listener.
+                stingrayLinearLayout.setOnClickListener {
+                    // Instantiate the stingray dialog fragment.
+                    val stingrayDialogFragment = WebViewDialog().type(WebViewDialog.STINGRAY)
+
+                    // Show the alert dialog.
+                    stingrayDialogFragment.show(supportFragmentManager, getString(R.string.stingrays))
+                }
+
+                // Set the data network click listener.
+                dataNetworkLinearLayout.setOnClickListener {
+                    // Instantiate the data network dialog fragment according to the network type.
+                    val dataNetworkDialogFragment = when (telephonyDisplayInfo.networkType) {
+                        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)
+                        TelephonyManager.NETWORK_TYPE_UMTS -> WebViewDialog().type(WebViewDialog.NETWORK_UMTS)
+                        TelephonyManager.NETWORK_TYPE_CDMA -> WebViewDialog().type(WebViewDialog.NETWORK_CDMA)
+                        TelephonyManager.NETWORK_TYPE_EVDO_0 -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_0)
+                        TelephonyManager.NETWORK_TYPE_EVDO_A -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_A)
+                        TelephonyManager.NETWORK_TYPE_1xRTT -> WebViewDialog().type(WebViewDialog.NETWORK_1xRTT)
+                        TelephonyManager.NETWORK_TYPE_HSDPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSDPA)
+                        TelephonyManager.NETWORK_TYPE_HSUPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSUPA)
+                        TelephonyManager.NETWORK_TYPE_HSPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSPA)
+                        TelephonyManager.NETWORK_TYPE_IDEN -> WebViewDialog().type(WebViewDialog.NETWORK_IDEN)
+                        TelephonyManager.NETWORK_TYPE_EVDO_B -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_B)
+                        TelephonyManager.NETWORK_TYPE_LTE -> WebViewDialog().type(WebViewDialog.NETWORK_LTE)
+                        TelephonyManager.NETWORK_TYPE_EHRPD -> WebViewDialog().type(WebViewDialog.NETWORK_EHRPD)
+                        TelephonyManager.NETWORK_TYPE_HSPAP -> WebViewDialog().type(WebViewDialog.NETWORK_HSPAP)
+                        TelephonyManager.NETWORK_TYPE_GSM -> WebViewDialog().type(WebViewDialog.NETWORK_GSM)
+                        TelephonyManager.NETWORK_TYPE_TD_SCDMA -> WebViewDialog().type(WebViewDialog.NETWORK_TD_SCDMA)
+                        TelephonyManager.NETWORK_TYPE_IWLAN -> WebViewDialog().type(WebViewDialog.NETWORK_IWLAN)
+                        TelephonyManager.NETWORK_TYPE_NR -> WebViewDialog().type(WebViewDialog.NETWORK_NR)
+                        else -> WebViewDialog().type(WebViewDialog.NETWORK_UNKNOWN)
+                    }
+
+                    // Show the alert dialog.
+                    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)
+                        else -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NR_NSA_MMWAVE)
+                    }
+
+                    // Show the alert dialog.
+                    additionalNetworkInfoDialogFragment.show(supportFragmentManager, getString(R.string.voice_network))
+                }
+            }
+
+            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]
+
+                // Get the voice network type.
+                val voiceNetworkType = getNetworkType(networkRegistrationInfo.accessNetworkTechnology)
+
+                // Populate the voice network text views.
+                voiceNetworkTextView.text = getString(R.string.voice_network, voiceNetworkType[0])
+                voiceNetworkDetailsTextView.text = voiceNetworkType[1]
+
+                // Set the voice network click listener.
+                voiceNetworkLinearLayout.setOnClickListener {
+                    // Instantiate the voice network dialog fragment according to the network type.
+                    val voiceNetworkDialogFragment = when (networkRegistrationInfo.accessNetworkTechnology) {
+                        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)
+                        TelephonyManager.NETWORK_TYPE_UMTS -> WebViewDialog().type(WebViewDialog.NETWORK_UMTS)
+                        TelephonyManager.NETWORK_TYPE_CDMA -> WebViewDialog().type(WebViewDialog.NETWORK_CDMA)
+                        TelephonyManager.NETWORK_TYPE_EVDO_0 -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_0)
+                        TelephonyManager.NETWORK_TYPE_EVDO_A -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_A)
+                        TelephonyManager.NETWORK_TYPE_1xRTT -> WebViewDialog().type(WebViewDialog.NETWORK_1xRTT)
+                        TelephonyManager.NETWORK_TYPE_HSDPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSDPA)
+                        TelephonyManager.NETWORK_TYPE_HSUPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSUPA)
+                        TelephonyManager.NETWORK_TYPE_HSPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSPA)
+                        TelephonyManager.NETWORK_TYPE_IDEN -> WebViewDialog().type(WebViewDialog.NETWORK_IDEN)
+                        TelephonyManager.NETWORK_TYPE_EVDO_B -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_B)
+                        TelephonyManager.NETWORK_TYPE_LTE -> WebViewDialog().type(WebViewDialog.NETWORK_LTE)
+                        TelephonyManager.NETWORK_TYPE_EHRPD -> WebViewDialog().type(WebViewDialog.NETWORK_EHRPD)
+                        TelephonyManager.NETWORK_TYPE_HSPAP -> WebViewDialog().type(WebViewDialog.NETWORK_HSPAP)
+                        TelephonyManager.NETWORK_TYPE_GSM -> WebViewDialog().type(WebViewDialog.NETWORK_GSM)
+                        TelephonyManager.NETWORK_TYPE_TD_SCDMA -> WebViewDialog().type(WebViewDialog.NETWORK_TD_SCDMA)
+                        TelephonyManager.NETWORK_TYPE_IWLAN -> WebViewDialog().type(WebViewDialog.NETWORK_IWLAN)
+                        TelephonyManager.NETWORK_TYPE_NR -> WebViewDialog().type(WebViewDialog.NETWORK_NR)
+                        else -> WebViewDialog().type(WebViewDialog.NETWORK_UNKNOWN)
+                    }
+
+                    // Show the alert dialog.
+                    voiceNetworkDialogFragment.show(supportFragmentManager, getString(R.string.voice_network))
+                }
+            }
+        }
+
         // Start the realtime monitoring service if it is enabled.
         if (realtimeMonitoring) {
             // Get a handle for the activity manager.
@@ -168,14 +293,14 @@ class PrivacyCellActivity : AppCompatActivity(), NavigationView.OnNavigationItem
         actionBarDrawerToggle.syncState()
     }
 
-    override fun onResume() {
+    override fun onStart() {
         // Run the default commands.
-        super.onResume()
+        super.onStart()
 
-        // Check to see if the read phone state permission has been granted.  These commands need to be run on every resume so that the listener gets reassigned as it is automatically paused.
+        // Check to see if the read phone state permission has been granted.  These commands need to be run on every start so that the listener is reregistered.
         if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {  // The storage permission has been granted.
-            // Populate Privacy Cell.
-            populatePrivacyCell(this)
+            // Register the telephony manager listener.
+            registerTelephonyManagerListener()
         } else {  // The phone permission has not been granted.
             // Check if the user has previously denied the storage permission.
             if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_PHONE_STATE)) {  // Show a dialog explaining the request first.
@@ -194,6 +319,17 @@ class PrivacyCellActivity : AppCompatActivity(), NavigationView.OnNavigationItem
         }
     }
 
+    override fun onStop() {
+        // Run the default commands.
+        super.onStop()
+
+        // Get a handle for the telephony manager.
+        val telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+
+        // Unregister the telephony manager listener.
+        telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE)
+    }
+
     override fun onNavigationItemSelected(menuItem: MenuItem) : Boolean {
         // Run the commands that correspond to the selected menu item.
         when (menuItem.itemId) {
@@ -330,7 +466,7 @@ class PrivacyCellActivity : AppCompatActivity(), NavigationView.OnNavigationItem
             // Check to see if the read phone state permission was granted.  If the dialog was canceled the grant results will be empty.
             if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {  // The read phone state permission was granted.
                 // Populate Privacy Cell.
-                populatePrivacyCell(this)
+                registerTelephonyManagerListener()
             } else {  // The read phone state permission was denied.
                 // Display the phone permission text on the main activity.
                 stingrayTextView.text = getString(R.string.phone_permission_text)
@@ -338,144 +474,12 @@ class PrivacyCellActivity : AppCompatActivity(), NavigationView.OnNavigationItem
         }
     }
 
-    private fun populatePrivacyCell(context: Context) {
+    private fun registerTelephonyManagerListener() {
         // Get a handle for the telephony manager.
         val telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
 
         // Listen to changes in the cell network state.
-        telephonyManager.listen(object : PhoneStateListener() {
-            override fun onDisplayInfoChanged(telephonyDisplayInfo: TelephonyDisplayInfo) {
-                // Populate the stingray security information.  <https://source.android.com/devices/tech/connect/acts-5g-testing>
-                if (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_NR) {  // This is a secure 5G NR SA network.
-                    // Populate the image view.
-                    stingrayImageView.setImageDrawable(AppCompatResources.getDrawable(context, R.drawable.secure_5g_nr_sa))
-
-                    // Set the text.
-                    stingrayTextView.text = getString(R.string.secure_from_stingray)
-
-                    // Set the text color.
-                    stingrayTextView.setTextColor(getColor(R.color.blue_text))
-                } else {  // This is not a secure 5G NR SA network.
-                    // Populate the image view.
-                    stingrayImageView.setImageDrawable(AppCompatResources.getDrawable(context, R.drawable.not_secure))
-
-                    // Set the text.
-                    stingrayTextView.text = getString(R.string.not_secure_from_stingray)
-
-                    // Set the text color.
-                    stingrayTextView.setTextColor(getColor(R.color.red_text))
-                }
-
-                // Get the strings that correspond to the network information.
-                val dataNetworkType = getNetworkType(telephonyDisplayInfo.networkType)
-                val additionalNetworkInfo = getAdditionalNetworkInfo(telephonyDisplayInfo.overrideNetworkType)
-
-                // 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]
-
-                // Set the stingray click listener.
-                stingrayLinearLayout.setOnClickListener {
-                    // Instantiate the stingray dialog fragment.
-                    val stingrayDialogFragment = WebViewDialog().type(WebViewDialog.STINGRAY)
-
-                    // Show the alert dialog.
-                    stingrayDialogFragment.show(supportFragmentManager, getString(R.string.stingrays))
-                }
-
-                // Set the data network click listener.
-                dataNetworkLinearLayout.setOnClickListener {
-                    // Instantiate the data network dialog fragment according to the network type.
-                    val dataNetworkDialogFragment = when (telephonyDisplayInfo.networkType) {
-                        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)
-                        TelephonyManager.NETWORK_TYPE_UMTS -> WebViewDialog().type(WebViewDialog.NETWORK_UMTS)
-                        TelephonyManager.NETWORK_TYPE_CDMA -> WebViewDialog().type(WebViewDialog.NETWORK_CDMA)
-                        TelephonyManager.NETWORK_TYPE_EVDO_0 -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_0)
-                        TelephonyManager.NETWORK_TYPE_EVDO_A -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_A)
-                        TelephonyManager.NETWORK_TYPE_1xRTT -> WebViewDialog().type(WebViewDialog.NETWORK_1xRTT)
-                        TelephonyManager.NETWORK_TYPE_HSDPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSDPA)
-                        TelephonyManager.NETWORK_TYPE_HSUPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSUPA)
-                        TelephonyManager.NETWORK_TYPE_HSPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSPA)
-                        TelephonyManager.NETWORK_TYPE_IDEN -> WebViewDialog().type(WebViewDialog.NETWORK_IDEN)
-                        TelephonyManager.NETWORK_TYPE_EVDO_B -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_B)
-                        TelephonyManager.NETWORK_TYPE_LTE -> WebViewDialog().type(WebViewDialog.NETWORK_LTE)
-                        TelephonyManager.NETWORK_TYPE_EHRPD -> WebViewDialog().type(WebViewDialog.NETWORK_EHRPD)
-                        TelephonyManager.NETWORK_TYPE_HSPAP -> WebViewDialog().type(WebViewDialog.NETWORK_HSPAP)
-                        TelephonyManager.NETWORK_TYPE_GSM -> WebViewDialog().type(WebViewDialog.NETWORK_GSM)
-                        TelephonyManager.NETWORK_TYPE_TD_SCDMA -> WebViewDialog().type(WebViewDialog.NETWORK_TD_SCDMA)
-                        TelephonyManager.NETWORK_TYPE_IWLAN -> WebViewDialog().type(WebViewDialog.NETWORK_IWLAN)
-                        TelephonyManager.NETWORK_TYPE_NR -> WebViewDialog().type(WebViewDialog.NETWORK_NR)
-                        else -> WebViewDialog().type(WebViewDialog.NETWORK_UNKNOWN)
-                    }
-
-                    // Show the alert dialog.
-                    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)
-                        else -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NR_NSA_MMWAVE)
-                    }
-
-                    // Show the alert dialog.
-                    additionalNetworkInfoDialogFragment.show(supportFragmentManager, getString(R.string.voice_network))
-                }
-            }
-
-            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]
-
-                // Get the voice network type.
-                val voiceNetworkType = getNetworkType(networkRegistrationInfo.accessNetworkTechnology)
-
-                // Populate the voice network text views.
-                voiceNetworkTextView.text = getString(R.string.voice_network, voiceNetworkType[0])
-                voiceNetworkDetailsTextView.text = voiceNetworkType[1]
-
-                // Set the voice network click listener.
-                voiceNetworkLinearLayout.setOnClickListener {
-                    // Instantiate the voice network dialog fragment according to the network type.
-                    val voiceNetworkDialogFragment = when (networkRegistrationInfo.accessNetworkTechnology) {
-                        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)
-                        TelephonyManager.NETWORK_TYPE_UMTS -> WebViewDialog().type(WebViewDialog.NETWORK_UMTS)
-                        TelephonyManager.NETWORK_TYPE_CDMA -> WebViewDialog().type(WebViewDialog.NETWORK_CDMA)
-                        TelephonyManager.NETWORK_TYPE_EVDO_0 -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_0)
-                        TelephonyManager.NETWORK_TYPE_EVDO_A -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_A)
-                        TelephonyManager.NETWORK_TYPE_1xRTT -> WebViewDialog().type(WebViewDialog.NETWORK_1xRTT)
-                        TelephonyManager.NETWORK_TYPE_HSDPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSDPA)
-                        TelephonyManager.NETWORK_TYPE_HSUPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSUPA)
-                        TelephonyManager.NETWORK_TYPE_HSPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSPA)
-                        TelephonyManager.NETWORK_TYPE_IDEN -> WebViewDialog().type(WebViewDialog.NETWORK_IDEN)
-                        TelephonyManager.NETWORK_TYPE_EVDO_B -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_B)
-                        TelephonyManager.NETWORK_TYPE_LTE -> WebViewDialog().type(WebViewDialog.NETWORK_LTE)
-                        TelephonyManager.NETWORK_TYPE_EHRPD -> WebViewDialog().type(WebViewDialog.NETWORK_EHRPD)
-                        TelephonyManager.NETWORK_TYPE_HSPAP -> WebViewDialog().type(WebViewDialog.NETWORK_HSPAP)
-                        TelephonyManager.NETWORK_TYPE_GSM -> WebViewDialog().type(WebViewDialog.NETWORK_GSM)
-                        TelephonyManager.NETWORK_TYPE_TD_SCDMA -> WebViewDialog().type(WebViewDialog.NETWORK_TD_SCDMA)
-                        TelephonyManager.NETWORK_TYPE_IWLAN -> WebViewDialog().type(WebViewDialog.NETWORK_IWLAN)
-                        TelephonyManager.NETWORK_TYPE_NR -> WebViewDialog().type(WebViewDialog.NETWORK_NR)
-                        else -> WebViewDialog().type(WebViewDialog.NETWORK_UNKNOWN)
-                    }
-
-                    // Show the alert dialog.
-                    voiceNetworkDialogFragment.show(supportFragmentManager, getString(R.string.voice_network))
-                }
-            }
-        }, PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED or PhoneStateListener.LISTEN_SERVICE_STATE)
+        telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED or PhoneStateListener.LISTEN_SERVICE_STATE)
     }
 
     private fun getNetworkType(networkType: Int) : Array<String> {
index 2d3b184abb3f56bad08b6fb3b65091b245ca285f..681a3da2b41ccb1c8f0d88f30d685533a19c790b 100644 (file)
@@ -57,18 +57,19 @@ class RealtimeMonitoringService : Service() {
 
     // Define the class variables.
     private var currentStatus = ""
+    private lateinit var phoneStateListener: PhoneStateListener
 
     inner class ServiceBinder : Binder() {
         // Get a copy of this service as a binder.
         fun getService(): RealtimeMonitoringService = this@RealtimeMonitoringService
     }
 
-    override fun onBind(intent: Intent): IBinder {
+    override fun onBind(intent: Intent?): IBinder {
         // Return a copy of the service binder.
         return ServiceBinder()
     }
 
-    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
+    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
         // Get a handle for the notification manager.
         val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
 
@@ -123,34 +124,8 @@ class RealtimeMonitoringService : Service() {
         // Start the foreground notification.
         startForeground(NOTIFICATION_ID, notificationBuilder.build())
 
-        // Register the telephony manager listener.
-        registerTelephonyManagerListener()
-
-        // Create a register realtime listener work request that fires every 15 minutes with a 1 minute initial delay.
-        val registerRealtimeListenerWorkRequest = PeriodicWorkRequestBuilder<RegisterRealtimeListener>(15, TimeUnit.MINUTES).setInitialDelay(1, TimeUnit.MINUTES).build()
-
-        // Register the realtime listener work request.
-        WorkManager.getInstance(this).enqueueUniquePeriodicWork(getString(R.string.register_listener_work_request), ExistingPeriodicWorkPolicy.REPLACE, registerRealtimeListenerWorkRequest)
-
-        // Return a sticky service.
-        return START_STICKY
-    }
-
-    fun registerTelephonyManagerListener() {
-        // Get a handle for the telephony manager.
-        val telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
-
-        // Get a handle for the notification manager.
-        val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
-
-        // Create an intent to open Privacy Cell.
-        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)
-
-        // Listen for changes to the phone state.
-        telephonyManager.listen(object : PhoneStateListener() {
+        // Define the phone state listener.
+        phoneStateListener = object : PhoneStateListener() {
             override fun onDisplayInfoChanged(telephonyDisplayInfo: TelephonyDisplayInfo) {
                 // Populate the notification according to the network type.
                 if (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_NR) {  // This is a secure 5G NR SA network.
@@ -179,7 +154,7 @@ class RealtimeMonitoringService : Service() {
                     }
                 } else {  // This is not a secure 5G NR SA network.
                     // Only update the notification if the network status has changed.
-                    if (currentStatus !=INSECURE_NETWORK) {
+                    if (currentStatus != INSECURE_NETWORK) {
                         // Create an insecure network notification builder.
                         val insecureNetworkNotificationBuilder = Notification.Builder(applicationContext, INSECURE_NETWORK)
 
@@ -203,6 +178,27 @@ class RealtimeMonitoringService : Service() {
                     }
                 }
             }
-        }, PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED)
+        }
+
+        // Create a register realtime listener work request that fires every hour.  For some reason, when the service launches it will initially register the listener and then unregister it.
+        // This periodic request will fire shortly thereafter (it fires about every hour near the beginning of the hour) and will reregister the listener, which will stick this time.
+        val registerRealtimeListenerWorkRequest = PeriodicWorkRequestBuilder<RegisterRealtimeListener>(1, TimeUnit.HOURS).build()
+
+        // Register the realtime listener work request.
+        WorkManager.getInstance(this).enqueueUniquePeriodicWork(getString(R.string.register_listener_work_request), ExistingPeriodicWorkPolicy.REPLACE, registerRealtimeListenerWorkRequest)
+
+        // Return a sticky service.
+        return START_STICKY
+    }
+
+    fun registerTelephonyManagerListener() {
+        // Get a handle for the telephony manager.
+        val telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+
+        // Cancel the current listener if it exists.
+        telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE)
+
+        // Listen for changes to the phone state.
+        telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED)
     }
 }
\ No newline at end of file
index eaa8a5512d45f37d9ce80d233c3fa606acfeb146..b2cd8346a3ea8f0cba424c0ec11f2e17f9b9d1ab 100644 (file)
@@ -35,21 +35,18 @@ import com.stoutner.privacycell.R
 import com.stoutner.privacycell.services.RealtimeMonitoringService
 
 class RegisterRealtimeListener (appContext: Context, workerParams: WorkerParameters) : Worker(appContext, workerParams) {
-    // Store the application context.
-    private val context = appContext
-
     override fun doWork(): Result {
         // Get a handle for the shared preferences.
-        val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
+        val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(applicationContext)
 
         // Get the realtime monitoring preference.  Sometimes the shared preferences can't return a value in time, because Android sucks.
         // So, the default value is set to true, which is the safest value if the shared preferences can't be queried.
-        val realtimeMonitoring = sharedPreferences.getBoolean(context.getString(R.string.realtime_monitoring_key), true)
+        val realtimeMonitoring = sharedPreferences.getBoolean(applicationContext.getString(R.string.realtime_monitoring_key), true)
 
         // Perform the functions according to the realtime monitoring status.
         if (realtimeMonitoring) {  // Realtime monitoring is enabled.
             // Get a handle for the activity manager.
-            val activityManager: ActivityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
+            val activityManager: ActivityManager = applicationContext.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
 
             // Get a list of the running service info.  The deprecated `getRunningServices()` now only returns services stared by Privacy Cell, but that is all we want to know anyway.
             val runningServiceInfoList: List<ActivityManager.RunningServiceInfo> = activityManager.getRunningServices(1)
@@ -57,7 +54,7 @@ class RegisterRealtimeListener (appContext: Context, workerParams: WorkerParamet
             // Check to see if the service is currently running.
             if (runningServiceInfoList.isEmpty()) {  // The service is currently stopped.
                 // Start the service.
-                context.startService(Intent(context, RealtimeMonitoringService::class.java))
+                applicationContext.startService(Intent(applicationContext, RealtimeMonitoringService::class.java))
             } else {  // The service is currently running.
                 // Create a service connection.
                 val serviceConnection = object : ServiceConnection {
@@ -72,7 +69,7 @@ class RegisterRealtimeListener (appContext: Context, workerParams: WorkerParamet
                         realtimeMonitoringService.registerTelephonyManagerListener()
 
                         // Unbind the service.
-                        context.unbindService(this)
+                        applicationContext.unbindService(this)
                     }
 
                     override fun onServiceDisconnected(componentName: ComponentName) {
@@ -81,11 +78,11 @@ class RegisterRealtimeListener (appContext: Context, workerParams: WorkerParamet
                 }
 
                 // Bind to the realtime monitoring service.
-                context.bindService(Intent(context, RealtimeMonitoringService::class.java), serviceConnection, 0)
+                applicationContext.bindService(Intent(applicationContext, RealtimeMonitoringService::class.java), serviceConnection, 0)
             }
         } else {  // Realtime monitoring is disabled.
             // Cancel the realtime listener work request.
-            WorkManager.getInstance(context).cancelUniqueWork(context.getString(R.string.register_listener_work_request))
+            WorkManager.getInstance(applicationContext).cancelUniqueWork(applicationContext.getString(R.string.register_listener_work_request))
         }
 
         // Return a success.
index 51db8961518f0529f3ff0621d3d73feca0152282..5747a0341e4431d53ac6ea0d8f4112fc9af46805 100644 (file)
@@ -38,6 +38,7 @@
 
     <!-- Navigation menu. -->
     <string name="settings">Ajustes</string>
+    <string name="logcat">Logcat</string>
     <string name="permissions">Permisos</string>
     <string name="privacy_policy">Política de privacidad</string>
     <string name="changelog">Registro de cambios</string>
     <string name="bottom_app_bar">Barra inferior de app</string>
     <string name="bottom_app_bar_summary">Mueve la barra de aplicaciones a la parte inferior de la pantalla.  Al cambiar esta configuración se reiniciará Privacy Cell.</string>
 
+    <!-- Logcat.  Android removes double spaces, but extra spaces can be manually specified with the Unicode `\u0020` formatting.
+        The `%1$s` code inserts variables into the displayed text and should be preserved in translation.-->
+    <string name="copy">Copiar</string>
+    <string name="save">Guardar</string>
+    <string name="clear">Limpiar</string>
+    <string name="logcat_copied">Logcat copiado.</string>
+    <string name="privacy_cell_logcat_txt">Privacy Cell Logcat.txt</string>
+    <string name="logcat_saved">%1$s guardado.</string>
+    <string name="error_saving_logcat">Error guardando logcat: \u0020 %1$s</string>
+
     <!-- Notifications. -->
     <string name="secure">Seguro</string>
     <string name="insecure">Inseguro</string>
index d3bf2130a17f7d20a7c65ef154f5c450849ce5e2..dd2198359b6541390923dff4b2fabd87a8e38db5 100644 (file)
@@ -38,6 +38,7 @@
 
     <!-- Navigation menu. -->
     <string name="settings">Impostazioni</string>
+    <string name="logcat">Logcat</string>
     <string name="permissions">Autorizzazioni</string>
     <string name="privacy_policy">Privacy Policy</string>
     <string name="changelog">Changelog</string>
     <string name="bottom_app_bar">Barra dell\'app in basso</string>
     <string name="bottom_app_bar_summary">Sposta la barra dell\'app nella parte inferiore dello schermo.  La modifica di questa impostazione provoca il riavvio di Privacy Cell.</string>
 
+    <!-- Logcat.  Android removes double spaces, but extra spaces can be manually specified with the Unicode `\u0020` formatting.
+            The `%1$s` code inserts variables into the displayed text and should be preserved in translation.-->
+    <string name="copy">Copia</string>
+    <string name="save">Salva</string>
+    <string name="clear">Cancella</string>
+    <string name="logcat_copied">Logcat copiato.</string>
+    <string name="privacy_cell_logcat_txt">Privacy Cell Logcat.txt</string>
+    <string name="logcat_saved">%1$s salvato.</string>
+    <string name="error_saving_logcat">Errore salvataggio logcat: \u0020 %1$s</string>
+
     <!-- Notifications. -->
     <string name="secure">Sicura</string>
     <string name="insecure">Insicura</string>
index 551e449957678b78c3664a801d59574b8a4a07de..c637402ffdd0c8fa39c2718040e13b5d9364c043 100644 (file)
@@ -40,6 +40,7 @@
 
     <!-- Navigation menu. -->
     <string name="settings">Settings</string>
+    <string name="logcat">Logcat</string>
     <string name="permissions">Permissions</string>
     <string name="privacy_policy">Privacy Policy</string>
     <string name="changelog">Changelog</string>
@@ -49,7 +50,6 @@
     <string name="roadmap">Roadmap</string>
     <string name="bug_tracker">Bug Tracker</string>
     <string name="forum">Forum</string>
-    <string name="logcat">Logcat</string>
     <string name="donations">Donations</string>
 
     <!-- Network types. -->
     <string name="bottom_app_bar">Bottom app bar</string>
     <string name="bottom_app_bar_summary">Move the app bar to the bottom of the screen.  Changing this setting will restart Privacy Cell.</string>
 
-    <!-- Logcat.
-        Android removes double spaces, but extra spaces can be manually specified with the Unicode `\u0020` formatting.
+    <!-- Logcat.  Android removes double spaces, but extra spaces can be manually specified with the Unicode `\u0020` formatting.
         The `%1$s` code inserts variables into the displayed text and should be preserved in translation.-->
     <string name="copy">Copy</string>
     <string name="save">Save</string>