]> gitweb.stoutner.com Git - PrivacyCell.git/blobdiff - app/src/main/java/com/stoutner/privacycell/fragments/SettingsFragment.kt
Disable swiping to dismiss realtime notifications. https://redmine.stoutner.com/issue...
[PrivacyCell.git] / app / src / main / java / com / stoutner / privacycell / fragments / SettingsFragment.kt
index 573cec3fa62fdce2024fdf6d867879a8a048ca83..9adae226fc76d8e34ae1016da741c705b01af433 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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>.
  *
 
 package com.stoutner.privacycell.fragments
 
+import android.Manifest
 import android.content.Intent
 import android.content.SharedPreferences
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener
+import android.content.pm.PackageManager
+import android.os.Build
 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
 
 import com.stoutner.privacycell.R
+import com.stoutner.privacycell.activities.PrivacyCellActivity
+import com.stoutner.privacycell.dialogs.NotificationPermissionDialog
 import com.stoutner.privacycell.services.RealtimeMonitoringService
 
 class SettingsFragment : PreferenceFragmentCompat() {
     // Declare the class variables.
-    private lateinit var sharedPreferenceChangeListener: SharedPreferences.OnSharedPreferenceChangeListener
+    private lateinit var sharedPreferenceChangeListener: OnSharedPreferenceChangeListener
 
     // Declare the class views.
     private lateinit var realtimeMonitoringPreference: Preference
+    private lateinit var secureNetworkNotificationPreference: Preference
+    private lateinit var insecureNetworkNotificationPreference: Preference
+    private lateinit var antiquatedNetworkNotificationPreference: Preference
+    private lateinit var consider3gAntiquatedPreference: Preference
     private lateinit var bottomAppBarPreference: Preference
 
     override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
@@ -46,26 +57,47 @@ class SettingsFragment : PreferenceFragmentCompat() {
         setPreferencesFromResource(R.xml.preferences, rootKey)
 
         // Get a handle for the shared preferences.
-        val sharedPreferences = preferenceScreen.sharedPreferences
+        val sharedPreferences = preferenceScreen.sharedPreferences!!
 
         // Get handles for the preferences.
         realtimeMonitoringPreference = findPreference(getString(R.string.realtime_monitoring_key))!!
-        val secureNetworkNotificationPreference = findPreference<Preference>(getString(R.string.secure_network_notification_key))!!
-        val insecureNetworkNotificationPreference = findPreference<Preference>(getString(R.string.insecure_network_notification_key))!!
+        secureNetworkNotificationPreference = findPreference(getString(R.string.secure_network_notification_key))!!
+        insecureNetworkNotificationPreference = findPreference(getString(R.string.insecure_network_notification_key))!!
+        antiquatedNetworkNotificationPreference = findPreference(getString(R.string.antiquated_network_notification_key))!!
+        consider3gAntiquatedPreference = findPreference(getString(R.string.consider_3g_antiquated_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 icons.
+                realtimeMonitoringPreference.setIcon(R.drawable.secure_notification_enabled)
+                secureNetworkNotificationPreference.setIcon(R.drawable.secure_notification_enabled)
+                insecureNetworkNotificationPreference.setIcon(R.drawable.insecure_notification_enabled)
+                antiquatedNetworkNotificationPreference.setIcon(R.drawable.antiquated_notification_enabled)
+            } else {
+                // Set the icons.
+                realtimeMonitoringPreference.setIcon(R.drawable.secure_notification_disabled)
+                secureNetworkNotificationPreference.setIcon(R.drawable.secure_notification_disabled)
+                insecureNetworkNotificationPreference.setIcon(R.drawable.insecure_notification_disabled)
+                antiquatedNetworkNotificationPreference.setIcon(R.drawable.antiquated_notification_disabled)
+            }
         } else {
-            // Set the disabled icon.
-            realtimeMonitoringPreference.setIcon(R.drawable.realtime_monitoring_disabled)
+            // Set the icons.
+            realtimeMonitoringPreference.setIcon(R.drawable.secure_notification_ghosted)
+            secureNetworkNotificationPreference.setIcon(R.drawable.secure_notification_ghosted)
+            insecureNetworkNotificationPreference.setIcon(R.drawable.insecure_notification_ghosted)
+            antiquatedNetworkNotificationPreference.setIcon(R.drawable.antiquated_notification_ghosted)
         }
 
         // Set the notification preferences to depend on the realtime monitoring preference.
         secureNetworkNotificationPreference.dependency = getString(R.string.realtime_monitoring_key)
         insecureNetworkNotificationPreference.dependency = getString(R.string.realtime_monitoring_key)
+        antiquatedNetworkNotificationPreference.dependency = getString(R.string.realtime_monitoring_key)
 
         // Create the notification intents.
         val secureNetworkNotificationIntent = Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS)
@@ -74,17 +106,26 @@ class SettingsFragment : PreferenceFragmentCompat() {
         val insecureNetworkNotificationIntent = Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS)
             .putExtra(Settings.EXTRA_APP_PACKAGE, requireContext().packageName)
             .putExtra(Settings.EXTRA_CHANNEL_ID, RealtimeMonitoringService.INSECURE_NETWORK)
+        val antiquatedNetworkNotificationIntent = Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS)
+            .putExtra(Settings.EXTRA_APP_PACKAGE, requireContext().packageName)
+            .putExtra(Settings.EXTRA_CHANNEL_ID, RealtimeMonitoringService.ANTIQUATED_NETWORK)
 
         // Set the notification preference intents.
         secureNetworkNotificationPreference.intent = secureNetworkNotificationIntent
         insecureNetworkNotificationPreference.intent = insecureNetworkNotificationIntent
