Fix a crash in realtime monitoring when the READ_PHONE_STATE permission is denied...
authorSoren Stoutner <soren@stoutner.com>
Wed, 20 Oct 2021 19:43:52 +0000 (12:43 -0700)
committerSoren Stoutner <soren@stoutner.com>
Wed, 20 Oct 2021 19:43:52 +0000 (12:43 -0700)
app/src/main/assets/en/changelog.html
app/src/main/assets/es/changelog.html
app/src/main/assets/fr/changelog.html
app/src/main/assets/it/changelog.html
app/src/main/assets/ru/changelog.html
app/src/main/java/com/stoutner/privacycell/fragments/SettingsFragment.kt
app/src/main/java/com/stoutner/privacycell/services/RealtimeMonitoringService.kt
app/src/main/res/drawable/realtime_monitoring_ghosted.xml [new file with mode: 0644]
app/src/main/res/values-night/colors.xml
app/src/main/res/values/colors.xml

index b87a4071fd550ee8b0c2915ccc10380f314c61c9..206f5b54ca4776250ebcfd02a1355e8169b8287d 100644 (file)
@@ -27,8 +27,8 @@
     </head>
 
     <body>
-        <h3>1.4 (version code 5)</h3>
-        <p>18 October 2021 - minimum API 30, target API 30.</p>
+        <h3><a href="https://www.stoutner.com/privacy-cell-1-4/">1.4</a> (version code 5)</h3>
+        <p><a href="https://gitweb.stoutner.com/?p=PrivacyCell.git;a=commitdiff;h=a1d76c6e3ed465dd14385c5a37416ee30922021f">18 October 2021</a> - minimum API 30, target API 30.</p>
         <ul>
             <li>Fix problems with realtime monitoring <a href="https://redmine.stoutner.com/issues/764">crashing</a> or <a href="https://redmine.stoutner.com/issues/763">playing the wrong sound</a>.</li>
             <li>Add a <a href="https://redmine.stoutner.com/issues/768">logcat activity</a>.</li>
index c0a2426f1e83594a78d433c21c8d91af786758f4..36be6bcd218ccafbc793ff294b16f708c9ad6221 100644 (file)
@@ -29,8 +29,8 @@
     </head>
 
     <body>
-        <h3>1.4 (versión del código 5)</h3>
-        <p>18 de octubre de 2021 - API mínimo 30, API objetivo 30.</p>
+        <h3><a href="https://www.stoutner.com/privacy-cell-1-4/">1.4</a> (versión del código 5)</h3>
+        <p><a href="https://gitweb.stoutner.com/?p=PrivacyCell.git;a=commitdiff;h=a1d76c6e3ed465dd14385c5a37416ee30922021f">18 de octubre de 2021</a> - API mínimo 30, API objetivo 30.</p>
         <ul>
             <li>Solucionar los problemas de crash de la <a href="https://redmine.stoutner.com/issues/764">monitorización en tiempo real</a> o
                 <a href="https://redmine.stoutner.com/issues/763">de reproducción de un sonido incorrecto</a>.</li>
index 294a8ad61889c25cc0223b71b00f7f259064fe05..0636750d689eb5acf3391fa6e72caedf06e9eb14 100644 (file)
@@ -29,8 +29,8 @@
     </head>
 
     <body>
-        <h3>1.4 (version de code 5)</h3>
-        <p>18 October 2021 - API minimum 30, API cible 30.</p>
+        <h3><a href="https://www.stoutner.com/privacy-cell-1-4/">1.4</a> (version de code 5)</h3>
+        <p><a href="https://gitweb.stoutner.com/?p=PrivacyCell.git;a=commitdiff;h=a1d76c6e3ed465dd14385c5a37416ee30922021f">18 October 2021</a> - API minimum 30, API cible 30.</p>
         <ul>
             <li>Fix problems with realtime monitoring <a href="https://redmine.stoutner.com/issues/764">crashing</a> or <a href="https://redmine.stoutner.com/issues/763">playing the wrong sound</a>.</li>
             <li>Add a <a href="https://redmine.stoutner.com/issues/768">logcat activity</a>.</li>
index a48730187079b3d589ba4c5e5064ef478700cf82..d0e0ba191fb2c5926660c2e6cf6aaadf9d982b7c 100644 (file)
@@ -29,8 +29,8 @@
     </head>
 
     <body>
-        <h3>1.4 (versione codice 5)</h3>
-        <p>18 Ottobre 2021 - minima API 30, target API 30.</p>
+        <h3><a href="https://www.stoutner.com/privacy-cell-1-4/">1.4</a> (versione codice 5)</h3>
+        <p><a href="https://gitweb.stoutner.com/?p=PrivacyCell.git;a=commitdiff;h=a1d76c6e3ed465dd14385c5a37416ee30922021f">18 Ottobre 2021</a> - minima API 30, target API 30.</p>
         <ul>
             <li>Correzione di problemi relativi al monitoraggio in tempo reale che andava in <a href="https://redmine.stoutner.com/issues/764">crash</a> or
                 <a href="https://redmine.stoutner.com/issues/763">suonando il suono sbagliato</a>.</li>
