Skip to content

Commit 37dc435

Browse files
authored
Release version 2.3.0 (#37)
* Support for enhanced feature streams, facilitating reduced SDK initialization times.
1 parent b8a1796 commit 37dc435

30 files changed

+1496
-264
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33

44
All notable changes to the LaunchDarkly Android SDK will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org).
55

6+
## [2.3.0] - 2018-03-21
7+
### Added
8+
- Support for enhanced feature streams, facilitating reduced SDK initialization times.
9+
610
## [2.2.1] - 2018-03-11
711
### Changed
812
- The minimum polling interval is now 5 minutes, and the default event publishing interval is 30 seconds.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Check out the included example app, or follow things here:
88
1. Declare this dependency:
99

1010
```
11-
compile 'com.launchdarkly:launchdarkly-android-client:2.2.1'
11+
compile 'com.launchdarkly:launchdarkly-android-client:2.3.0'
1212
```
1313
1. In your application configure and initialize the client:
1414

build.gradle

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ buildscript {
44
repositories {
55
jcenter()
66
mavenCentral()
7-
maven { url 'https://maven.google.com'}
7+
google()
88
}
99
dependencies {
1010
classpath 'com.android.tools.build:gradle:3.0.1'
@@ -22,7 +22,7 @@ allprojects {
2222
repositories {
2323
jcenter()
2424
mavenCentral()
25-
maven { url 'https://maven.google.com'}
25+
google()
2626
}
2727
}
2828

@@ -40,4 +40,4 @@ subprojects {
4040
project.android.dexOptions.preDexLibraries = rootProject.ext.preDexLibs
4141
}
4242
}
43-
}
43+
}

example/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ repositories {
66
mavenLocal()
77
// Before LaunchDarkly release artifacts get synced to Maven Central they are here along with snapshots:
88
maven { url "https://oss.sonatype.org/content/groups/public/" }
9+
google()
910
mavenCentral()
1011
}
1112

gradle/wrapper/gradle-wrapper.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#Mon Jan 08 12:00:13 PST 2018
1+
#Thu Jan 11 09:20:17 PST 2018
22
distributionBase=GRADLE_USER_HOME
33
distributionPath=wrapper/dists
44
zipStoreBase=GRADLE_USER_HOME

launchdarkly-android-client/build.gradle

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@ apply plugin: 'com.android.library'
22
apply plugin: 'com.github.dcendents.android-maven'
33
apply plugin: 'signing'
44
apply plugin: 'org.ajoberstar.github-pages'
5-
// make sure this line comes *after* you apply the Android plugin
65
apply plugin: 'com.getkeepsafe.dexcount'
76
apply plugin: 'io.codearte.nexus-staging'
87

