import android.app.Service
import android.content.Context
import android.content.Intent
+import android.os.Binder
import android.os.IBinder
import android.telephony.PhoneStateListener
import android.telephony.TelephonyDisplayInfo
import android.telephony.TelephonyManager
+import androidx.work.ExistingPeriodicWorkPolicy
+import androidx.work.PeriodicWorkRequestBuilder
+import androidx.work.WorkManager
+
import com.stoutner.privacycell.R
import com.stoutner.privacycell.activities.PrivacyCellActivity
+import com.stoutner.privacycell.workers.RegisterRealtimeListener
+
+import java.util.concurrent.TimeUnit
// Define the class constants.
const val REALTIME_MONITORING = "realtime_monitoring"
const val NOTIFICATION_ID = 1
+const val UNKNOWN_NETWORK = "unknown_network"
class RealtimeMonitoringService : Service() {
companion object {
- // Define the public constants.
+ // Define the public constants. These are used in the settings fragment to launch intents to edit the sound that plays for each channel.
const val SECURE_NETWORK = "secure_network"
const val INSECURE_NETWORK = "insecure_network"
}
- override fun onBind(intent: Intent?): IBinder? {
- // Do nothing.
- return null
+ // Define the class variables.
+ private var currentStatus = ""
+
+ inner class ServiceBinder : Binder() {
+ // Get a copy of this service as a binder.
+ fun getService(): RealtimeMonitoringService = this@RealtimeMonitoringService
+ }
+
+ 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 {
notificationManager.createNotificationChannelGroup(NotificationChannelGroup(REALTIME_MONITORING, getString(R.string.realtime_monitoring)))
// Prepare the notification channels.
- val secureNetworkChannel = NotificationChannel(SECURE_NETWORK, getString(R.string.secure_network_channel), NotificationManager.IMPORTANCE_DEFAULT)
- val insecureNetworkChannel = NotificationChannel(INSECURE_NETWORK, getString(R.string.insecure_network_channel), NotificationManager.IMPORTANCE_DEFAULT)
+ val secureNetworkChannel = NotificationChannel(SECURE_NETWORK, getString(R.string.secure_network_channel), NotificationManager.IMPORTANCE_HIGH)
+ val insecureNetworkChannel = NotificationChannel(INSECURE_NETWORK, getString(R.string.insecure_network_channel), NotificationManager.IMPORTANCE_HIGH)
+ val unknownNetworkChannel = NotificationChannel(UNKNOWN_NETWORK, getString(R.string.unknown_network_channel), NotificationManager.IMPORTANCE_LOW)
// Set the notification channel group.
secureNetworkChannel.group = REALTIME_MONITORING
insecureNetworkChannel.group = REALTIME_MONITORING
+ unknownNetworkChannel.group = REALTIME_MONITORING
// Disable the notification dots.
secureNetworkChannel.setShowBadge(false)
insecureNetworkChannel.setShowBadge(false)
+ unknownNetworkChannel.setShowBadge(false)
- // Set the notifications to be public.
+ // Set the notifications to be public for the secure and insecure networks.
secureNetworkChannel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC
insecureNetworkChannel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC
// Create the notification channels.
notificationManager.createNotificationChannel(secureNetworkChannel)
notificationManager.createNotificationChannel(insecureNetworkChannel)
+ notificationManager.createNotificationChannel(unknownNetworkChannel)
// Create a notification builder.
- val notificationBuilder = Notification.Builder(this, INSECURE_NETWORK)
+ val notificationBuilder = Notification.Builder(this, UNKNOWN_NETWORK)
// Create an intent to open Privacy Cell.
val privacyCellIntent = Intent(this, PrivacyCellActivity::class.java)
// Start the foreground notification.
startForeground(NOTIFICATION_ID, notificationBuilder.build())
- // Get a handle for the telephony manager and the context.
+ // 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
- // Initialize the current status.
- var currentStatus = ""
+ // 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() {
}
}
}, PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED)
-
- // Return a sticky service.
- return START_STICKY
}
}
\ No newline at end of file