diff --git a/plugins/radar-android-application-status/src/main/java/org/radarbase/monitor/application/ApplicationStatusManager.kt b/plugins/radar-android-application-status/src/main/java/org/radarbase/monitor/application/ApplicationStatusManager.kt index d1a1d6712..bf0103642 100755 --- a/plugins/radar-android-application-status/src/main/java/org/radarbase/monitor/application/ApplicationStatusManager.kt +++ b/plugins/radar-android-application-status/src/main/java/org/radarbase/monitor/application/ApplicationStatusManager.kt @@ -307,6 +307,7 @@ class ApplicationStatusManager( override fun onClose() { applicationStatusExecutor.stop { this.processor.stop() + tzProcessor?.stop() } } diff --git a/radar-commons-android/src/main/java/org/radarbase/android/MainActivity.kt b/radar-commons-android/src/main/java/org/radarbase/android/MainActivity.kt index a9522bb25..b7ee9c5f9 100644 --- a/radar-commons-android/src/main/java/org/radarbase/android/MainActivity.kt +++ b/radar-commons-android/src/main/java/org/radarbase/android/MainActivity.kt @@ -30,6 +30,7 @@ import com.google.firebase.analytics.FirebaseAnalytics import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.StateFlow @@ -48,6 +49,7 @@ import org.radarbase.android.auth.AuthService import org.radarbase.android.auth.AuthServiceStateReactor import org.radarbase.android.auth.LoginListener import org.radarbase.android.auth.LoginManager +import org.radarbase.android.splash.SplashActivity import org.radarbase.android.util.BindState import org.radarbase.android.util.BluetoothEnforcer import org.radarbase.android.util.CoroutineTaskExecutor @@ -57,6 +59,7 @@ import org.radarbase.android.util.PermissionBroadcast import org.radarbase.android.util.PermissionHandler import org.radarbase.kotlin.coroutines.launchJoin import org.slf4j.LoggerFactory +import java.io.File import kotlin.time.Duration import kotlin.time.Duration.Companion.milliseconds @@ -373,22 +376,67 @@ abstract class MainActivity : AppCompatActivity(), LoginListener { * still valid. */ protected suspend fun logout(disableRefresh: Boolean) { + logger.trace("NewBroadcastTrace: now performing logout from superclass") authConnection.applyBinder { invalidate(null, disableRefresh) } + radarConfig.resetConfig() + clearAppData(this) logger.debug("Disabling Firebase Analytics") FirebaseAnalytics.getInstance(this).setAnalyticsCollectionEnabled(false) } override fun loginSucceeded(manager: LoginManager?, authState: AppAuthState) = Unit - override fun logoutSucceeded(manager: LoginManager?, authState: AppAuthState) { + override suspend fun logoutSucceeded(manager: LoginManager?, authState: AppAuthState) { + logger.trace("NewBroadcastTrace: Starting splash 1") + delay(1000) + logger.trace("NewBroadcastTrace: Starting splash 2") logger.info("Starting SplashActivity") - val intent = packageManager.getLaunchIntentForPackage(BuildConfig.LIBRARY_PACKAGE_NAME) ?: return - startActivity(intent.apply { - flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_TASK_ON_HOME or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP - }) - finish() + try { + val intent = packageManager.getLaunchIntentForPackage(packageName) + intent ?: return + startActivity(intent.apply { + flags = + Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_TASK_ON_HOME or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP + }) + logger.trace("NewBroadcastTrace: Started splash and now finishing") + finish() + logger.trace("NewBroadcastTrace: Started splash and now finished") + } catch (ex: Exception) { + logger.trace("NewBroadcastTrace: Exception when starting splash: $ex") + } finally { + logger.info("NewBroadcastTrace: Logout succeeded method completed") + } + } + + private fun clearAppData(context: Context) { + clearCache(context) + clearFilesDir(context) + } + + private fun clearFilesDir(context: Context) { + val filesDir = context.filesDir + deleteFilesInDirectory(filesDir) + } + + private fun clearCache(context: Context) { + val cacheDir = context.cacheDir + deleteFilesInDirectory(cacheDir) } + private fun deleteFilesInDirectory(directory: File) { + if (directory.isDirectory) { + val children = directory.listFiles() + if (children != null) { + for (child in children) { + if (child.absolutePath.toString().contains("firebase")) return + deleteFilesInDirectory(child) + } + } + } + directory.delete() + } + + companion object { private val logger = LoggerFactory.getLogger(MainActivity::class.java) diff --git a/radar-commons-android/src/main/java/org/radarbase/android/RadarConfiguration.kt b/radar-commons-android/src/main/java/org/radarbase/android/RadarConfiguration.kt index d36b94315..b2f0df366 100644 --- a/radar-commons-android/src/main/java/org/radarbase/android/RadarConfiguration.kt +++ b/radar-commons-android/src/main/java/org/radarbase/android/RadarConfiguration.kt @@ -63,10 +63,12 @@ interface RadarConfiguration { */ suspend fun forceFetch() + suspend fun resetConfig() + /** * Adds base URL from auth state to configuration. */ - suspend fun updateWithAuthState(context: Context, appAuthState: AppAuthState?) + suspend fun updateWithAuthState(context: Context, appAuthState: AppAuthState?, isLogoutCall: Boolean = false) companion object { const val RADAR_CONFIGURATION_CHANGED = "org.radarcns.android.RadarConfiguration.CHANGED" 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 1b8513655..56df474df 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 @@ -58,7 +58,6 @@ import org.radarbase.android.kafka.ServerStatusListener import org.radarbase.android.kafka.TopicSendReceipt import org.radarbase.android.source.* import org.radarbase.android.util.* -import org.radarbase.android.util.BluetoothEnforcer.Companion import org.radarbase.android.util.ManagedServiceConnection.Companion.serviceConnection import org.radarbase.android.util.NotificationHandler.Companion.NOTIFICATION_CHANNEL_INFO import org.radarbase.android.util.PermissionHandler.Companion.isPermissionGranted @@ -238,9 +237,6 @@ abstract class RadarService : LifecycleService(), ServerStatusListener, LoginLis launch { configuration.config.collect(::configure) } - launch { - - } } bluetoothReceiver = BluetoothStateReceiver(this) { enabled -> @@ -306,6 +302,8 @@ abstract class RadarService : LifecycleService(), ServerStatusListener, LoginLis it.close() sourceRegistrar = null } + (dataHandler as TableDataHandler).stop() + dataHandler = null } recordTrackerJob?.cancel() statusTrackerJob?.cancel() @@ -596,7 +594,18 @@ abstract class RadarService : LifecycleService(), ServerStatusListener, LoginLis } } - override fun logoutSucceeded(manager: LoginManager?, authState: AppAuthState) = Unit + override suspend fun logoutSucceeded(manager: LoginManager?, authState: AppAuthState) { + radarExecutor.execute { + updateProviders(authState, configuration.latestConfig) + val oldProviders = mConnections + removeProviders(mConnections.toSet()) + oldProviders.forEach { + it.stopService() + } + stopForeground(STOP_FOREGROUND_REMOVE) + stopSelf() + } + } private fun removeProviders(sourceProviders: Set>) { if (sourceProviders.isEmpty()) { @@ -770,8 +779,6 @@ abstract class RadarService : LifecycleService(), ServerStatusListener, LoginLis private val logger = LoggerFactory.getLogger(RadarService::class.java) private const val RADAR_PACKAGE = "org.radarbase.android" - const val ACTION_PROVIDERS_UPDATED = "$RADAR_PACKAGE.ACTION_PROVIDERS_UPDATED" - const val ACTION_CHECK_PERMISSIONS = "$RADAR_PACKAGE.ACTION_CHECK_PERMISSIONS" const val EXTRA_PERMISSIONS = "$RADAR_PACKAGE.EXTRA_PERMISSIONS" diff --git a/radar-commons-android/src/main/java/org/radarbase/android/auth/AuthService.kt b/radar-commons-android/src/main/java/org/radarbase/android/auth/AuthService.kt index 40c0a1ed6..daa2e9c6d 100644 --- a/radar-commons-android/src/main/java/org/radarbase/android/auth/AuthService.kt +++ b/radar-commons-android/src/main/java/org/radarbase/android/auth/AuthService.kt @@ -59,6 +59,7 @@ abstract class AuthService : LifecycleService(), LoginListener { private val serviceMutex: Mutex = Mutex(false) private val registryTweakMutex: Mutex = Mutex(false) private val authUpdateMutex: Mutex = Mutex(false) + private var shouldUpdateAuth: AtomicBoolean = AtomicBoolean(true) private var needLoadedState: AtomicBoolean = AtomicBoolean(true) @@ -99,6 +100,7 @@ abstract class AuthService : LifecycleService(), LoginListener { override fun onCreate() { super.onCreate() + shouldUpdateAuth = AtomicBoolean(true) networkConnectedListener = NetworkConnectedReceiver(this) executor.start() @@ -135,8 +137,10 @@ abstract class AuthService : LifecycleService(), LoginListener { authState .collectLatest { state -> logger.trace("Collected AppAuth: {}", state) - radarConfig.updateWithAuthState(this@AuthService, state) - } + if (shouldUpdateAuth.get()) { + radarConfig.updateWithAuthState(this@AuthService, state) + } + } } launch(Dispatchers.Default) { networkConnectedListener.monitor() @@ -185,6 +189,20 @@ abstract class AuthService : LifecycleService(), LoginListener { } } } + launch(Dispatchers.Default) { + authStateLogout + .collectLatest { + logger.info("Logout succeeded") + shouldUpdateAuth = AtomicBoolean(false) + val clearedState = latestAppAuth.reset() + _authState.value = clearedState + authSerialization.remove() + callListeners { + it.listener.logoutSucceeded(null, clearedState) + } + radarConfig.updateWithAuthState(this@AuthService, clearedState, true) + } + } } } } @@ -235,6 +253,10 @@ abstract class AuthService : LifecycleService(), LoginListener { suspend fun refreshIfOnline() { executor.execute { logger.debug("Refreshing if online") + if (!shouldUpdateAuth.get()) { + logger.debug("Performing logout aborting refresh") + return@execute + } for (i in 1..3) { if (!isNetworkStatusReceived) { delay(100) @@ -345,7 +367,7 @@ abstract class AuthService : LifecycleService(), LoginListener { _authState.value = authState } - override fun logoutSucceeded(manager: LoginManager?, authState: AppAuthState) { + override suspend fun logoutSucceeded(manager: LoginManager?, authState: AppAuthState) { lifecycleScope.launch { _authStateLogout.emit(AuthLoginListener.AuthStateLogout(manager, authState)) } @@ -405,6 +427,7 @@ abstract class AuthService : LifecycleService(), LoginListener { suspend fun invalidate(token: String?, disableRefresh: Boolean) { executor.execute { + logger.trace("NewBroadcastTrace: Invalidating auth state") updateState { auth -> logger.info("Invalidating authentication state") if (token != null && token != auth.token) return@updateState @@ -476,6 +499,7 @@ abstract class AuthService : LifecycleService(), LoginListener { override fun onBind(intent: Intent): IBinder? { super.onBind(intent) + shouldUpdateAuth = AtomicBoolean(true) return AuthServiceBinder() } diff --git a/radar-commons-android/src/main/java/org/radarbase/android/auth/LoginActivity.kt b/radar-commons-android/src/main/java/org/radarbase/android/auth/LoginActivity.kt index 780fac9fb..a81861545 100644 --- a/radar-commons-android/src/main/java/org/radarbase/android/auth/LoginActivity.kt +++ b/radar-commons-android/src/main/java/org/radarbase/android/auth/LoginActivity.kt @@ -153,6 +153,8 @@ abstract class LoginActivity : AppCompatActivity(), LoginListener { finish() } + override suspend fun logoutSucceeded(manager: LoginManager?, authState: AppAuthState) = Unit + companion object { private val logger = LoggerFactory.getLogger(LoginActivity::class.java) const val ACTION_LOGIN = "org.radarcns.auth.LoginActivity.login" diff --git a/radar-commons-android/src/main/java/org/radarbase/android/auth/LoginListener.kt b/radar-commons-android/src/main/java/org/radarbase/android/auth/LoginListener.kt index d80773695..3d8a73477 100644 --- a/radar-commons-android/src/main/java/org/radarbase/android/auth/LoginListener.kt +++ b/radar-commons-android/src/main/java/org/radarbase/android/auth/LoginListener.kt @@ -42,5 +42,5 @@ interface LoginListener { */ fun loginFailed(manager: LoginManager?, ex: Exception?) - fun logoutSucceeded(manager: LoginManager?, authState: AppAuthState) + suspend fun logoutSucceeded(manager: LoginManager?, authState: AppAuthState) } diff --git a/radar-commons-android/src/main/java/org/radarbase/android/auth/portal/ManagementPortalLoginManager.kt b/radar-commons-android/src/main/java/org/radarbase/android/auth/portal/ManagementPortalLoginManager.kt index 4d3938142..d3c828d50 100644 --- a/radar-commons-android/src/main/java/org/radarbase/android/auth/portal/ManagementPortalLoginManager.kt +++ b/radar-commons-android/src/main/java/org/radarbase/android/auth/portal/ManagementPortalLoginManager.kt @@ -155,6 +155,7 @@ class ManagementPortalLoginManager( if (authState.authenticationSource != SOURCE_TYPE) return if (disableRefresh) { authState.clear() + listener.logoutSucceeded(this@ManagementPortalLoginManager, AppAuthState()) } else authState.invalidate() } diff --git a/radar-commons-android/src/main/java/org/radarbase/android/config/AppConfigRadarConfiguration.kt b/radar-commons-android/src/main/java/org/radarbase/android/config/AppConfigRadarConfiguration.kt index 131d84436..8bc641e83 100644 --- a/radar-commons-android/src/main/java/org/radarbase/android/config/AppConfigRadarConfiguration.kt +++ b/radar-commons-android/src/main/java/org/radarbase/android/config/AppConfigRadarConfiguration.kt @@ -88,7 +88,7 @@ class AppConfigRadarConfiguration( } } - override suspend fun doFetch(maxCacheAge: Long) { + override suspend fun doFetch(maxCacheAgeMillis: Long) { val (client, appConfig) = configMutex.withLock { Pair(client, appConfig) } @@ -175,6 +175,11 @@ class AppConfigRadarConfiguration( } } + override suspend fun reset() { + status.value = RadarConfiguration.RemoteConfigStatus.INITIAL + auth = null + } + private suspend fun updateConfiguration(auth: AppAuthState?, config: SingleRadarConfiguration?) { val appConfig = config?.let { value -> val serverConfig = value.optString(BASE_URL_KEY) { baseUrl -> diff --git a/radar-commons-android/src/main/java/org/radarbase/android/config/CombinedRadarConfig.kt b/radar-commons-android/src/main/java/org/radarbase/android/config/CombinedRadarConfig.kt index 8324f9ddb..2b0706d87 100644 --- a/radar-commons-android/src/main/java/org/radarbase/android/config/CombinedRadarConfig.kt +++ b/radar-commons-android/src/main/java/org/radarbase/android/config/CombinedRadarConfig.kt @@ -10,9 +10,12 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.cancelAndJoin import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch +import kotlinx.coroutines.sync.Mutex import org.radarbase.android.RadarConfiguration import org.radarbase.android.RadarConfiguration.Companion.BASE_URL_KEY import org.radarbase.android.RadarConfiguration.Companion.FETCH_TIMEOUT_MS_DEFAULT @@ -29,6 +32,7 @@ import org.radarbase.android.RadarConfiguration.RemoteConfigStatus.UNAVAILABLE import org.radarbase.android.auth.AppAuthState import org.radarbase.android.auth.portal.GetSubjectParser.Companion.externalUserId import org.radarbase.android.auth.portal.GetSubjectParser.Companion.humanReadableUserId +import org.radarbase.android.config.FirebaseRemoteConfiguration.Companion import org.radarbase.kotlin.coroutines.flow.zipAll import org.radarbase.kotlin.coroutines.launchJoin import org.slf4j.LoggerFactory @@ -56,28 +60,45 @@ class CombinedRadarConfig( private val job = SupervisorJob() private val configScope = CoroutineScope(coroutineContext + job + CoroutineName("CombinedConfig")) + private val updateStateMutex = Mutex() + private var lastAppAuth: AppAuthState? = null init { configScope.launch { launch { + logger.trace("RadarConfigTrace: ---updateConfig(launch)") updateConfig() + logger.trace("RadarConfigTrace: ---updateConfig(land)") } launch { + logger.trace("RadarConfigTrace: ---collectStatus(launch)") collectStatus() + logger.trace("RadarConfigTrace: ---collectStatus(land)") } launch { + logger.trace("RadarConfigTrace: ---collectConfig(launch)") collectConfig() + logger.trace("RadarConfigTrace: ---collectConfig(land)") } launch { + logger.trace("RadarConfigTrace: ---prepareConfig(launch)") propagateConfig() + logger.trace("RadarConfigTrace: ---prepareConfig(land)") } } } private suspend fun collectStatus() { - remoteConfigs.map { it.status } - .zipAll() - .collect { allStatus -> +// remoteConfigs.map { it.status } +// .zipAll() +// remoteConfigs.first { +// it is FirebaseRemoteConfiguration +// }.status.map { +// listOf(it, UNAVAILABLE) +// } + combine(remoteConfigs.map { it.status }) { allStatus -> + allStatus.toList() + }.collect { allStatus -> status.value = when { FETCHING in allStatus -> FETCHING FETCHED in allStatus && allStatus.all { it == FETCHED || it == UNAVAILABLE } -> FETCHED @@ -87,13 +108,20 @@ class CombinedRadarConfig( INITIAL in allStatus -> INITIAL else -> UNAVAILABLE } + logger.trace( + "RadarConfigTrace: CombinedRadarConfig::CollectStatus: value of both states: {}", + allStatus + ) } } private suspend fun collectConfig() { status .filter { it == FETCHED } - .collect { updateConfig(it) } + .collect { + updateConfig(it) + logger.trace("RadarConfigTrace: CombinedRadarConfig::collectConfig: status: {}", it) + } } private suspend fun propagateConfig() { @@ -110,16 +138,21 @@ class CombinedRadarConfig( status: RadarConfiguration.RemoteConfigStatus = this.status.value, ) { val newConfig = readConfig(status) + logger.trace("RadarConfigTrace: CombinedRadarConfig::updateConfig ({})", status) if (newConfig != latestConfig) { if (newConfig.status != latestConfig.status) { logger.info("Updating config status to {}", newConfig.status) + logger.trace("RadarConfigTrace: CombinedRadarConfig::updateConfig, new status: {}", newConfig.status) } if (newConfig.config != latestConfig.config) { logger.info("Updating config to {}", newConfig) + logger.trace("RadarConfigTrace: CombinedRadarConfig::updateConfig, new config added") } latestConfig = newConfig } else { logger.info("No change to config. Skipping.") + logger.trace("RadarConfigTrace: CombinedRadarConfig::updateConfig, no changes") + } } @@ -149,17 +182,24 @@ class CombinedRadarConfig( } override suspend fun forceFetch() = remoteConfigs.forEach { + logger.trace("RadarConfigTrace: CombinedRadarConfig::forceFetch ({})", it) it.forceFetch() } + override suspend fun resetConfig() { + status.value = RadarConfiguration.RemoteConfigStatus.INITIAL + localConfig.clearLocalConfig() + } + override fun toString(): String = latestConfig.toString() - override suspend fun updateWithAuthState(context: Context, appAuthState: AppAuthState?) { - val enableAnalytics = appAuthState?.isPrivacyPolicyAccepted == true + override suspend fun updateWithAuthState(context: Context, appAuthState: AppAuthState?, isLogoutCall: Boolean) { + if (appAuthState == null || appAuthState == lastAppAuth) return + + val enableAnalytics = appAuthState.isPrivacyPolicyAccepted logger.debug("Setting Firebase Analytics enabled: {}", enableAnalytics) FirebaseAnalytics.getInstance(context).setAnalyticsCollectionEnabled(enableAnalytics) - appAuthState ?: return val baseUrl = appAuthState.baseUrl val projectId = appAuthState.projectId @@ -189,6 +229,13 @@ class CombinedRadarConfig( } persistChanges() + + if (isLogoutCall) { + latestConfig = SingleRadarConfiguration(INITIAL, emptyMap()) + status.value = INITIAL + return + } + remoteConfigs.forEach { it.updateWithAuthState(appAuthState) } diff --git a/radar-commons-android/src/main/java/org/radarbase/android/config/FirebaseRemoteConfiguration.kt b/radar-commons-android/src/main/java/org/radarbase/android/config/FirebaseRemoteConfiguration.kt index 6952bd3b2..1eecdf5ed 100644 --- a/radar-commons-android/src/main/java/org/radarbase/android/config/FirebaseRemoteConfiguration.kt +++ b/radar-commons-android/src/main/java/org/radarbase/android/config/FirebaseRemoteConfiguration.kt @@ -35,10 +35,11 @@ import org.slf4j.LoggerFactory import java.util.concurrent.atomic.AtomicBoolean @Suppress("unused") -class FirebaseRemoteConfiguration(private val context: Context, inDevelopmentMode: Boolean, @XmlRes defaultSettings: Int) : RemoteConfig { +class FirebaseRemoteConfiguration(private val context: Context, inDebugMode: Boolean, @XmlRes defaultSettings: Int) : RemoteConfig { + private val firebase = FirebaseRemoteConfig.getInstance().apply { setDefaultsAsync(defaultSettings) - isInDevelopmentMode = inDevelopmentMode + isInDevelopmentMode = inDebugMode fetch() } @@ -46,6 +47,7 @@ class FirebaseRemoteConfiguration(private val context: Context, inDevelopmentMod private val onFailureListener: OnFailureListener = OnFailureListener { ex -> logger.info("Failed to fetch Firebase config", ex) + logger.trace("RadarConfigTrace: FirebaseRemoteConfig::fetchingFailed (Status Failed)") status.value = RadarConfiguration.RemoteConfigStatus.ERROR } private val hasChange: AtomicBoolean = AtomicBoolean(false) @@ -69,6 +71,7 @@ class FirebaseRemoteConfiguration(private val context: Context, inDevelopmentMod .toMap() status.value = RadarConfiguration.RemoteConfigStatus.FETCHED + logger.trace("RadarConfigTrace: FirebaseRemoteConfig::fetchingSuccessful (Status Fetched)") } .addOnFailureListener(onFailureListener) } @@ -85,12 +88,14 @@ class FirebaseRemoteConfiguration(private val context: Context, inDevelopmentMod * @return fetch task or null status is [RadarConfiguration.RemoteConfigStatus.UNAVAILABLE]. */ override suspend fun doFetch(maxCacheAgeMillis: Long) { + logger.trace("RadarConfigTrace: FirebaseRemoteConfig::doFetch (start). Is in development mode?: {}", isInDevelopmentMode) if (status.value == RadarConfiguration.RemoteConfigStatus.UNAVAILABLE) { return } val task = firebase.fetch(maxCacheAgeMillis / 1000L) synchronized(this) { status.value = RadarConfiguration.RemoteConfigStatus.FETCHING + logger.trace("RadarConfigTrace: FirebaseRemoteConfig::doFetch (Status: Fetching)Is in development mode?: {}", isInDevelopmentMode) task.addOnSuccessListener(onFetchCompleteHandler) task.addOnFailureListener(onFailureListener) } @@ -115,6 +120,10 @@ class FirebaseRemoteConfiguration(private val context: Context, inDevelopmentMod // do nothing } + override suspend fun reset() { + status.value = RadarConfiguration.RemoteConfigStatus.INITIAL + } + companion object { private val logger = LoggerFactory.getLogger(FirebaseRemoteConfiguration::class.java) private const val FIREBASE_FETCH_TIMEOUT_MS_DEFAULT = 12 * 60 * 60 * 1000L diff --git a/radar-commons-android/src/main/java/org/radarbase/android/config/LocalConfig.kt b/radar-commons-android/src/main/java/org/radarbase/android/config/LocalConfig.kt index 92bacd7b2..99e6c9457 100644 --- a/radar-commons-android/src/main/java/org/radarbase/android/config/LocalConfig.kt +++ b/radar-commons-android/src/main/java/org/radarbase/android/config/LocalConfig.kt @@ -24,4 +24,6 @@ interface LocalConfig { operator fun get(key: String): String? operator fun contains(key: String): Boolean fun toMap(): Map + + suspend fun clearLocalConfig() } diff --git a/radar-commons-android/src/main/java/org/radarbase/android/config/LocalConfiguration.kt b/radar-commons-android/src/main/java/org/radarbase/android/config/LocalConfiguration.kt index 622b248b4..0a031a60b 100644 --- a/radar-commons-android/src/main/java/org/radarbase/android/config/LocalConfiguration.kt +++ b/radar-commons-android/src/main/java/org/radarbase/android/config/LocalConfiguration.kt @@ -67,6 +67,14 @@ class LocalConfiguration(context: Context) : LocalConfig { } } + override suspend fun clearLocalConfig() { + val editor = preferences.edit() + preferences.all.clear() + withContext(Dispatchers.IO) { + editor.commit() + } + } + override operator fun get(key: String): String? = config[key] override operator fun contains(key: String): Boolean = key in config diff --git a/radar-commons-android/src/main/java/org/radarbase/android/config/RemoteConfig.kt b/radar-commons-android/src/main/java/org/radarbase/android/config/RemoteConfig.kt index d55487e9f..614867026 100644 --- a/radar-commons-android/src/main/java/org/radarbase/android/config/RemoteConfig.kt +++ b/radar-commons-android/src/main/java/org/radarbase/android/config/RemoteConfig.kt @@ -33,4 +33,6 @@ interface RemoteConfig { } suspend fun stop() + + suspend fun reset() } diff --git a/radar-commons-android/src/main/java/org/radarbase/android/data/TableDataHandler.kt b/radar-commons-android/src/main/java/org/radarbase/android/data/TableDataHandler.kt index abe9011d2..9fc706638 100644 --- a/radar-commons-android/src/main/java/org/radarbase/android/data/TableDataHandler.kt +++ b/radar-commons-android/src/main/java/org/radarbase/android/data/TableDataHandler.kt @@ -416,8 +416,7 @@ class TableDataHandler( val newRest = config.restConfig newRest.kafkaConfig?.let { kafkaConfig -> - val contentTypeChanged: Boolean = - oldConfig.restConfig.hasBinaryContent != newRest.hasBinaryContent + oldConfig.restConfig.hasBinaryContent != newRest.hasBinaryContent logger.trace( "KafkaSenderTrace: Tweaking RestKafkaSender in TableDataHandler::handler: Is sender null? {}.", sender == null diff --git a/radar-commons-android/src/main/java/org/radarbase/android/source/SourceProvider.kt b/radar-commons-android/src/main/java/org/radarbase/android/source/SourceProvider.kt index 65c6864dd..1e284dd95 100644 --- a/radar-commons-android/src/main/java/org/radarbase/android/source/SourceProvider.kt +++ b/radar-commons-android/src/main/java/org/radarbase/android/source/SourceProvider.kt @@ -149,6 +149,12 @@ abstract class SourceProvider(protected val radarService: R connection.onServiceDisconnected(null) } + fun stopService() { + val intent = Intent(radarService, serviceClass) + radarService.stopService(intent) + } + + /** * Update the configuration of the service based on the given RadarConfiguration. * @throws IllegalStateException if [.getConnection] has not been called diff --git a/radar-commons-android/src/main/java/org/radarbase/android/source/SourceProviderRegistrar.kt b/radar-commons-android/src/main/java/org/radarbase/android/source/SourceProviderRegistrar.kt index fc515d406..ba12e7f1c 100644 --- a/radar-commons-android/src/main/java/org/radarbase/android/source/SourceProviderRegistrar.kt +++ b/radar-commons-android/src/main/java/org/radarbase/android/source/SourceProviderRegistrar.kt @@ -79,7 +79,7 @@ class SourceProviderRegistrar( override fun loginFailed(manager: LoginManager?, ex: Exception?) { } - override fun logoutSucceeded(manager: LoginManager?, authState: AppAuthState) = Unit + override suspend fun logoutSucceeded(manager: LoginManager?, authState: AppAuthState) = Unit private fun resetRetry() { retry.values.forEach { (_, future) -> diff --git a/radar-commons-android/src/main/java/org/radarbase/android/source/SourceService.kt b/radar-commons-android/src/main/java/org/radarbase/android/source/SourceService.kt index 0a9d71dca..97a376d9d 100644 --- a/radar-commons-android/src/main/java/org/radarbase/android/source/SourceService.kt +++ b/radar-commons-android/src/main/java/org/radarbase/android/source/SourceService.kt @@ -438,7 +438,7 @@ abstract class SourceService : } - override fun logoutSucceeded(manager: LoginManager?, authState: AppAuthState) = Unit + override suspend fun logoutSucceeded(manager: LoginManager?, authState: AppAuthState) = Unit /** * Override this function to get any parameters from the given intent. diff --git a/radar-commons-android/src/main/java/org/radarbase/android/splash/SplashActivity.kt b/radar-commons-android/src/main/java/org/radarbase/android/splash/SplashActivity.kt index 547ad7888..8586aa888 100644 --- a/radar-commons-android/src/main/java/org/radarbase/android/splash/SplashActivity.kt +++ b/radar-commons-android/src/main/java/org/radarbase/android/splash/SplashActivity.kt @@ -171,7 +171,7 @@ abstract class SplashActivity : AppCompatActivity() { return } - logger.info("Starting SplashActivity.") + logger.info("NewBroadcastTrace: Starting SplashActivity.") lifecycleScope.launch(Dispatchers.Default) { @@ -227,7 +227,7 @@ abstract class SplashActivity : AppCompatActivity() { } } - override fun logoutSucceeded(manager: LoginManager?, authState: AppAuthState) = Unit + override suspend fun logoutSucceeded(manager: LoginManager?, authState: AppAuthState) = Unit override fun loginSucceeded(manager: LoginManager?, authState: AppAuthState) { if (authState.isPrivacyPolicyAccepted) {