package com.stoutner.privacycell.services
+import android.Manifest
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationChannelGroup
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.PhoneStateListener // This can be replaced by `TelephonyCallback` once the minimum API >= 31.
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
// Define the class variables.
private var currentStatus = ""
+ private lateinit var phoneStateListener: PhoneStateListener // The `PhoneStateListener` can be replaced by `TelephonyCallback` once the minimum API >= 31.
inner class ServiceBinder : Binder() {
// Get a copy of this service as a binder.
fun getService(): RealtimeMonitoringService = this@RealtimeMonitoringService
}
- override fun onBind(intent: Intent): IBinder {
+ 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 {
+ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
// Get a handle for the notification manager.
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// Start the foreground notification.
startForeground(NOTIFICATION_ID, notificationBuilder.build())
- // 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
-
- // 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() {
+ // Define the phone state listener. The `PhoneStateListener` can be replaced by `TelephonyCallback` once the minimum API >= 31.
+ phoneStateListener = object : PhoneStateListener() {
override fun onDisplayInfoChanged(telephonyDisplayInfo: TelephonyDisplayInfo) {
// Populate the notification according to the network type.
if (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_NR) { // This is a secure 5G NR SA network.
}
} else { // This is not a secure 5G NR SA network.
// Only update the notification if the network status has changed.
- if (currentStatus !=INSECURE_NETWORK) {
+ if (currentStatus != INSECURE_NETWORK) {
// Create an insecure network notification builder.
val insecureNetworkNotificationBuilder = Notification.Builder(applicationContext, INSECURE_NETWORK)
}
}
}
- }, PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED)
+ }
+
+ // 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)
+ }
+
+ // Return a sticky service.
+ return START_STICKY
+ }
+
+ fun registerTelephonyManagerListener() {
+ // 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. The `PhoneStateListener` can be replaced by `TelephonyCallback` once the minimum API >= 31.
+ telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE)
+
+ // Listen for changes to the phone state. The `PhoneStateListener` can be replaced by `TelephonyCallback` once the minimum API >= 31.
+ telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED)
+ }
}
}
\ No newline at end of file