Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@

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

## [2.0.3] - 2017-05-18
### Changed
- Even better thread safety in UserManager when removing change listeners.

## [2.0.2] - 2017-05-03
### Changed
- Improved thread safety in UserManager when removing change listeners.
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.1'
classpath 'com.android.tools.build:gradle:2.3.2'

// For displaying method/field counts when building with Gradle:
// https://github.com/KeepSafe/dexcount-gradle-plugin
Expand Down
8 changes: 6 additions & 2 deletions circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,19 @@ dependencies:
# Android SDK Platform 24
- if [ ! -d "/usr/local/android-sdk-linux/platforms/android-24" ]; then echo y | android update sdk --no-ui --all --filter "android-24"; fi
# Android SDK Build-tools
- if [ ! -d "/usr/local/android-sdk-linux/build-tools/25.0.2" ]; then echo y | android update sdk --no-ui --all --filter "build-tools-25.0.2"; fi
- if [ ! -d "/usr/local/android-sdk-linux/build-tools/25.0.2" ]; then echo y | android update sdk --no-ui --all --filter "build-tools-25.0.3"; fi
# brings in appcompat
- if [ ! -d "/usr/local/android-sdk-linux/extras/android/m2repository" ]; then echo y | android update sdk --no-ui --all --filter "extra-android-m2repository"; fi
- mkdir -p /usr/local/android-sdk-linux/licenses
- aws s3 cp s3://launchdarkly-pastebin/ci/android/licenses/android-sdk-license /usr/local/android-sdk-linux/licenses/android-sdk-license
- aws s3 cp s3://launchdarkly-pastebin/ci/android/licenses/intel-android-extra-license /usr/local/android-sdk-linux/licenses/intel-android-extra-license
cache_directories:
- /usr/local/android-sdk-linux/platforms/android-24
- /usr/local/android-sdk-linux/build-tools/25.0.2
- /usr/local/android-sdk-linux/build-tools/25.0.3
- /usr/local/android-sdk-linux/extras/android/m2repository
test:
override:
- unset ANDROID_NDK_HOME
- emulator -avd circleci-android24 -no-audio -no-window:
background: true
parallel: true
Expand Down
2 changes: 1 addition & 1 deletion example/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ repositories {

android {
compileSdkVersion 24
buildToolsVersion '25.0.2'
buildToolsVersion '25.0.3'
defaultConfig {
applicationId "com.launchdarkly.example"
minSdkVersion 15
Expand Down
4 changes: 2 additions & 2 deletions launchdarkly-android-client/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ apply plugin: 'com.getkeepsafe.dexcount'

allprojects {
group = 'com.launchdarkly'
version = '2.0.2'
version = '2.0.3'
sourceCompatibility = 1.7
targetCompatibility = 1.7
}

android {
compileSdkVersion 24
buildToolsVersion '25.0.2'
buildToolsVersion '25.0.3'

defaultConfig {
minSdkVersion 15
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@ class UserManager {

private final Application application;
// Maintains references enabling (de)registration of listeners for realtime updates
private final Multimap<String, Pair<FeatureFlagChangeListener, OnSharedPreferenceChangeListener>> listeners =
Multimaps.synchronizedMultimap(ArrayListMultimap.<String, Pair<FeatureFlagChangeListener,OnSharedPreferenceChangeListener>>create());
private final Multimap<String, Pair<FeatureFlagChangeListener, OnSharedPreferenceChangeListener>> listeners = ArrayListMultimap.create();

// The current user- we'll always fetch this user from the response we get from the api
private SharedPreferences currentUserSharedPrefs;
Expand Down Expand Up @@ -116,6 +115,7 @@ void setCurrentUser(final LDUser user) {

/**
* Completely deletes a user's saved flag settings and the remaining empty SharedPreferences xml file.
*
* @param userKey
*/
private void deleteSharedPreferences(String userKey) {
Expand Down Expand Up @@ -166,17 +166,21 @@ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, Strin
}
}
};
listeners.put(key, new Pair<>(listener, sharedPrefsListener));
synchronized (listeners) {
listeners.put(key, new Pair<>(listener, sharedPrefsListener));
}
activeUserSharedPrefs.registerOnSharedPreferenceChangeListener(sharedPrefsListener);
Log.d(TAG, "Added listener. Total count: [" + listeners.size() + "]");
}

void unregisterListener(String key, FeatureFlagChangeListener listener) {
for (Pair<FeatureFlagChangeListener, OnSharedPreferenceChangeListener> pair : listeners.get(key)) {
if (pair.first.equals(listener)) {
Log.d(TAG, "Removing listener for key: [" + key + "]");
activeUserSharedPrefs.unregisterOnSharedPreferenceChangeListener(pair.second);
listeners.remove(key, pair);
synchronized (listeners) {
for (Pair<FeatureFlagChangeListener, OnSharedPreferenceChangeListener> pair : listeners.get(key)) {
if (pair.first.equals(listener)) {
Log.d(TAG, "Removing listener for key: [" + key + "]");
activeUserSharedPrefs.unregisterOnSharedPreferenceChangeListener(pair.second);
listeners.remove(key, pair);
}
}
}
}
Expand All @@ -190,7 +194,7 @@ void unregisterListener(String key, FeatureFlagChangeListener listener) {
* @param flags
*/
private void saveFlagSettings(JsonObject flags) {
Log.d(TAG, "saveFlagSettings for user key: "+ currentUser.getKey());
Log.d(TAG, "saveFlagSettings for user key: " + currentUser.getKey());
SharedPreferences.Editor currentEditor = currentUserSharedPrefs.edit();
currentEditor.clear();

Expand Down Expand Up @@ -260,7 +264,9 @@ private void syncCurrentUserToActiveUser() {
if (current.get(key) == null) {
Log.d(tag, "Deleting value and listeners for key: [" + key + "]");
activeEditor.remove(key);
listeners.removeAll(key);
synchronized (listeners) {
listeners.removeAll(key);
}
}
}
activeEditor.apply();
Expand Down