Skip to content

Commit 188fdaf

Browse files
committed
android sdk local resolve
1 parent e84b724 commit 188fdaf

68 files changed

Lines changed: 7747 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Gradle
2+
.gradle/
3+
build/
4+
**/build/
5+
6+
# IDE
7+
.idea/
8+
*.iml
9+
local.properties
10+
11+
# OS
12+
.DS_Store
13+
Thumbs.db
14+
15+
# Kotlin
16+
*.class
17+
*.log
18+
*.jar
19+
*.war
20+
*.nar
21+
*.ear
22+
*.zip
23+
*.tar.gz
24+
*.rar
25+
26+
# Android
27+
*.apk
28+
*.ap_
29+
*.aab
30+
*.dex
31+
/captures
32+
.externalNativeBuild
33+
.cxx
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
.PHONY: build test clean
2+
3+
build:
4+
./gradlew build
5+
6+
test:
7+
./gradlew test
8+
9+
clean:
10+
./gradlew clean
11+
12+
assemble:
13+
./gradlew assemble
14+
15+
lint:
16+
./gradlew lint
17+
18+
publish-local:
19+
./gradlew publishToMavenLocal
20+
21+
copy-wasm:
22+
cp ../../wasm/confidence_resolver.wasm confidence-provider/src/main/resources/wasm/
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
# Confidence Android OpenFeature Provider
2+
3+
Local-resolution OpenFeature provider for Android that evaluates Confidence feature flags using a WebAssembly (WASM) resolver.
4+
5+
## Features
6+
7+
- **Local Resolution**: Evaluates flags locally using an embedded WASM resolver for fast, low-latency flag evaluation
8+
- **Automatic State Sync**: Periodically syncs flag configurations from the Confidence CDN
9+
- **Static Context Support**: Designed for Android's static context pattern where evaluation context is set once and reused
10+
- **Sticky Assignments**: Supports maintaining consistent variant assignments via materialization stores
11+
- **Background Processing**: Uses Kotlin coroutines for non-blocking state polling and log flushing
12+
13+
## Requirements
14+
15+
- Android API 26+ (Android 8.0 Oreo)
16+
- Kotlin 1.9+
17+
18+
## Installation
19+
20+
Add the dependency to your `build.gradle.kts`:
21+
22+
```kotlin
23+
dependencies {
24+
implementation("com.spotify.confidence:confidence-android-provider:0.1.0")
25+
}
26+
```
27+
28+
## Usage
29+
30+
### Basic Setup
31+
32+
```kotlin
33+
import com.spotify.confidence.android.ConfidenceLocalProvider
34+
import dev.openfeature.sdk.OpenFeatureAPI
35+
import dev.openfeature.sdk.ImmutableContext
36+
import dev.openfeature.sdk.Value
37+
38+
// Create the provider
39+
val provider = ConfidenceLocalProvider("your-client-secret")
40+
41+
// Set global evaluation context (Android static context pattern)
42+
OpenFeatureAPI.setEvaluationContext(
43+
ImmutableContext(
44+
targetingKey = "user-123",
45+
attributes = mapOf(
46+
"country" to Value.String("US"),
47+
"premium" to Value.Boolean(true)
48+
)
49+
)
50+
)
51+
52+
// Initialize the provider
53+
OpenFeatureAPI.setProviderAndWait(provider)
54+
55+
// Get a client and resolve flags
56+
val client = OpenFeatureAPI.getClient()
57+
val showFeature = client.getBooleanValue("show-new-feature", false)
58+
val buttonColor = client.getStringValue("button-color", "blue")
59+
```
60+
61+
### Advanced Configuration
62+
63+
```kotlin
64+
import com.spotify.confidence.android.LocalProviderConfig
65+
import java.time.Duration
66+
67+
val config = LocalProviderConfig.Builder()
68+
.statePollInterval(Duration.ofSeconds(60)) // How often to check for state updates
69+
.logFlushInterval(Duration.ofSeconds(30)) // How often to flush flag logs
70+
.useRemoteMaterializationStore(true) // Enable remote sticky assignments
71+
.build()
72+
73+
val provider = ConfidenceLocalProvider(config, "your-client-secret")
74+
```
75+
76+
### Nested Flag Values
77+
78+
Access nested values using dot notation:
79+
80+
```kotlin
81+
// If your flag has a structure like: { "button": { "color": "red", "size": 12 } }
82+
val buttonColor = client.getStringValue("my-flag.button.color", "blue")
83+
val buttonSize = client.getIntegerValue("my-flag.button.size", 10)
84+
```
85+
86+
### Shutdown
87+
88+
Clean up resources when the provider is no longer needed:
89+
90+
```kotlin
91+
provider.shutdown()
92+
```
93+
94+
## Static Context Pattern
95+
96+
Android's OpenFeature SDK uses a static context pattern, meaning:
97+
98+
1. The evaluation context is set once during app initialization
99+
2. This context is reused for all subsequent flag evaluations
100+
3. Context updates are applied to all future evaluations
101+
102+
This differs from server-side SDKs where context is passed per-request. The Confidence provider fully supports this pattern:
103+
104+
```kotlin
105+
// Set context once at startup
106+
OpenFeatureAPI.setEvaluationContext(
107+
ImmutableContext(
108+
targetingKey = userId,
109+
attributes = userAttributes
110+
)
111+
)
112+
113+
// All evaluations use this context
114+
val feature1 = client.getBooleanValue("feature-1", false)
115+
val feature2 = client.getStringValue("feature-2", "default")
116+
117+
// Update context when user info changes
118+
OpenFeatureAPI.setEvaluationContext(
119+
ImmutableContext(
120+
targetingKey = newUserId,
121+
attributes = newUserAttributes
122+
)
123+
)
124+
```
125+
126+
## Architecture
127+
128+
The provider consists of these components:
129+
130+
- **ConfidenceLocalProvider**: Main OpenFeature provider implementation
131+
- **WasmResolver**: Interfaces with the Confidence WASM resolver binary via Chicory
132+
- **SwapWasmResolverApi**: Manages WASM instance lifecycle with hot-swapping support
133+
- **StateFetcher**: Fetches and caches resolver state from CDN with ETag support
134+
- **GrpcWasmFlagLogger**: Sends flag resolution logs via gRPC
135+
- **MaterializationStore**: Interface for sticky assignment storage
136+
- **ConfidenceValue**: Type-safe value system compatible with Confidence SDK
137+
- **ValueConversions**: Utilities for converting between OpenFeature and Confidence types
138+
- **TypeMapper**: Converts between Protobuf and OpenFeature types
139+
140+
## Compatibility with Existing Confidence SDK
141+
142+
This provider is designed to be compatible with the [Confidence SDK Android](https://github.com/spotify/confidence-sdk-android).
143+
It uses the same:
144+
- Value type system (ConfidenceValue)
145+
- Context handling patterns
146+
- Initialization strategies
147+
148+
The main difference is that this provider uses local WASM-based resolution instead of remote HTTP/gRPC calls.
149+
150+
## Configuration Options
151+
152+
| Option | Description | Default |
153+
|--------|-------------|---------|
154+
| `statePollInterval` | How often to poll for state updates | 30 seconds |
155+
| `logFlushInterval` | How often to flush flag logs | 10 seconds |
156+
| `initialisationStrategy` | How to initialize (FetchAndActivate or ActivateAndFetchAsync) | FetchAndActivate |
157+
| `useRemoteMaterializationStore` | Whether to use remote gRPC for sticky assignments | false |
158+
159+
## License
160+
161+
Apache 2.0
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Root build file for Confidence Android OpenFeature Provider
2+
plugins {
3+
alias(libs.plugins.android.application) apply false
4+
alias(libs.plugins.android.library) apply false
5+
alias(libs.plugins.kotlin.android) apply false
6+
alias(libs.plugins.protobuf) apply false
7+
}

0 commit comments

Comments
 (0)