index 184888cb8469e1d2f612231cf5009e0100aa45c1..2ccdc65b57d909e18f9900c5e4afdaf1154c8c10 100644 (file)
@@ -27,8 +27,8 @@
     </head>
 
     <body>
-        <h3>1.4 (код версии 5)</h3>
-        <p>18 октября 2021 года - минимальный API 30, целевой API 30.</p>
+        <h3><a href="https://www.stoutner.com/privacy-cell-1-4/">1.4</a> (код версии 5)</h3>
+        <p><a href="https://gitweb.stoutner.com/?p=PrivacyCell.git;a=commitdiff;h=a1d76c6e3ed465dd14385c5a37416ee30922021f">18 октября 2021 года</a> - минимальный API 30, целевой API 30.</p>
         <ul>
             <li>Устранены проблемы, связанные со <a href="https://redmine.stoutner.com/issues/764">сбоем</a> мониторинга в реальном времени или
                 <a href="https://redmine.stoutner.com/issues/763">воспроизведением некорректного звука</a>.</li>
index 573cec3fa62fdce2024fdf6d867879a8a048ca83..dd8c9c728fd08ffa4864c4c76701615a8e507bb3 100644 (file)
 
 package com.stoutner.privacycell.fragments
 
+import android.Manifest
 import android.content.Intent
 import android.content.SharedPreferences
+import android.content.pm.PackageManager
 import android.os.Bundle
 import android.os.Handler
 import android.os.Looper
 import android.provider.Settings
 
+import androidx.core.app.ActivityCompat
 import androidx.preference.Preference
 import androidx.preference.PreferenceFragmentCompat
 import androidx.work.WorkManager
@@ -54,13 +57,22 @@ class SettingsFragment : PreferenceFragmentCompat() {
         val insecureNetworkNotificationPreference = findPreference<Preference>(getString(R.string.insecure_network_notification_key))!!
         bottomAppBarPreference = findPreference(getString(R.string.bottom_app_bar_key))!!
 
-        // Set the realtime monitoring preference icon.
-        if (sharedPreferences.getBoolean(getString(R.string.realtime_monitoring_key), false)) {
-            // Set the enabled icon.
-            realtimeMonitoringPreference.setIcon(R.drawable.realtime_monitoring_enabled)
+        // Only enable the realtime monitoring preference if the READ_PHONE_STATE permission has been granted.
+        realtimeMonitoringPreference.isEnabled = (ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED)
+
+        // Set the realtime monitoring icon according to the status.
+        if (realtimeMonitoringPreference.isEnabled) {
+            // Set the realtime monitoring preference icon.
+            if (sharedPreferences.getBoolean(getString(R.string.realtime_monitoring_key), false)) {
+                // Set the enabled icon.
+                realtimeMonitoringPreference.setIcon(R.drawable.realtime_monitoring_enabled)
+            } else {
+                // Set the disabled icon.
+                realtimeMonitoringPreference.setIcon(R.drawable.realtime_monitoring_disabled)
+            }
         } else {
-            // Set the disabled icon.
-            realtimeMonitoringPreference.setIcon(R.drawable.realtime_monitoring_disabled)
+            // Set the ghosted icon.
+            realtimeMonitoringPreference.setIcon(R.drawable.realtime_monitoring_ghosted)
         }
 
         // Set the notification preferences to depend on the realtime monitoring preference.
index 681a3da2b41ccb1c8f0d88f30d685533a19c790b..23e7278c9bd3a20629fd4ebc005adb1ec12cd564 100644 (file)
@@ -19,6 +19,7 @@
 
 package com.stoutner.privacycell.services
 
+import android.Manifest
 import android.app.Notification
 import android.app.NotificationChannel
 import android.app.NotificationChannelGroup
@@ -27,12 +28,14 @@ import android.app.PendingIntent
 import android.app.Service
 import android.content.Context
 import android.content.Intent
+import android.content.pm.PackageManager
 import android.os.Binder
 import android.os.IBinder
 import android.telephony.PhoneStateListener
 import android.telephony.TelephonyDisplayInfo
 import android.telephony.TelephonyManager
 
+import androidx.core.app.ActivityCompat
 import androidx.work.ExistingPeriodicWorkPolicy
 import androidx.work.PeriodicWorkRequestBuilder
 import androidx.work.WorkManager
@@ -180,25 +183,31 @@ class RealtimeMonitoringService : Service() {
             }
         }
 
-        // 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()
+        // Check to see if the read phone state permission has been granted.
+        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
+            // Create a register realtime listener work request that fires every hour.
+            // This periodic request will fire shortly after being created (it fires about every hour near the beginning of the hour) and will reregister the listener if it gets garbage collected.
+            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)
+            // 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
+        // Check to see if the read phone state permission has been granted.
+        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
+            // 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)
+            // 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)
+            // Listen for changes to the phone state.
+            telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED)
+        }
     }
 }
