/*
- * Copyright © 2021-2022 Soren Stoutner <soren@stoutner.com>.
+ * Copyright 2021-2023 Soren Stoutner <soren@stoutner.com>.
*
* This file is part of Privacy Cell <https://www.stoutner.com/privacy-cell>.
*
// Set the color.
notificationBuilder.setColor(getColor(R.color.red_notification_icon))
+ // Prevent swiping to dismiss the notification. This no longer works (except on the lock screen) in API >= 34.
+ notificationBuilder.setOngoing(true)
+
// Start the foreground notification.
startForeground(NOTIFICATION_ID, notificationBuilder.build())
// Instantiate the protocol helper.
val protocolHelper = ProtocolHelper()
+ // Get a handle for the telephony manager.
+ val telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+
// 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 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()
+ // Check to see if realtime monitoring is enabled. Sometimes the system keeps running the service even when it is supposed to shut down.
+ if (sharedPreferences.getBoolean(applicationContext.getString(R.string.realtime_monitoring_key), true)) { // Realtime monitoring is enabled.
+ // 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()
+ } else { // Realtime monitoring is disabled.
+ // Cancel the current listener if it exists. The `PhoneStateListener` can be replaced by `TelephonyCallback` once the minimum API >= 31.
+ telephonyManager.listen(phoneStateListener, LISTEN_NONE)
+ }
}
@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)
-
- // Update the data network security status.
- dataNetworkSecurityStatus = protocolHelper.checkNetwork(telephonyDisplayInfo.networkType, consider3gAntiquated)
-
- // Populate the notification.
- populateNotification()
+ // Check to see if realtime monitoring is enabled. Sometimes the system keeps running the service even when it is supposed to shut down.
+ if (sharedPreferences.getBoolean(applicationContext.getString(R.string.realtime_monitoring_key), true)) { // Realtime monitoring is enabled.
+ // Get the consider 3G antiquated preference.
+ val consider3gAntiquated = sharedPreferences.getBoolean(getString(R.string.consider_3g_antiquated_key), false)
+
+ // Update the data network security status.
+ dataNetworkSecurityStatus = protocolHelper.checkNetwork(telephonyDisplayInfo.networkType, consider3gAntiquated)
+
+ // Populate the notification.
+ populateNotification()
+ } else { // Realtime monitoring is disabled.
+ // Cancel the current listener if it exists. The `PhoneStateListener` can be replaced by `TelephonyCallback` once the minimum API >= 31.
+ telephonyManager.listen(phoneStateListener, LISTEN_NONE)
+ }
}
}
// 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<RegisterRealtimeListenerWorker>(1, TimeUnit.HOURS).build()
+ // Create a register realtime listener work request that fires every fifteen minutes.
+ // This periodic request will fire shortly after being created and will reregister the listener if it gets garbage collected.
+ val registerRealtimeListenerWorkRequest = PeriodicWorkRequestBuilder<RegisterRealtimeListenerWorker>(15, TimeUnit.MINUTES).build()
// Register the realtime listener work request.
WorkManager.getInstance(this).enqueueUniquePeriodicWork(getString(R.string.register_listener_work_request), ExistingPeriodicWorkPolicy.REPLACE, registerRealtimeListenerWorkRequest)
}
fun populateNotification() {
+ // Get the list of current notifications.
+ val activeNotificationsArray = notificationManager.activeNotifications
+
+ // Check to see if there is a current notification.
+ val noCurrentNotification = activeNotificationsArray.isEmpty()
+
// 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) {
+ if ((currentStatus != ANTIQUATED_NETWORK) || noCurrentNotification) {
// Create an antiquated network notification builder.
val antiquatedNetworkNotificationBuilder = Notification.Builder(applicationContext, ANTIQUATED_NETWORK)
// Set the color.
antiquatedNetworkNotificationBuilder.setColor(getColor(R.color.red_notification_icon))
+ // Prevent swiping to dismiss the notification. This no longer works (except on the lock screen) in API >= 34.
+ antiquatedNetworkNotificationBuilder.setOngoing(true)
+
// Update the notification.
notificationManager.notify(NOTIFICATION_ID, antiquatedNetworkNotificationBuilder.build())
}
} 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) {
+ if ((currentStatus != INSECURE_NETWORK) || noCurrentNotification) {
// Create an insecure network notification builder.
val insecureNetworkNotificationBuilder = Notification.Builder(applicationContext, INSECURE_NETWORK)
// Set the color.
insecureNetworkNotificationBuilder.setColor(getColor(R.color.yellow_notification_icon))
+ // Prevent swiping to dismiss the notification. This no longer works (except on the lock screen) in API >= 34.
+ insecureNetworkNotificationBuilder.setOngoing(true)
+
// Update the notification.
notificationManager.notify(NOTIFICATION_ID, insecureNetworkNotificationBuilder.build())
}
} else { // This is a secure network.
// Only update the notification if the network status has changed.
- if (currentStatus != SECURE_NETWORK) {
+ if ((currentStatus != SECURE_NETWORK) || noCurrentNotification) {
// Create a secure network notification builder.
val secureNetworkNotificationBuilder = Notification.Builder(applicationContext, SECURE_NETWORK)
// Set the color.
secureNetworkNotificationBuilder.setColor(getColor(R.color.blue_icon))
+ // Prevent swiping to dismiss the notification. This no longer works (except on the lock screen) in API >= 34.
+ secureNetworkNotificationBuilder.setOngoing(true)
+
// Update the notification.
notificationManager.notify(NOTIFICATION_ID, secureNetworkNotificationBuilder.build())
}
}
}
-}
\ No newline at end of file
+}