+        antiquatedNetworkNotificationPreference.intent = antiquatedNetworkNotificationIntent
+
+        // Set the consider 3G antiquated preference icon.
+        if (sharedPreferences.getBoolean(getString(R.string.consider_3g_antiquated_key), false)) {
+            consider3gAntiquatedPreference.setIcon(R.drawable.antiquated_3g_enabled)
+        } else {
+            consider3gAntiquatedPreference.setIcon(R.drawable.antiquated_3g_disabled)
+        }
 
         // Set the bottom app bar preference icon.
         if (sharedPreferences.getBoolean(getString(R.string.bottom_app_bar_key), false)) {
-            // Set the enabled icon.
             bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_enabled)
         } else {
-            // Set the disabled icon.
             bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_disabled)
         }
     }
@@ -95,7 +136,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
         super.onPause()
 
         // Get a handle for the shared preferences.
-        val sharedPreferences = preferenceScreen.sharedPreferences
+        val sharedPreferences = preferenceScreen.sharedPreferences!!
 
         // Unregister the shared preference listener.
         sharedPreferences.unregisterOnSharedPreferenceChangeListener(sharedPreferenceChangeListener)
@@ -110,30 +151,63 @@ class SettingsFragment : PreferenceFragmentCompat() {
         sharedPreferenceChangeListener = getSharedPreferenceChangeListener()
 
         // Get a handle for the shared preferences.
-        val sharedPreferences = preferenceScreen.sharedPreferences
+        val sharedPreferences = preferenceScreen.sharedPreferences!!
 
         // Re-register the shared preference listener.
         sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener)
+
+        // Update the realtime monitoring preference summary.
+        updateRealtimeMonitoringSummary()
     }
 