\ No newline at end of file
diff --git a/app/src/main/res/drawable/realtime_monitoring_ghosted.xml b/app/src/main/res/drawable/realtime_monitoring_ghosted.xml
new file mode 100644 (file)
index 0000000..9850b29
--- /dev/null
@@ -0,0 +1,31 @@
+<!--
+  This file is derived from `security` and `5g`, which are part of the Android Material icon set.  They are released under the Apache License 2.0.
+
+  Changes copyright © 2016,2021 Soren Stoutner <soren@stoutner.com>.  The resulting image is released under the GPLv3+ license.
+
+  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/>. -->
+
+<vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="24dp"
+    android:width="24dp"
+    android:viewportHeight="256"
+    android:viewportWidth="256" >
+
+    <path
+        android:fillColor="@color/icon_ghosted"
+        android:pathData="M128,0 L23.273,46.545L23.273,116.364c-0,64.582 44.684,124.974 104.727,139.636 60.044,-14.662 104.727,-75.054 104.727,-139.636L232.727,46.545ZM54.852,76.633l48.656,0c4.541,0 8.109,3.569 8.109,8.11 0,4.541 -3.568,8.109 -8.109,8.109l-40.547,0l0,24.327l32.437,0c8.92,0 16.219,7.298 16.219,16.219l0,24.328c0,8.92 -7.298,16.219 -16.219,16.219l-40.546,0c-4.541,0 -8.11,-3.569 -8.11,-8.11 0,-4.541 3.569,-8.109 8.11,-8.109l40.546,0l0,-24.328l-40.546,0c-4.541,0 -8.11,-3.568 -8.11,-8.109l0,-40.546c0,-4.541 3.569,-8.11 8.11,-8.11zM144.054,76.633l56.765,0c4.541,0 8.109,3.569 8.109,8.11 0,4.541 -3.568,8.109 -8.109,8.109L144.054,92.852l0,64.874l48.656,0l0,-24.328l-24.328,0c-4.541,0 -8.109,-3.568 -8.109,-8.109 0,-4.541 3.568,-8.11 8.109,-8.11l32.437,0c4.541,0 8.109,3.569 8.109,8.11l0,32.437c0,8.92 -7.297,16.219 -16.218,16.219L144.054,173.945c-8.92,0 -16.219,-7.298 -16.219,-16.219L127.835,92.852c0,-8.92 7.298,-16.219 16.219,-16.219z" />
+</vector>
\ No newline at end of file
index fed68ea3d57e720e6e193719a6ef67b47e3638ce..3a15eb29cf12e6d35d5ce668355f87d6c8f4b320 100644 (file)
@@ -21,8 +21,9 @@
 <resources>
     <!-- Nicknamed colors. -->
     <color name="blue_text">@color/violet_500</color>
-    <color name="icon_enabled">@color/violet_500</color>
     <color name="icon_disabled">@color/gray_500</color>
+    <color name="icon_enabled">@color/violet_500</color>
+    <color name="icon_ghosted">@color/gray_700</color>
     <color name="logcat_icons">@color/white</color>
     <color name="red_text">@color/salmon</color>
 
     <color name="blue_700">#FF1976D2</color>
     <color name="blue_900">#FF0D47A1</color>
 
+    <color name="gray_425">#FFB7B7B7</color>
     <color name="gray_500">#FF9E9E9E</color>
     <color name="gray_600">#FF757575</color>
+    <color name="gray_700">#FF616161</color>
     <color name="gray_925">#FF202020</color>
 
     <color name="red_600">#FFE53935</color>
index 584c22da5681e7a2ac38a1bb3b0a94b193b2b6cc..95f9c46f6236d9f7d31d089784755776941f61c3 100644 (file)
@@ -21,8 +21,9 @@
 <resources>
     <!-- Nicknamed colors. -->
     <color name="blue_text">@color/blue_700</color>
-    <color name="icon_enabled">@color/blue_700</color>
     <color name="icon_disabled">@color/gray_600</color>
+    <color name="icon_enabled">@color/blue_700</color>
+    <color name="icon_ghosted">@color/gray_425</color>
     <color name="logcat_icons">@color/gray_925</color>
     <color name="red_text">@color/red_700</color>
 
     <color name="blue_700">#FF1976D2</color>
     <color name="blue_900">#FF0D47A1</color>
 
+    <color name="gray_425">#FFB7B7B7</color>
     <color name="gray_500">#FF9E9E9E</color>
     <color name="gray_600">#FF757575</color>
+    <color name="gray_700">#FF616161</color>
     <color name="gray_925">#FF202020</color>
 
     <color name="red_600">#FFE53935</color>