Skip to content

Commit

Permalink
remote sdk configuration (#371)
Browse files Browse the repository at this point in the history
* add server side logging options

* add server side start tracking on initialize

* add server size track once on app open

* updates sdk config when Radar is initialized

* merge feature settings and sdk configuration
  • Loading branch information
ShiCheng-Lu authored Jul 19, 2024
1 parent 00818c6 commit 8085041
Show file tree
Hide file tree
Showing 18 changed files with 263 additions and 117 deletions.
1 change: 1 addition & 0 deletions example/src/main/java/io/radar/example/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import io.radar.sdk.RadarVerifiedReceiver
import io.radar.sdk.model.RadarVerifiedLocationToken
import org.json.JSONObject
import java.util.EnumSet
import androidx.core.content.edit

class MainActivity : AppCompatActivity() {

Expand Down
2 changes: 1 addition & 1 deletion sdk/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ apply plugin: "org.jetbrains.dokka"
apply plugin: 'io.radar.mvnpublish'

ext {
radarVersion = '3.15.0'
radarVersion = '3.16.0'
}

String buildNumber = ".${System.currentTimeMillis()}"
Expand Down
40 changes: 33 additions & 7 deletions sdk/src/main/java/io/radar/sdk/Radar.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import android.location.Location
import android.os.Build
import android.os.Handler
import androidx.annotation.RequiresApi
import androidx.core.content.edit
import io.radar.sdk.model.*
import io.radar.sdk.model.RadarEvent.RadarEventVerification
import io.radar.sdk.util.RadarLogBuffer
Expand Down Expand Up @@ -463,7 +464,12 @@ object Radar {
* @param[fraud] A boolean indicating whether to enable additional fraud detection signals for location verification.
*/
@JvmStatic
fun initialize(context: Context?, publishableKey: String? = null, receiver: RadarReceiver? = null, provider: RadarLocationServicesProvider = RadarLocationServicesProvider.GOOGLE, fraud: Boolean = false) {
fun initialize(
context: Context?,
publishableKey: String? = null,
receiver: RadarReceiver? = null,
provider: RadarLocationServicesProvider = RadarLocationServicesProvider.GOOGLE,
fraud: Boolean = false) {
if (context == null) {
return
}
Expand Down Expand Up @@ -534,16 +540,26 @@ object Radar {
}
application?.registerActivityLifecycleCallbacks(RadarActivityLifecycleCallbacks(fraud))

val featureSettings = RadarSettings.getFeatureSettings(this.context)
if (featureSettings.usePersistence) {
val sdkConfiguration = RadarSettings.getSdkConfiguration(this.context)
if (sdkConfiguration.usePersistence) {
Radar.loadReplayBufferFromSharedPreferences()
}

val usage = "initialize"
this.apiClient.getConfig(usage, false, object : RadarApiClient.RadarGetConfigApiCallback {
override fun onComplete(status: RadarStatus, config: RadarConfig) {
locationManager.updateTrackingFromMeta(config?.meta)
RadarSettings.setFeatureSettings(context, config?.meta.featureSettings)
if (status == RadarStatus.SUCCESS) {
locationManager.updateTrackingFromMeta(config.meta)
RadarSettings.setSdkConfiguration(context, config.meta.sdkConfiguration)
}

val sdkConfiguration = RadarSettings.getSdkConfiguration(context)
if (sdkConfiguration.startTrackingOnInitialize && !RadarSettings.getTracking(context)) {
Radar.startTracking(Radar.getTrackingOptions())
}
if (sdkConfiguration.trackOnceOnAppOpen) {
Radar.trackOnce()
}
}
})

Expand Down Expand Up @@ -3113,8 +3129,18 @@ object Radar {
if (!initialized) {
return
}

RadarSettings.setLogLevel(context, level)
// update clientSdkConfiguration if the new level is different, otherwise no-op
val sdkConfiguration = RadarSettings.getClientSdkConfiguration(context)
if (sdkConfiguration.optString("logLevel") == level.toString().lowercase()) {
return;
}
sdkConfiguration.put("logLevel", level.toString().lowercase())
RadarSettings.setClientSdkConfiguration(context, sdkConfiguration)
// if the current log level is already the target log level, no-op
if (RadarSettings.getLogLevel(context) == level) {
return;
}
RadarSdkConfiguration.updateSdkConfigurationFromServer(context)
}

/**
Expand Down
21 changes: 18 additions & 3 deletions sdk/src/main/java/io/radar/sdk/RadarActivityLifecycleCallbacks.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ internal class RadarActivityLifecycleCallbacks(
private val fraud: Boolean = false
) : Application.ActivityLifecycleCallbacks {
private var count = 0
private var isFirstOnResume = true

companion object {
var foreground: Boolean = false
Expand All @@ -44,23 +45,36 @@ internal class RadarActivityLifecycleCallbacks(
}

override fun onActivityResumed(activity: Activity) {
if (count == 0) {
if (count == 0 && !isFirstOnResume) {
try {
val updated = RadarSettings.updateSessionId(activity.applicationContext)
if (updated) {
val usage = "resume"
Radar.apiClient.getConfig(usage, false, object : RadarApiClient.RadarGetConfigApiCallback {
override fun onComplete(status: Radar.RadarStatus, config: RadarConfig) {
Radar.locationManager.updateTrackingFromMeta(config.meta)
RadarSettings.setFeatureSettings(activity.applicationContext, config.meta.featureSettings)
if (status == Radar.RadarStatus.SUCCESS) {
Radar.locationManager.updateTrackingFromMeta(config.meta)
RadarSettings.setSdkConfiguration(activity.applicationContext, config.meta.sdkConfiguration)
}

val sdkConfiguration = RadarSettings.getSdkConfiguration(activity.applicationContext)
if (sdkConfiguration.trackOnceOnAppOpen) {
Radar.trackOnce()
}
}
})
} else {
val sdkConfiguration = RadarSettings.getSdkConfiguration(activity.applicationContext)
if (sdkConfiguration.trackOnceOnAppOpen) {
Radar.trackOnce()
}
}
} catch (e: Exception) {
Log.e(TAG, e.message, e)
}
}
count++
isFirstOnResume = false
foreground = count > 0

Radar.logOpenedAppConversion()
Expand Down Expand Up @@ -113,6 +127,7 @@ internal class RadarActivityLifecycleCallbacks(
}

override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
Log.w(TAG, "ON CREATE ${count}")
updatePermissionsDenied(activity)
}
}
3 changes: 3 additions & 0 deletions sdk/src/main/java/io/radar/sdk/RadarApiClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
import java.util.*
import java.net.URLEncoder

internal class RadarApiClient(
private val context: Context,
Expand Down Expand Up @@ -130,6 +131,8 @@ internal class RadarApiClient(
if (usage != null) {
queryParams.append("&usage=${usage}")
}
val clientSdkConfiguration = RadarSettings.getClientSdkConfiguration(context).toString()
queryParams.append("&clientSdkConfiguration=${URLEncoder.encode(clientSdkConfiguration, "utf-8")}")

val path = "v1/config?${queryParams}"
val headers = headers(publishableKey)
Expand Down
6 changes: 3 additions & 3 deletions sdk/src/main/java/io/radar/sdk/RadarBeaconManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ internal class RadarBeaconManager(
}

fun startMonitoringBeacons(beacons: Array<RadarBeacon>) {
if (RadarSettings.getFeatureSettings(context).useRadarModifiedBeacon) {
if (RadarSettings.getSdkConfiguration(context).useRadarModifiedBeacon) {
return
}

Expand Down Expand Up @@ -149,7 +149,7 @@ internal class RadarBeaconManager(
}

fun startMonitoringBeaconUUIDs(beaconUUIDs: Array<String>?, beaconUIDs: Array<String>?) {
if (RadarSettings.getFeatureSettings(context).useRadarModifiedBeacon) {
if (RadarSettings.getSdkConfiguration(context).useRadarModifiedBeacon) {
return
}

Expand Down Expand Up @@ -256,7 +256,7 @@ internal class RadarBeaconManager(
}

fun stopMonitoringBeacons() {
if (RadarSettings.getFeatureSettings(context).useRadarModifiedBeacon) {
if (RadarSettings.getSdkConfiguration(context).useRadarModifiedBeacon) {
return
}

Expand Down
4 changes: 2 additions & 2 deletions sdk/src/main/java/io/radar/sdk/RadarJobScheduler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class RadarJobScheduler : JobService() {

val sourceStr = stringForSource(source)

val settings = RadarSettings.getFeatureSettings(context)
val settings = RadarSettings.getSdkConfiguration(context)
val jobId = BASE_JOB_ID_LOCATIONS + (numActiveLocationJobs.incrementAndGet() % settings.maxConcurrentJobs)

val jobInfo = JobInfo.Builder(jobId, componentName)
Expand Down Expand Up @@ -95,7 +95,7 @@ class RadarJobScheduler : JobService() {

val sourceStr = stringForSource(source)

val settings = RadarSettings.getFeatureSettings(context)
val settings = RadarSettings.getSdkConfiguration(context)
val jobId = BASE_JOB_ID_BEACONS + (numActiveBeaconJobs.incrementAndGet() % settings.maxConcurrentJobs)

val jobInfo = JobInfo.Builder(jobId, componentName)
Expand Down
2 changes: 1 addition & 1 deletion sdk/src/main/java/io/radar/sdk/RadarLocationManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ internal class RadarLocationManager(
this.started = false
RadarSettings.setTracking(context, false)
this.updateTracking()
val settings = RadarSettings.getFeatureSettings(context)
val settings = RadarSettings.getSdkConfiguration(context)
if (settings.extendFlushReplays) {
Radar.flushReplays()
}
Expand Down
2 changes: 1 addition & 1 deletion sdk/src/main/java/io/radar/sdk/RadarLogger.kt
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ internal class RadarLogger(
break
}
}
}
}
}

fun getBatteryLevel(): Float {
Expand Down
52 changes: 34 additions & 18 deletions sdk/src/main/java/io/radar/sdk/RadarSettings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@ package io.radar.sdk
import android.content.Context
import android.content.SharedPreferences
import androidx.core.content.edit
import io.radar.sdk.model.RadarFeatureSettings
import io.radar.sdk.model.RadarSdkConfiguration
import org.json.JSONObject
import java.text.DecimalFormat
import java.util.*


internal object RadarSettings {

private const val KEY_PUBLISHABLE_KEY = "publishable_key"
Expand All @@ -27,7 +26,8 @@ internal object RadarSettings {
private const val KEY_REMOTE_TRACKING_OPTIONS = "remote_tracking_options"
private const val KEY_FOREGROUND_SERVICE = "foreground_service"
private const val KEY_NOTIFICATION_OPTIONS = "notification_options"
private const val KEY_FEATURE_SETTINGS = "feature_settings"
private const val KEY_CLIENT_SDK_CONFIGURATION = "client_sdk_configuration"
private const val KEY_SDK_CONFIGURATION = "sdk_configuration"
private const val KEY_TRIP_OPTIONS = "trip_options"
private const val KEY_LOG_LEVEL = "log_level"
private const val KEY_HOST = "host"
Expand Down Expand Up @@ -82,7 +82,7 @@ internal object RadarSettings {
val timestampSeconds = System.currentTimeMillis() / 1000
val sessionIdSeconds = getSharedPreferences(context).getLong(KEY_SESSION_ID, 0)

val settings = RadarSettings.getFeatureSettings(context)
val settings = getSdkConfiguration(context)
if (settings.extendFlushReplays) {
Radar.logger.d("Flushing replays from updateSessionId()")
Radar.flushReplays()
Expand Down Expand Up @@ -293,33 +293,49 @@ internal object RadarSettings {
getSharedPreferences(context).edit { putString(KEY_TRIP_OPTIONS, optionsJson) }
}

fun setFeatureSettings(context: Context, featureSettings: RadarFeatureSettings) {
Radar.setLogPersistenceFeatureFlag(featureSettings.useLogPersistence)
val optionsJson = featureSettings.toJson().toString()
fun setSdkConfiguration(context: Context, configuration: RadarSdkConfiguration?) {
Radar.logger.d("set SDK Configuration | sdkConfiguration = $configuration")
if (configuration != null) {
Radar.setLogPersistenceFeatureFlag(configuration.useLogPersistence)
setLogLevel(context, configuration.logLevel)
val sdkConfigurationString = configuration.toJson().toString()
getSharedPreferences(context).edit { putString(KEY_SDK_CONFIGURATION, sdkConfigurationString) }
} else {
getSharedPreferences(context).edit { remove(KEY_SDK_CONFIGURATION) }
}
}

getSharedPreferences(context).edit { putString(KEY_FEATURE_SETTINGS, optionsJson) }
fun getSdkConfiguration(context: Context): RadarSdkConfiguration {
val sdkConfigurationString = getSharedPreferences(context).getString(KEY_SDK_CONFIGURATION, null)
val sdkConfigurationJSON = sdkConfigurationString?.let { JSONObject(it) }
return RadarSdkConfiguration.fromJson(sdkConfigurationJSON)
}

fun getFeatureSettings(context: Context): RadarFeatureSettings {
val sharedPrefFeatureSettings = getSharedPreferences(context).getString(KEY_FEATURE_SETTINGS, null)
try {
Radar.logger.d("Getting feature settings | featureSettings = $sharedPrefFeatureSettings")
} catch (e: Exception) {
fun getClientSdkConfiguration(context: Context): JSONObject {
val sharedPrefClientSdkConfig = getSharedPreferences(context).getString(KEY_CLIENT_SDK_CONFIGURATION, null);

return if (sharedPrefClientSdkConfig != null) {
JSONObject(sharedPrefClientSdkConfig)
} else {
JSONObject()
}
}

fun setClientSdkConfiguration(context: Context, sdkConfiguration: JSONObject?) {
val sdkConfigurationString = sdkConfiguration?.toString()
getSharedPreferences(context).edit {
putString(KEY_CLIENT_SDK_CONFIGURATION, sdkConfigurationString)
}
val optionsJson = sharedPrefFeatureSettings ?: return RadarFeatureSettings.default()
return RadarFeatureSettings.fromJson(JSONObject(optionsJson))
}

internal fun getLogLevel(context: Context): Radar.RadarLogLevel {
val logLevelInt = getSharedPreferences(context).getInt(KEY_LOG_LEVEL, 3)
val logLevelInt = getSharedPreferences(context).getInt(KEY_LOG_LEVEL, Radar.RadarLogLevel.INFO.value)
val userDebug = getUserDebug(context)
return if (userDebug) Radar.RadarLogLevel.DEBUG else Radar.RadarLogLevel.fromInt(logLevelInt)
}

internal fun setLogLevel(context: Context, level: Radar.RadarLogLevel) {
val logLevelInt = level.value
getSharedPreferences(context).edit { putInt(KEY_LOG_LEVEL, logLevelInt) }
getSharedPreferences(context).edit { putInt(KEY_LOG_LEVEL, level.value) }
}

internal fun getHost(context: Context): String {
Expand Down
62 changes: 0 additions & 62 deletions sdk/src/main/java/io/radar/sdk/model/RadarFeatureSettings.kt

This file was deleted.

Loading

0 comments on commit 8085041

Please sign in to comment.