-    private fun getSharedPreferenceChangeListener(): SharedPreferences.OnSharedPreferenceChangeListener {
+    private fun getSharedPreferenceChangeListener(): OnSharedPreferenceChangeListener {
         // Return the shared preference change listener.
-        return SharedPreferences.OnSharedPreferenceChangeListener {sharedPreferences, key ->
+        return OnSharedPreferenceChangeListener { sharedPreferences: SharedPreferences, key: String? ->
             when (key) {
                 getString(R.string.realtime_monitoring_key) -> {
                     // Update the icon.
                     if (sharedPreferences.getBoolean(getString(R.string.realtime_monitoring_key), false)) {
-                        // Set the enabled icon.
-                        realtimeMonitoringPreference.setIcon(R.drawable.realtime_monitoring_enabled)
+                        // Set the icons.
+                        realtimeMonitoringPreference.setIcon(R.drawable.secure_notification_enabled)
+                        secureNetworkNotificationPreference.setIcon(R.drawable.secure_notification_enabled)
+                        insecureNetworkNotificationPreference.setIcon(R.drawable.insecure_notification_enabled)
+                        antiquatedNetworkNotificationPreference.setIcon(R.drawable.antiquated_notification_enabled)
                     } else {
-                        // Set the disabled icon.
-                        realtimeMonitoringPreference.setIcon(R.drawable.realtime_monitoring_disabled)
+                        // Set the icons.
+                        realtimeMonitoringPreference.setIcon(R.drawable.secure_notification_disabled)
+                        secureNetworkNotificationPreference.setIcon(R.drawable.secure_notification_disabled)
+                        insecureNetworkNotificationPreference.setIcon(R.drawable.insecure_notification_disabled)
+                        antiquatedNetworkNotificationPreference.setIcon(R.drawable.antiquated_notification_disabled)
                     }
 
                     // Start or stop the service.
                     if (sharedPreferences.getBoolean(getString(R.string.realtime_monitoring_key), false)) {  // Realtime monitoring has been enabled.
-                        // Start the realtime monitoring service.
-                        requireActivity().startService(Intent(context, RealtimeMonitoringService::class.java))
+                        // Start the service according to the API.
+                        if (Build.VERSION.SDK_INT >= 33) {  // The device API is >= 33.
+                            // Check to see if the post notification has been granted.
+                            if (ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {  // The permission has been granted.
+                                // Start the realtime monitoring service.
+                                requireActivity().startService(Intent(context, RealtimeMonitoringService::class.java))
+                            } else {  // The post notification permission has not been granted.
+                                // Check if the user has previously denied the post notifications permission.
+                                if (ActivityCompat.shouldShowRequestPermissionRationale(requireActivity(), Manifest.permission.POST_NOTIFICATIONS)) {  // Show a dialog explaining the request first.
+                                    // Check to see if a notification permission dialog is already displayed.  This happens if the app is restarted while the dialog is shown.
+                                    if (requireActivity().supportFragmentManager.findFragmentByTag(getString(R.string.notification_permission)) == null) {  // No dialog is currently shown.
+                                        // Instantiate the notification permission dialog fragment.
+                                        val notificationPermissionDialogFragment = NotificationPermissionDialog()
+
+                                        // Show the notification permission alert dialog.  The permission will be requested when the dialog is closed.
+                                        notificationPermissionDialogFragment.show(requireActivity().supportFragmentManager, getString(R.string.notification_permission))
+                                    }
+                                } else {  // Show the permission request directly.
+                                    // Request the post notifications permission directly.
+                                    ActivityCompat.requestPermissions(requireActivity(), arrayOf(Manifest.permission.POST_NOTIFICATIONS), PrivacyCellActivity.NOTIFICATION_PERMISSION_REQUEST_CODE)
+                                }
+                            }
+                        } else {   // The device API is < 33.
+                            // Start the realtime monitoring service.
+                            requireActivity().startService(Intent(context, RealtimeMonitoringService::class.java))
+                        }
                     } else {  // Realtime monitoring has been disabled.
                         // Stop the realtime monitoring service.
                         requireActivity().stopService(Intent(context, RealtimeMonitoringService::class.java))
@@ -143,35 +217,64 @@ class SettingsFragment : PreferenceFragmentCompat() {
                     }
                 }
 
+                getString(R.string.consider_3g_antiquated_key) -> {
+                    // Update the icon.
+                    if (sharedPreferences.getBoolean(getString(R.string.consider_3g_antiquated_key), false)) {
+                        consider3gAntiquatedPreference.setIcon(R.drawable.antiquated_3g_enabled)
+                    } else {
+                        consider3gAntiquatedPreference.setIcon(R.drawable.antiquated_3g_disabled)
+                    }
+
+                    // Restart Privacy Cell.
+                    restartPrivacyCell()
+                }
+
                 getString(R.string.bottom_app_bar_key) -> {
                     // Update the icon.
                     if (sharedPreferences.getBoolean(getString(R.string.bottom_app_bar_key), false)) {
-                        // Set the enabled icon.
                         bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_enabled)
                     } else {
-                        // Set the disabled icon.
                         bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_disabled)
                     }
 
-                    // Create an intent to restart Privacy Cell.
-                    val restartIntent = requireActivity().parentActivityIntent!!
+                    // Restart Privacy Cell after 400 milliseconds.
+                    restartPrivacyCell()
+                }
+            }
+        }
+    }
 
-                    // `Intent.FLAG_ACTIVITY_CLEAR_TASK` removes all activities from the stack.  It requires `Intent.FLAG_ACTIVITY_NEW_TASK`.
-                    restartIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
+    private fun restartPrivacyCell() {
+        // Create an intent to restart Privacy Cell.
+        val restartIntent = requireActivity().parentActivityIntent!!
 
-                    // Create a handler to restart the activity.
-                    val restartHandler = Handler(Looper.getMainLooper())
+        // `Intent.FLAG_ACTIVITY_CLEAR_TASK` removes all activities from the stack.  It requires `Intent.FLAG_ACTIVITY_NEW_TASK`.
+        restartIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
 
-                    // Create a runnable to restart the activity.
-                    val restartRunnable = Runnable {
-                        // Restart the activity.
-                        startActivity(restartIntent)
-                    }
+        // Create a handler to restart the activity.
+        val restartHandler = Handler(Looper.getMainLooper())
 
-                    // Restart the activity after 400 milliseconds, so that the app has enough time to save the change to the preference.
-                    restartHandler.postDelayed(restartRunnable, 400)
-                }
-            }
+        // Create a runnable to restart the activity.
+        val restartRunnable = Runnable {
+            // Restart the activity.
+            startActivity(restartIntent)
+        }
+
+        // Restart the activity after 400 milliseconds, so that the app has enough time to save the change to the preference.
+        restartHandler.postDelayed(restartRunnable, 400)
+    }
+
+    fun updateRealtimeMonitoringSummary() {
+        // Update the summary according to the API.
+        if (Build.VERSION.SDK_INT >= 33) {  // The API >= 33.
+            // Set the summary according to the notification permission status.
+            if (ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED)
+                realtimeMonitoringPreference.summary = getString(R.string.realtime_monitoring_summary)
+            else
+                realtimeMonitoringPreference.summary = (getString(R.string.realtime_monitoring_summary) + " " + getString(R.string.notification_permission_denied))
+        } else {  // The API is < 33.
+            // Set the realtime monitoring summary.
+            realtimeMonitoringPreference.summary = getString(R.string.realtime_monitoring_summary)
         }
     }
-}
\ No newline at end of file
+}