98
allprojects {
109
group = 'com.launchdarkly'
11-
version = '2.2.1'
10+
version = '2.3.0'
1211
sourceCompatibility = 1.7
1312
targetCompatibility = 1.7
1413
}
@@ -59,7 +58,7 @@ android {
5958
ext {
6059
supportVersion = "26.0.1"
6160
okhttpVersion = "3.6.0"
62-
eventsourceVersion = "1.5.3"
61+
eventsourceVersion = "1.7.0"
6362
gsonVersion = "2.8.2"
6463
testRunnerVersion = "0.5"
6564
}
@@ -72,6 +71,7 @@ dependencies {
7271
implementation "com.google.code.gson:gson:$gsonVersion"
7372
implementation "com.launchdarkly:okhttp-eventsource:$eventsourceVersion"
7473
implementation "com.squareup.okhttp3:okhttp:$okhttpVersion"
74+
implementation 'com.jakewharton.timber:timber:4.6.0'
7575

7676
androidTestImplementation "com.android.support:appcompat-v7:$supportVersion"
7777
androidTestImplementation "com.android.support:support-annotations:$supportVersion"
@@ -92,13 +92,15 @@ repositories {
9292
// Before LaunchDarkly release artifacts get synced to Maven Central they are here along with snapshots:
9393
maven { url "https://oss.sonatype.org/content/groups/public/" }
9494
mavenCentral()
95+
google()
9596
}
9697

9798
buildscript {
9899
repositories {
99100
jcenter()
100101
mavenCentral()
101102
mavenLocal()
103+
google()
102104
}
103105
dependencies {
104106
classpath 'org.ajoberstar:gradle-git:1.5.0-rc.1'

launchdarkly-android-client/src/androidTest/java/com/launchdarkly/android/UserManagerTest.java

Lines changed: 216 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626

2727
import static com.google.common.util.concurrent.Futures.immediateFailedFuture;
2828
import static junit.framework.Assert.assertEquals;
29-
import static junit.framework.Assert.assertNotNull;
3029
import static junit.framework.Assert.assertFalse;
30+
import static junit.framework.Assert.assertNotNull;
3131
import static junit.framework.Assert.assertTrue;
3232
import static org.easymock.EasyMock.expect;
3333
import static org.easymock.EasyMock.reset;
@@ -42,6 +42,7 @@ public class UserManagerTest extends EasyMockSupport {
4242
@Rule
4343
public EasyMockRule easyMockRule = new EasyMockRule(this);
4444

45+
@SuppressWarnings("unused")
4546
@Mock
4647
private FeatureFlagFetcher fetcher;
4748

@@ -60,18 +61,17 @@ public void TestFailedFetchThrowsException() throws InterruptedException {
6061
@Test
6162
public void TestBasicRetrieval() throws ExecutionException, InterruptedException {
6263
String expectedStringFlagValue = "string1";
63-
boolean expectedBoolFlagValue = true;
6464

6565
JsonObject jsonObject = new JsonObject();
66-
jsonObject.addProperty("boolFlag1", expectedBoolFlagValue);
66+
jsonObject.addProperty("boolFlag1", true);
6767
jsonObject.addProperty("stringFlag1", expectedStringFlagValue);
6868

6969
Future<Void> future = setUser("userKey", jsonObject);
7070
future.get();
7171

7272
SharedPreferences sharedPrefs = userManager.getCurrentUserSharedPrefs();
7373
assertEquals(2, sharedPrefs.getAll().size());
74-
assertEquals(expectedBoolFlagValue, sharedPrefs.getBoolean("boolFlag1", false));
74+
assertEquals(true, sharedPrefs.getBoolean("boolFlag1", false));
7575
assertEquals(expectedStringFlagValue, sharedPrefs.getString("stringFlag1", ""));
7676
}
7777

@@ -151,6 +151,216 @@ public void onFeatureFlagChange(String flagKey) {
151151
assertTrue(listeners.isEmpty());
152152
}
153153

154+
@Test
155+
public void TestDeleteFlag() throws ExecutionException, InterruptedException {
156+
userManager.clearVersionSharedPreferences();
157+
158+
String expectedStringFlagValue = "string1";
159+
160+
JsonObject jsonObject = new JsonObject();
161+
jsonObject.addProperty("boolFlag1", true);
162+
jsonObject.addProperty("stringFlag1", expectedStringFlagValue);
163+
164+
Future<Void> future = setUser("userKey", jsonObject);
165+
future.get();
166+
167+
SharedPreferences sharedPrefs = userManager.getCurrentUserSharedPrefs();
168+
assertEquals(2, sharedPrefs.getAll().size());
169+
assertEquals(true, sharedPrefs.getBoolean("boolFlag1", false));
170+
assertEquals(expectedStringFlagValue, sharedPrefs.getString("stringFlag1", ""));
171+
172+
userManager.deleteCurrentUserFlag("{\"key\":\"stringFlag1\",\"version\":16}").get();
173+
assertEquals("", sharedPrefs.getString("stringFlag1", ""));
174+
assertEquals(true, sharedPrefs.getBoolean("boolFlag1", false));
175+
176+
userManager.deleteCurrentUserFlag("{\"key\":\"nonExistentFlag\",\"version\":16,\"value\":false}").get();
177+
}
178+
179+
@Test
180+
public void TestDeleteForInvalidResponse() throws ExecutionException, InterruptedException {
181+
String expectedStringFlagValue = "string1";
182+
183+
JsonObject jsonObject = new JsonObject();
184+
jsonObject.addProperty("boolFlag1", true);
185+
jsonObject.addProperty("stringFlag1", expectedStringFlagValue);
186+
187+
Future<Void> future = setUser("userKey", jsonObject);
188+
future.get();
189+
190+
userManager.deleteCurrentUserFlag("{}").get();
191+
192+
//noinspection ConstantConditions
193+
userManager.deleteCurrentUserFlag(null).get();
194+
195+
userManager.deleteCurrentUserFlag("abcd").get();
196+
}
197+
198+
@Test
199+
public void TestDeleteWithVersion() throws ExecutionException, InterruptedException {
200+
userManager.clearVersionSharedPreferences();
201+
202+
Future<Void> future = setUser("userKey", new JsonObject());
203+
future.get();
204+
205+
String json = "{\n" +
206+
" \"stringFlag1\": {\n" +
207+
" \"key\": \"\",\n" +
208+
" \"version\": 125,\n" +
209+
" \"value\": \"string1\"\n" +
210+
" }\n" +
211+
" }";
212+
213+
userManager.putCurrentUserFlags(json).get();
214+
215+
userManager.deleteCurrentUserFlag("{\"key\":\"stringFlag1\",\"version\":16}").get();
216+
SharedPreferences sharedPrefs = userManager.getCurrentUserSharedPrefs();
217+
assertEquals("string1", sharedPrefs.getString("stringFlag1", ""));
218+
219+
userManager.deleteCurrentUserFlag("{\"key\":\"stringFlag1\",\"version\":127}").get();
220+
assertEquals("", sharedPrefs.getString("stringFlag1", ""));
221+
222+
userManager.deleteCurrentUserFlag("{\"key\":\"nonExistent\",\"version\":1}").get();
223+
}
224+
225+
@Test
226+
public void TestPatchForAddAndReplaceFlags() throws ExecutionException, InterruptedException {
227+
userManager.clearVersionSharedPreferences();
228+
229+
JsonObject jsonObject = new JsonObject();
230+
jsonObject.addProperty("boolFlag1", true);
231+
jsonObject.addProperty("stringFlag1", "string1");
232+
jsonObject.addProperty("floatFlag1", 3.0f);
233+
234+
Future<Void> future = setUser("userKey", jsonObject);
235+
future.get();
236+
237+
userManager.patchCurrentUserFlags("{\"key\":\"new-flag\",\"version\":16,\"value\":false}").get();
238+
239+
SharedPreferences sharedPrefs = userManager.getCurrentUserSharedPrefs();
240+
assertEquals(false, sharedPrefs.getBoolean("new-flag", true));
241+
242+
243+
userManager.patchCurrentUserFlags("{\"key\":\"stringFlag1\",\"version\":16,\"value\":\"string2\"}").get();
244+
assertEquals("string2", sharedPrefs.getString("stringFlag1", ""));
245+
246+
userManager.patchCurrentUserFlags("{\"key\":\"boolFlag1\",\"version\":16,\"value\":false}").get();
247+
assertEquals(false, sharedPrefs.getBoolean("boolFlag1", false));
248+
249+
assertEquals(3.0f, sharedPrefs.getFloat("floatFlag1", Float.MIN_VALUE));
250+
251+
userManager.patchCurrentUserFlags("{\"key\":\"floatFlag2\",\"version\":16,\"value\":8.0}").get();
252+
assertEquals(8.0f, sharedPrefs.getFloat("floatFlag2", Float.MIN_VALUE));
253+
}
254+
255+
@Test
256+
public void TestPatchWithVersion() throws ExecutionException, InterruptedException {
257+
userManager.clearVersionSharedPreferences();
258+
259+
Future<Void> future = setUser("userKey", new JsonObject());
260+
future.get();
261+
262+
String json = "{\n" +
263+
" \"stringFlag1\": {\n" +
264+
" \"key\": \"\",\n" +
265+
" \"version\": 125,\n" +
266+
" \"value\": \"string1\"\n" +
267+
" }\n" +
268+
" }";
269+
270+
userManager.putCurrentUserFlags(json).get();
271+
272+
273+
userManager.patchCurrentUserFlags("{\"key\":\"stringFlag1\",\"version\":16,\"value\":\"string2\"}").get();
274+
SharedPreferences sharedPrefs = userManager.getCurrentUserSharedPrefs();
275+
assertEquals("string1", sharedPrefs.getString("stringFlag1", ""));
276+
277+
userManager.patchCurrentUserFlags("{\"key\":\"stringFlag1\",\"version\":126,\"value\":\"string2\"}").get();
278+
assertEquals("string2", sharedPrefs.getString("stringFlag1", ""));
279+
280+
userManager.patchCurrentUserFlags("{\"key\":\"stringFlag20\",\"version\":1,\"value\":\"stringValue\"}").get();
281+
assertEquals("stringValue", sharedPrefs.getString("stringFlag20", ""));
282+
}
283+
284+
@Test
285+
public void TestPatchForInvalidResponse() throws ExecutionException, InterruptedException {
286+
String expectedStringFlagValue = "string1";
287+
288+
JsonObject jsonObject = new JsonObject();
289+
jsonObject.addProperty("boolFlag1", true);
290+
jsonObject.addProperty("stringFlag1", expectedStringFlagValue);
291+
292+
Future<Void> future = setUser("userKey", jsonObject);
293+
future.get();
294+
295+
userManager.patchCurrentUserFlags("{}").get();
296+
297+
//noinspection ConstantConditions
298+
userManager.patchCurrentUserFlags(null).get();
299+
300+
userManager.patchCurrentUserFlags("abcd").get();
301+
}
302+
303+
@Test
304+
public void TestPutForReplaceFlags() throws ExecutionException, InterruptedException {
305+
306+
JsonObject jsonObject = new JsonObject();
307+
jsonObject.addProperty("stringFlag1", "string1");
308+
jsonObject.addProperty("boolFlag1", true);
309+
jsonObject.addProperty("floatFlag1", 3.0f);
310+
311+
Future<Void> future = setUser("userKey", jsonObject);
312+
future.get();
313+
314+
String json = "{\n" +
315+
" \"stringFlag1\": {\n" +
316+
" \"key\": \"\",\n" +
317+
" \"version\": 125,\n" +
318+
" \"value\": \"string2\"\n" +
319+
" },\n" +
320+
" \"boolFlag1\": {\n" +
321+
" \"key\": \"\",\n" +
322+
" \"version\": 2,\n" +
323+
" \"value\": false\n" +
324+
" },\n" +
325+
" \"floatFlag2\": {\n" +
326+
" \"key\": \"\",\n" +
327+
" \"version\": 3,\n" +
328+
" \"value\": 8.0\n" +
329+
" }\n" +
330+
" }";
331+
332+
userManager.putCurrentUserFlags(json).get();
333+
334+
SharedPreferences sharedPrefs = userManager.getCurrentUserSharedPrefs();
335+
336+
assertEquals("string2", sharedPrefs.getString("stringFlag1", ""));
337+
assertEquals(false, sharedPrefs.getBoolean("boolFlag1", false));
338+
339+
// Should have value Float.MIN_VALUE instead of 3.0f which was deleted by PUT.
340+
assertEquals(Float.MIN_VALUE, sharedPrefs.getFloat("floatFlag1", Float.MIN_VALUE));
341+
342+
assertEquals(8.0f, sharedPrefs.getFloat("floatFlag2", 1.0f));
343+
}
344+
345+
@Test
346+
public void TestPutForInvalidResponse() throws ExecutionException, InterruptedException {
347+
String expectedStringFlagValue = "string1";
348+
349+
JsonObject jsonObject = new JsonObject();
350+
jsonObject.addProperty("boolFlag1", true);
351+
jsonObject.addProperty("stringFlag1", expectedStringFlagValue);
352+
353+
Future<Void> future = setUser("userKey", jsonObject);
354+
future.get();
355+
356+
userManager.putCurrentUserFlags("{}").get();
357+
358+
//noinspection ConstantConditions
359+
userManager.putCurrentUserFlags(null).get();
360+
361+
userManager.putCurrentUserFlags("abcd").get();
362+
}
363+
154364
private Future<Void> setUser(String userKey, JsonObject flags) {
155365
LDUser user = new LDUser.Builder(userKey).build();
156366
ListenableFuture<JsonObject> jsonObjectFuture = Futures.immediateFuture(flags);
@@ -184,4 +394,5 @@ private void assertFlagValue(String flagKey, Object expectedValue) {
184394
SharedPreferences sharedPrefs = userManager.getCurrentUserSharedPrefs();
185395
assertEquals(expectedValue, sharedPrefs.getAll().get(flagKey));
186396
}
187-
}
397+
398+
}

0 commit comments

Comments
 (0)