• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Unleash / unleash-android / 10075269522

24 Jul 2024 10:50AM UTC coverage: 69.676% (+4.4%) from 65.26%
10075269522

Pull #64

github

web-flow
Merge edfc3794f into 4fb5c6315
Pull Request #64: tests: test metrics sender

178 of 280 branches covered (63.57%)

Branch coverage included in aggregate %.

532 of 739 relevant lines covered (71.99%)

4.59 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/unleashandroidsdk/src/main/java/io/getunleash/android/backup/LocalBackup.kt
1
package io.getunleash.android.backup
2

3
import android.util.Log
4
import com.fasterxml.jackson.module.kotlin.readValue
5
import io.getunleash.android.data.Parser
6
import io.getunleash.android.data.Toggle
7
import io.getunleash.android.data.UnleashContext
8
import io.getunleash.android.data.UnleashState
9
import io.getunleash.android.unleashScope
10
import kotlinx.coroutines.Dispatchers
11
import kotlinx.coroutines.flow.Flow
12
import kotlinx.coroutines.launch
13
import kotlinx.coroutines.withContext
14
import java.io.File
15

16
private data class BackupState(val contextId: String, val toggles: Map<String, Toggle>)
×
17

18
/**
19
 * Local backup of the last state of the Unleash SDK.
20
 *
21
 * Because it only keeps the last state, it also saves the context id, and uses it to verify the context
22
 * is the same when loading the state from disc.
23
 */
24
class LocalBackup(
×
25
    private val localDir: File
×
26
) {
27
    companion object {
28
        private const val TAG = "LocalBackup"
29
        private const val STATE_BACKUP_FILE = "unleash_state.json"
30
    }
31

32
    private var lastContext: UnleashContext? = null
33

34
    fun subscribeTo(state: Flow<UnleashState>) {
35
        unleashScope.launch {
×
36
            withContext(Dispatchers.IO) {
×
37
                state.collect {
×
38
                    if (it.context != lastContext) {
×
39
                        lastContext = it.context
×
40
                        writeToDisc(it)
×
41
                    } else {
42
                        Log.d(TAG, "Context unchanged, not writing to disc")
×
43
                    }
44
                }
×
45
            }
×
46
        }
×
47
    }
×
48

49
    private fun writeToDisc(state: UnleashState) {
50
        try {
×
51
            // write only the last state
52
            val contextBackup = File(localDir.absolutePath, STATE_BACKUP_FILE)
×
53
            contextBackup.writeBytes(Parser.jackson.writeValueAsBytes(BackupState(id(state.context), state.toggles)))
×
54
            Log.d(TAG, "Written state to ${contextBackup.absolutePath}")
×
55
        } catch (e: Exception) {
×
56
            Log.i(TAG, "Error writing to disc", e)
×
57
        }
58
    }
×
59

60
    fun loadFromDisc(context: UnleashContext): UnleashState? {
61
        val stateBackup = File(localDir.absolutePath, STATE_BACKUP_FILE)
×
62
        try {
×
63
            if (stateBackup.exists()) {
×
64
                val backupState = Parser.jackson.readValue<BackupState>(stateBackup.readBytes())
×
65
                if (backupState.contextId != id(context)) {
×
66
                    Log.i(TAG, "Context id mismatch, ignoring backup")
×
67
                    return null
×
68
                }
69
                return UnleashState(context, backupState.toggles)
×
70
            } else {
71
                Log.d(TAG, "No backup found at ${stateBackup.absolutePath}")
×
72
            }
73
        } catch (e: Exception) {
×
74
            Log.w(TAG, "Error loading from disc ${stateBackup.absolutePath}", e)
×
75
        }
76
        return null
×
77
    }
78

79
    private fun id(context: UnleashContext): String {
80
        return context.hashCode().toString()
×
81
    }
82
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc