Skip to content

Commit

Permalink
Version 2.5.4 (#59)
Browse files Browse the repository at this point in the history
* Polling for flag updates might block the main thread
* Outbound HTTP requests now have an authentication scheme token in Authorization request headers
* Refactored map synchronization to avoid crashes in apps build with Gradle 3.3.0-alpha11
* Restored support for network connectivity detection in Android 7.0+ devices
  • Loading branch information
arun251 committed Oct 25, 2018
1 parent 53ad9ce commit 196a896
Show file tree
Hide file tree
Showing 12 changed files with 111 additions and 19 deletions.
68 changes: 68 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
version: 2
jobs:
build:
working_directory: ~/launchdarkly/android-client-private
docker:
- image: circleci/android:api-27-alpha
environment:
JVM_OPTS: -Xmx3200m
CIRCLE_ARTIFACTS: /tmp/circleci-artifacts
CIRCLE_TEST_REPORTS: /tmp/circleci-test-results

steps:
- checkout
- restore_cache:
keys:
# This branch if available
- v1-dep-{{ .Branch }}-
# Default branch if not
- v1-dep-master-
# Any branch if there are none on the default branch - this should be unnecessary if you have your default branch configured correctly
- v1-dep-

- run:
name: Download Dependencies
command: ./gradlew androidDependencies
- run: sudo mkdir -p $CIRCLE_TEST_REPORTS
- run: sudo apt-get -y -qq install awscli
- run: sudo mkdir -p /usr/local/android-sdk-linux/licenses

- save_cache:
key: v1-dep-{{ .Branch }}-{{ epoch }}
paths:
# This is a broad list of cache paths to include many possible development environments
# You can probably delete some of these entries
- vendor/bundle
- ~/virtualenvs
- ~/.m2
- ~/.ivy2
- ~/.bundle
- ~/.go_workspace
- ~/.gradle
- ~/.cache/bower
# These cache paths were specified in the 1.0 config
- /usr/local/android-sdk-linux/platforms/android-26
- /usr/local/android-sdk-linux/build-tools/26.0.2
- /usr/local/android-sdk-linux/platforms/android-27
- /usr/local/android-sdk-linux/build-tools/27.0.3
- /usr/local/android-sdk-linux/extras/android/m2repository
- run: unset ANDROID_NDK_HOME

- run: ./gradlew :launchdarkly-android-client:assembleDebug --console=plain -PdisablePreDex
- run: ./gradlew :launchdarkly-android-client:test --console=plain -PdisablePreDex

- run: ./gradlew packageRelease --console=plain -PdisablePreDex
- run:
name: Run Tests
command: ./gradlew test

- run:
name: Save test results
command: |
mkdir -p ~/tests/test-results
find . -type f -regex ".*/build/test-results/.*xml" -exec cp {} ~/tests/test-results/ \;
when: always
- store_test_results:
path: ~/tests
- store_artifacts:
path: ~/tests
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@

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

## [2.5.4] - 2018-10-25
### Changed
- Outbound HTTP requests now have an authentication scheme token in `Authorization` request headers

### Fixed
- Polling for flag updates might block the main thread
- Refactored map synchronization to avoid crashes in apps build with Gradle 3.3.0-alpha11
- Restored support for network connectivity detection in Android 7.0+ devices

## [2.5.3] - 2018-09-27
### Fixed
- Restored support for initializing `LDClient` on non-main threads
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Check out the included example app, or follow things here:
1. Declare this dependency:

```
compile 'com.launchdarkly:launchdarkly-android-client:2.5.3'
compile 'com.launchdarkly:launchdarkly-android-client:2.5.4'
```
1. In your application configure and initialize the client:

Expand Down
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

buildscript {
repositories {
jcenter()
mavenCentral()
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
Expand All @@ -20,9 +20,9 @@ buildscript {

allprojects {
repositories {
jcenter()
mavenCentral()
google()
jcenter()
}
}

Expand All @@ -40,4 +40,4 @@ subprojects {
project.android.dexOptions.preDexLibraries = rootProject.ext.preDexLibs
}
}
}
}
4 changes: 2 additions & 2 deletions launchdarkly-android-client/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ apply plugin: 'io.codearte.nexus-staging'

allprojects {
group = 'com.launchdarkly'
version = '2.5.3'
version = '2.5.4'
sourceCompatibility = 1.7
targetCompatibility = 1.7
}
Expand Down Expand Up @@ -96,10 +96,10 @@ repositories {

buildscript {
repositories {
jcenter()
mavenCentral()
mavenLocal()
google()
jcenter()
}
dependencies {
classpath 'org.ajoberstar:gradle-git:1.5.0-rc.1'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

public class ConnectivityReceiver extends BroadcastReceiver {

static final String CONNECTIVITY_CHANGE = "android.net.conn.CONNECTIVITY_CHANGE";

@Override
public void onReceive(Context context, Intent intent) {
if (isInternetConnected(context)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import android.app.Application;
import android.content.Context;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Build;
import android.support.annotation.NonNull;

import com.google.common.annotations.VisibleForTesting;
Expand Down Expand Up @@ -55,6 +57,7 @@ public class LDClient implements LDClientInterface, Closeable {
private final UpdateProcessor updateProcessor;
private final FeatureFlagFetcher fetcher;
private final Throttler throttler;
private ConnectivityReceiver connectivityReceiver;

private volatile boolean isOffline = false;
private volatile boolean isAppForegrounded = true;
Expand Down Expand Up @@ -226,6 +229,12 @@ public void run() {
setOnlineStatus();
}
}, RETRY_TIME_MS, MAX_RETRY_TIME_MS);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
connectivityReceiver = new ConnectivityReceiver();
IntentFilter filter = new IntentFilter(ConnectivityReceiver.CONNECTIVITY_CHANGE);
application.registerReceiver(connectivityReceiver, filter);
}
}

/**
Expand Down Expand Up @@ -518,6 +527,9 @@ public JsonElement jsonVariation(String flagKey, JsonElement fallback) {
public void close() throws IOException {
updateProcessor.stop();
eventProcessor.close();
if (connectivityReceiver != null && application.get() != null) {
application.get().unregisterReceiver(connectivityReceiver);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public class LDConfig {

static final String SHARED_PREFS_BASE_KEY = "LaunchDarkly-";
static final String USER_AGENT_HEADER_VALUE = "AndroidClient/" + BuildConfig.VERSION_NAME;
static final String AUTH_SCHEME = "api_key ";
static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
static final Gson GSON = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();

Expand Down Expand Up @@ -98,7 +99,7 @@ public LDConfig(String mobileKey,

public Request.Builder getRequestBuilder() {
return new Request.Builder()
.addHeader("Authorization", mobileKey)
.addHeader("Authorization", LDConfig.AUTH_SCHEME + mobileKey)
.addHeader("User-Agent", USER_AGENT_HEADER_VALUE);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,10 @@ public void onReceive(Context context, Intent intent) {
Timber.e("UserManager singleton was accessed before it was initialized! doing nothing");
return;
}
userManager.updateCurrentUser().get(15, TimeUnit.SECONDS);
userManager.updateCurrentUser();
} else {
Timber.d("onReceive with no internet connection! Skipping fetch.");
}
} catch (InterruptedException | ExecutionException e) {
Timber.e(e, "Exception caught when awaiting update");
} catch (TimeoutException e) {
Timber.e(e, "Feature Flag update timed out");
} catch (LaunchDarklyException e) {
Timber.e(e, "Exception when getting client");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public synchronized ListenableFuture<Void> start() {
stop();
Timber.d("Starting.");
Headers headers = new Headers.Builder()
.add("Authorization", config.getMobileKey())
.add("Authorization", LDConfig.AUTH_SCHEME + config.getMobileKey())
.add("User-Agent", LDConfig.USER_AGENT_HEADER_VALUE)
.add("Accept", "text/event-stream")
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;

import java.io.File;
import java.util.Collection;
Expand Down Expand Up @@ -36,17 +37,17 @@ class UserLocalSharedPreferences {

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

// The current user- we'll always fetch this user from the response we get from the api
private SharedPreferences currentUserSharedPrefs;

UserLocalSharedPreferences(Application application) {
this.application = application;

this.usersSharedPrefs = application.getSharedPreferences(LDConfig.SHARED_PREFS_BASE_KEY + "users", Context.MODE_PRIVATE);
this.activeUserSharedPrefs = loadSharedPrefsForActiveUser();

HashMultimap<String, Pair<FeatureFlagChangeListener, SharedPreferences.OnSharedPreferenceChangeListener>> multimap = HashMultimap.create();
listeners = Multimaps.synchronizedMultimap(multimap);
}

SharedPreferences getCurrentUserSharedPrefs() {
Expand Down Expand Up @@ -137,7 +138,9 @@ private SharedPreferences loadSharedPrefsForActiveUser() {
}

Collection<Pair<FeatureFlagChangeListener, SharedPreferences.OnSharedPreferenceChangeListener>> getListener(String key) {
return listeners.get(key);
synchronized (listeners) {
return listeners.get(key);
}
}

void registerListener(final String key, final FeatureFlagChangeListener listener) {
Expand All @@ -152,9 +155,9 @@ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, Strin
};
synchronized (listeners) {
listeners.put(key, new Pair<>(listener, sharedPrefsListener));
Timber.d("Added listener. Total count: [" + listeners.size() + "]");
}
activeUserSharedPrefs.registerOnSharedPreferenceChangeListener(sharedPrefsListener);
Timber.d("Added listener. Total count: [" + listeners.size() + "]");

}

Expand Down
3 changes: 2 additions & 1 deletion scripts/release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ rm -f launchdarkly-android-client/build.gradle.bak
sed -i.bak "s/com.launchdarkly:launchdarkly-android-client:[^']*/com.launchdarkly:launchdarkly-android-client:${VERSION}/" README.md
rm -f README.md.bak

./gradlew test sourcesJar javadocJar packageRelease uploadArchives closeAndReleaseRepository
./gradlew test sourcesJar javadocJar packageRelease
./gradlew uploadArchives closeAndReleaseRepository
./gradlew publishGhPages
echo "Finished android-client release."

0 comments on commit 196a896

Please sign in to comment.