From 48c9e74b052366d6c0bdda7dd555f834c593c0e9 Mon Sep 17 00:00:00 2001 From: this-Aditya Date: Thu, 8 May 2025 11:57:10 +0530 Subject: [PATCH 1/3] Periodic permission observer class for logging non granted permissions --- .../org/radarbase/android/RadarService.kt | 4 ++ .../util/PeriodicPermissionObserver.kt | 65 +++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 radar-commons-android/src/main/java/org/radarbase/android/util/PeriodicPermissionObserver.kt diff --git a/radar-commons-android/src/main/java/org/radarbase/android/RadarService.kt b/radar-commons-android/src/main/java/org/radarbase/android/RadarService.kt index ae78175f5..89ee0c0c1 100644 --- a/radar-commons-android/src/main/java/org/radarbase/android/RadarService.kt +++ b/radar-commons-android/src/main/java/org/radarbase/android/RadarService.kt @@ -420,6 +420,10 @@ abstract class RadarService : LifecycleService(), ServerStatusListener, LoginLis } } + fun nonGrantedPermissions(): Set { + return needsPermissions + } + private fun updateBluetoothNeeded(newValue: Boolean) { needsBluetooth.applyIfChanged(newValue) { if (newValue) { diff --git a/radar-commons-android/src/main/java/org/radarbase/android/util/PeriodicPermissionObserver.kt b/radar-commons-android/src/main/java/org/radarbase/android/util/PeriodicPermissionObserver.kt new file mode 100644 index 000000000..04e505fa6 --- /dev/null +++ b/radar-commons-android/src/main/java/org/radarbase/android/util/PeriodicPermissionObserver.kt @@ -0,0 +1,65 @@ +package org.radarbase.android.util + +import com.google.firebase.crashlytics.ktx.crashlytics +import com.google.firebase.ktx.Firebase +import org.radarbase.android.RadarApplication.Companion.radarConfig +import org.radarbase.android.RadarService +import org.radarbase.android.config.SingleRadarConfiguration + +class PeriodicPermissionObserver(private val context: RadarService) { + private var count = 0 + private val isFirstAlarm: Boolean + get() = count <= 1 + + private val pObserverProcessor = OfflineProcessor(context) { + process = listOf(this@PeriodicPermissionObserver::observePermissions) + requestCode = PERIODIC_PERMISSION_OBSERVER_REQUEST_CODE + requestName = PERIODIC_PERMISSION_OBSERVER_REQUEST_NAME + wake = false + } + + private var observerInterval: Long = -1L + + fun start() { + pObserverProcessor.start() + configurePermissionObserver(context.radarConfig.latestConfig) + } + + private fun observePermissions() { + count += 1 + if (isFirstAlarm) return + + val permissions = context.nonGrantedPermissions() + + if (permissions.isNotEmpty()) { + Firebase.crashlytics.apply { + log("User have not granted some permissions") + setCustomKey("error_type", "permissions_not_granted") + setCustomKey("non_granted_permissions", permissions.joinToString(", ") { it }) + } + } + + } + + private fun configurePermissionObserver(config: SingleRadarConfiguration) { + observerInterval = config.getLong( + PERMISSION_OBSERVER_INTERVAL_SECONDS, + PERMISSION_OBSERVER_INTERVAL_SECONDS_DEFAULT + ) + } + + + fun stop() { + + } + + companion object { + private const val PERIODIC_PERMISSION_OBSERVER_REQUEST_CODE = 683768762 + private const val PERIODIC_PERMISSION_OBSERVER_REQUEST_NAME = + "org.radarbase.android.util.PeriodicPermissionObserver.PERIODIC_PERMISSION_OBSERVER_REQUEST_NAME" + private const val PERMISSION_OBSERVER_INTERVAL_SECONDS = + "org.radarbase.android.util.PeriodicPermissionObserver.PERMISSION_OBSERVER_INTERVAL_SECONDS" + private const val PERMISSION_OBSERVER_INTERVAL_SECONDS_DEFAULT = + 2L * ((60 * 60) * 24) // 2-DAYS + } +} \ No newline at end of file From c2c4d9a6153b3e2bd8e7b7fb7f26361ae04fc86a Mon Sep 17 00:00:00 2001 From: this-Aditya Date: Thu, 8 May 2025 13:52:42 +0530 Subject: [PATCH 2/3] Using observer in radarservice --- .../java/org/radarbase/android/RadarService.kt | 6 ++++++ .../android/util/PeriodicPermissionObserver.kt | 17 ++++++++--------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/radar-commons-android/src/main/java/org/radarbase/android/RadarService.kt b/radar-commons-android/src/main/java/org/radarbase/android/RadarService.kt index 89ee0c0c1..44124c187 100644 --- a/radar-commons-android/src/main/java/org/radarbase/android/RadarService.kt +++ b/radar-commons-android/src/main/java/org/radarbase/android/RadarService.kt @@ -118,6 +118,7 @@ abstract class RadarService : LifecycleService(), ServerStatusListener, LoginLis } } private lateinit var notificationHandler: NotificationHandler + private lateinit var periodicPermissionObserver: PeriodicPermissionObserver override fun onBind(intent: Intent): IBinder? { super.onBind(intent) @@ -155,6 +156,9 @@ abstract class RadarService : LifecycleService(), ServerStatusListener, LoginLis configuration = radarConfig providerLoader = SourceProviderLoader(plugins) broadcaster = LocalBroadcastManager.getInstance(this) + periodicPermissionObserver = PeriodicPermissionObserver(this).apply { + start() + } broadcaster.run { permissionsBroadcastReceiver = register(ACTION_PERMISSIONS_GRANTED) { _, intent -> @@ -320,6 +324,8 @@ abstract class RadarService : LifecycleService(), ServerStatusListener, LoginLis } authConnection.unbind() + periodicPermissionObserver.stop() + mConnections.asSequence() .filter(SourceProvider<*>::isBound) .forEach(SourceProvider<*>::unbind) diff --git a/radar-commons-android/src/main/java/org/radarbase/android/util/PeriodicPermissionObserver.kt b/radar-commons-android/src/main/java/org/radarbase/android/util/PeriodicPermissionObserver.kt index 04e505fa6..75d66f07e 100644 --- a/radar-commons-android/src/main/java/org/radarbase/android/util/PeriodicPermissionObserver.kt +++ b/radar-commons-android/src/main/java/org/radarbase/android/util/PeriodicPermissionObserver.kt @@ -29,16 +29,15 @@ class PeriodicPermissionObserver(private val context: RadarService) { count += 1 if (isFirstAlarm) return - val permissions = context.nonGrantedPermissions() - - if (permissions.isNotEmpty()) { - Firebase.crashlytics.apply { - log("User have not granted some permissions") - setCustomKey("error_type", "permissions_not_granted") - setCustomKey("non_granted_permissions", permissions.joinToString(", ") { it }) + context.nonGrantedPermissions().also { permissions -> + if (permissions.isNotEmpty()) { + Firebase.crashlytics.apply { + log("User have not granted some permissions") + setCustomKey("error_type", "permissions_not_granted") + setCustomKey("non_granted_permissions", permissions.joinToString(", ") { it }) + } } } - } private fun configurePermissionObserver(config: SingleRadarConfiguration) { @@ -50,7 +49,7 @@ class PeriodicPermissionObserver(private val context: RadarService) { fun stop() { - + pObserverProcessor.close() } companion object { From 04ad8e3ca213e10931c237e1f50a68472ab217ab Mon Sep 17 00:00:00 2001 From: this-Aditya Date: Thu, 8 May 2025 15:13:24 +0530 Subject: [PATCH 3/3] Also configuring the interval with update in remote configs --- .../org/radarbase/android/RadarService.kt | 2 ++ .../util/PeriodicPermissionObserver.kt | 23 ++++++++++++++----- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/radar-commons-android/src/main/java/org/radarbase/android/RadarService.kt b/radar-commons-android/src/main/java/org/radarbase/android/RadarService.kt index 44124c187..0bc433ea9 100644 --- a/radar-commons-android/src/main/java/org/radarbase/android/RadarService.kt +++ b/radar-commons-android/src/main/java/org/radarbase/android/RadarService.kt @@ -366,6 +366,8 @@ abstract class RadarService : LifecycleService(), ServerStatusListener, LoginLis } } } + + periodicPermissionObserver.configurePermissionObserver(config) } private fun hasFeatures(provider: SourceProvider<*>, packageManager: PackageManager?): Boolean { diff --git a/radar-commons-android/src/main/java/org/radarbase/android/util/PeriodicPermissionObserver.kt b/radar-commons-android/src/main/java/org/radarbase/android/util/PeriodicPermissionObserver.kt index 75d66f07e..4d43e1364 100644 --- a/radar-commons-android/src/main/java/org/radarbase/android/util/PeriodicPermissionObserver.kt +++ b/radar-commons-android/src/main/java/org/radarbase/android/util/PeriodicPermissionObserver.kt @@ -5,6 +5,9 @@ import com.google.firebase.ktx.Firebase import org.radarbase.android.RadarApplication.Companion.radarConfig import org.radarbase.android.RadarService import org.radarbase.android.config.SingleRadarConfiguration +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import java.util.concurrent.TimeUnit class PeriodicPermissionObserver(private val context: RadarService) { private var count = 0 @@ -21,30 +24,37 @@ class PeriodicPermissionObserver(private val context: RadarService) { private var observerInterval: Long = -1L fun start() { - pObserverProcessor.start() configurePermissionObserver(context.radarConfig.latestConfig) + pObserverProcessor.start() } private fun observePermissions() { count += 1 - if (isFirstAlarm) return + if (isFirstAlarm) { + logger.info("This is the first alarm, aborting it") + return + } context.nonGrantedPermissions().also { permissions -> if (permissions.isNotEmpty()) { + logger.info("Some permissions are still not granted: ${permissions.joinToString(", ") { it }}") Firebase.crashlytics.apply { - log("User have not granted some permissions") + log("User has not granted some permissions") setCustomKey("error_type", "permissions_not_granted") setCustomKey("non_granted_permissions", permissions.joinToString(", ") { it }) + recordException(RuntimeException("Some permissions have not been granted.")) } } } } - private fun configurePermissionObserver(config: SingleRadarConfiguration) { + fun configurePermissionObserver(config: SingleRadarConfiguration) { observerInterval = config.getLong( PERMISSION_OBSERVER_INTERVAL_SECONDS, PERMISSION_OBSERVER_INTERVAL_SECONDS_DEFAULT ) + + pObserverProcessor.interval(observerInterval, TimeUnit.SECONDS) } @@ -53,12 +63,13 @@ class PeriodicPermissionObserver(private val context: RadarService) { } companion object { + private val logger: Logger = LoggerFactory.getLogger(PeriodicPermissionObserver::class.java) + private const val PERIODIC_PERMISSION_OBSERVER_REQUEST_CODE = 683768762 private const val PERIODIC_PERMISSION_OBSERVER_REQUEST_NAME = "org.radarbase.android.util.PeriodicPermissionObserver.PERIODIC_PERMISSION_OBSERVER_REQUEST_NAME" private const val PERMISSION_OBSERVER_INTERVAL_SECONDS = "org.radarbase.android.util.PeriodicPermissionObserver.PERMISSION_OBSERVER_INTERVAL_SECONDS" - private const val PERMISSION_OBSERVER_INTERVAL_SECONDS_DEFAULT = - 2L * ((60 * 60) * 24) // 2-DAYS + private const val PERMISSION_OBSERVER_INTERVAL_SECONDS_DEFAULT = 2L * ((60 * 60) * 24) // 2-DAYS } } \ No newline at end of file