2 * Copyright © 2021 Soren Stoutner <soren@stoutner.com>.
4 * This file is part of Privacy Cell <https://www.stoutner.com/privacy-cell>.
6 * Privacy Cell is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * Privacy Cell is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Privacy Cell. If not, see <http://www.gnu.org/licenses/>.
20 package com.stoutner.privacycell.fragments
22 import android.content.Intent
23 import android.content.SharedPreferences
24 import android.os.Bundle
25 import android.os.Handler
26 import android.os.Looper
27 import android.provider.Settings
29 import androidx.preference.Preference
30 import androidx.preference.PreferenceFragmentCompat
31 import androidx.work.WorkManager
33 import com.stoutner.privacycell.R
34 import com.stoutner.privacycell.services.RealtimeMonitoringService
36 class SettingsFragment : PreferenceFragmentCompat() {
37 // Declare the class variables.
38 private lateinit var sharedPreferenceChangeListener: SharedPreferences.OnSharedPreferenceChangeListener
40 // Declare the class views.
41 private lateinit var realtimeMonitoringPreference: Preference
42 private lateinit var bottomAppBarPreference: Preference
44 override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
45 // Load the preferences from the XML file.
46 setPreferencesFromResource(R.xml.preferences, rootKey)
48 // Get a handle for the shared preferences.
49 val sharedPreferences = preferenceScreen.sharedPreferences
51 // Get handles for the preferences.
52 realtimeMonitoringPreference = findPreference(getString(R.string.realtime_monitoring_key))!!
53 val secureNetworkNotificationPreference = findPreference<Preference>(getString(R.string.secure_network_notification_key))!!
54 val insecureNetworkNotificationPreference = findPreference<Preference>(getString(R.string.insecure_network_notification_key))!!
55 bottomAppBarPreference = findPreference(getString(R.string.bottom_app_bar_key))!!
57 // Set the realtime monitoring preference icon.
58 if (sharedPreferences.getBoolean(getString(R.string.realtime_monitoring_key), false)) {
59 // Set the enabled icon.
60 realtimeMonitoringPreference.setIcon(R.drawable.realtime_monitoring_enabled)
62 // Set the disabled icon.
63 realtimeMonitoringPreference.setIcon(R.drawable.realtime_monitoring_disabled)
66 // Set the notification preferences to depend on the realtime monitoring preference.
67 secureNetworkNotificationPreference.dependency = getString(R.string.realtime_monitoring_key)
68 insecureNetworkNotificationPreference.dependency = getString(R.string.realtime_monitoring_key)
70 // Create the notification intents.
71 val secureNetworkNotificationIntent = Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS)
72 .putExtra(Settings.EXTRA_APP_PACKAGE, requireContext().packageName)
73 .putExtra(Settings.EXTRA_CHANNEL_ID, RealtimeMonitoringService.SECURE_NETWORK)
74 val insecureNetworkNotificationIntent = Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS)
75 .putExtra(Settings.EXTRA_APP_PACKAGE, requireContext().packageName)
76 .putExtra(Settings.EXTRA_CHANNEL_ID, RealtimeMonitoringService.INSECURE_NETWORK)
78 // Set the notification preference intents.
79 secureNetworkNotificationPreference.intent = secureNetworkNotificationIntent
80 insecureNetworkNotificationPreference.intent = insecureNetworkNotificationIntent
82 // Set the bottom app bar preference icon.
83 if (sharedPreferences.getBoolean(getString(R.string.bottom_app_bar_key), false)) {
84 // Set the enabled icon.
85 bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_enabled)
87 // Set the disabled icon.
88 bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_disabled)
92 // The listener should be unregistered when the app is paused.
93 override fun onPause() {
94 // Run the default commands.
97 // Get a handle for the shared preferences.
98 val sharedPreferences = preferenceScreen.sharedPreferences
100 // Unregister the shared preference listener.
101 sharedPreferences.unregisterOnSharedPreferenceChangeListener(sharedPreferenceChangeListener)
104 // The listener should be re-registered when the app is resumed.
105 override fun onResume() {
106 // Run the default commands.
109 // Get a new shared preference change listener.
110 sharedPreferenceChangeListener = getSharedPreferenceChangeListener()
112 // Get a handle for the shared preferences.
113 val sharedPreferences = preferenceScreen.sharedPreferences
115 // Re-register the shared preference listener.
116 sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener)
119 private fun getSharedPreferenceChangeListener(): SharedPreferences.OnSharedPreferenceChangeListener {
120 // Return the shared preference change listener.
121 return SharedPreferences.OnSharedPreferenceChangeListener {sharedPreferences, key ->
123 getString(R.string.realtime_monitoring_key) -> {
125 if (sharedPreferences.getBoolean(getString(R.string.realtime_monitoring_key), false)) {
126 // Set the enabled icon.
127 realtimeMonitoringPreference.setIcon(R.drawable.realtime_monitoring_enabled)
129 // Set the disabled icon.
130 realtimeMonitoringPreference.setIcon(R.drawable.realtime_monitoring_disabled)
133 // Start or stop the service.
134 if (sharedPreferences.getBoolean(getString(R.string.realtime_monitoring_key), false)) { // Realtime monitoring has been enabled.
135 // Start the realtime monitoring service.
136 requireActivity().startService(Intent(context, RealtimeMonitoringService::class.java))
137 } else { // Realtime monitoring has been disabled.
138 // Stop the realtime monitoring service.
139 requireActivity().stopService(Intent(context, RealtimeMonitoringService::class.java))
141 // Cancel the realtime listener work request.
142 WorkManager.getInstance(requireContext()).cancelUniqueWork(getString(R.string.register_listener_work_request))
146 getString(R.string.bottom_app_bar_key) -> {
148 if (sharedPreferences.getBoolean(getString(R.string.bottom_app_bar_key), false)) {
149 // Set the enabled icon.
150 bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_enabled)
152 // Set the disabled icon.
153 bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_disabled)
156 // Create an intent to restart Privacy Cell.
157 val restartIntent = requireActivity().parentActivityIntent!!
159 // `Intent.FLAG_ACTIVITY_CLEAR_TASK` removes all activities from the stack. It requires `Intent.FLAG_ACTIVITY_NEW_TASK`.
160 restartIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
162 // Create a handler to restart the activity.
163 val restartHandler = Handler(Looper.getMainLooper())
165 // Create a runnable to restart the activity.
166 val restartRunnable = Runnable {
167 // Restart the activity.
168 startActivity(restartIntent)
171 // Restart the activity after 400 milliseconds, so that the app has enough time to save the change to the preference.
172 restartHandler.postDelayed(restartRunnable, 400)