From c9837e935272802afc5f45f65bdeabf70b712e45 Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Wed, 13 Nov 2019 19:48:00 -0800 Subject: [PATCH 01/11] add entire compile-time classpath to javadoc classpath --- launchdarkly-android-client-sdk/build.gradle | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/launchdarkly-android-client-sdk/build.gradle b/launchdarkly-android-client-sdk/build.gradle index 45b7a8ce..1c8885d5 100644 --- a/launchdarkly-android-client-sdk/build.gradle +++ b/launchdarkly-android-client-sdk/build.gradle @@ -40,10 +40,6 @@ android { execution 'ANDROID_TEST_ORCHESTRATOR' } - configurations { - javadocDeps - } - compileOptions { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 @@ -89,10 +85,6 @@ dependencies { androidTestImplementation 'org.easymock:easymock:3.6' androidTestImplementation 'junit:junit:4.12' androidTestImplementation "com.squareup.okhttp3:mockwebserver:$okhttpVersion" - - javadocDeps "com.google.code.gson:gson:$gsonVersion" - javadocDeps "com.squareup.okhttp3:okhttp:$okhttpVersion" - javadocDeps "com.launchdarkly:okhttp-eventsource:$eventsourceVersion" } repositories { @@ -128,7 +120,13 @@ task javadoc(type: Javadoc) { failOnError false source = android.sourceSets.main.java.srcDirs classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) - classpath += configurations.javadocDeps +} + +afterEvaluate { +// https://stackoverflow.com/questions/34571371/android-studio-javadoc-cannot-find-symbol/34572606#34572606 + javadoc.classpath += files(android.libraryVariants.collect { variant -> + variant.javaCompile.classpath.files + }) } task javadocJar(type: Jar, dependsOn: javadoc) { From 17aee4a0575f79feb2e72270c5e85c95d3fc05ea Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Wed, 13 Nov 2019 19:48:14 -0800 Subject: [PATCH 02/11] javadoc fixes:

is not a thing --- .../com/launchdarkly/android/Foreground.java | 14 +++---- .../com/launchdarkly/android/LDClient.java | 2 +- .../android/LDClientInterface.java | 4 +- .../launchdarkly/android/LDCountryCode.java | 41 ++++++------------- .../java/com/launchdarkly/android/LDUser.java | 5 +-- 5 files changed, 24 insertions(+), 42 deletions(-) diff --git a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/Foreground.java b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/Foreground.java index a3302190..971f4b5d 100644 --- a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/Foreground.java +++ b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/Foreground.java @@ -20,16 +20,16 @@ /** * Usage: - *

+ *

* 1. Get the Foreground Singleton, passing a Context or Application object unless you * are sure that the Singleton has definitely already been initialised elsewhere. - *

+ *

* 2.a) Perform a direct, synchronous check: Foreground.isForeground() / .isBackground() - *

+ *

* or - *

+ *

* 2.b) Register to be notified (useful in Service or other non-UI components): - *

+ *

* Foreground.Listener myListener = new Foreground.Listener(){ * void onBecameForeground(){ * // ... whatever you want to do @@ -38,12 +38,12 @@ * // ... whatever you want to do * } * } - *

+ *

* void onCreate(){ * super.onCreate(); * Foreground.get(this).addListener(listener); * } - *

+ *

* void onDestroy(){ * super.onCreate(); * Foreground.get(this).removeListener(listener); diff --git a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDClient.java b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDClient.java index ccfdf5ab..4811f0e1 100644 --- a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDClient.java +++ b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDClient.java @@ -58,7 +58,7 @@ public class LDClient implements LDClientInterface, Closeable { * will complete once the client has been initialized with the latest feature flag values. For * immediate access to the Client (possibly with out of date feature flags), it is safe to ignore * the return value of this method, and afterward call {@link #get()} - *

+ *

* If the client has already been initialized, is configured for offline mode, or the device is * not connected to the internet, this method will return a {@link Future} that is * already in the completed state. diff --git a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDClientInterface.java b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDClientInterface.java index 67e91c25..b4d1aa09 100644 --- a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDClientInterface.java +++ b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDClientInterface.java @@ -37,7 +37,7 @@ public interface LDClientInterface extends Closeable { * Shuts down any network connections maintained by the client and puts the client in offline * mode, preventing the client from opening new network connections until * setOnline() is called. - *

+ *

* Note: The client automatically monitors the device's network connectivity and app foreground * status, so calling setOffline() or setOnline() is normally * unnecessary in most situations. @@ -47,7 +47,7 @@ public interface LDClientInterface extends Closeable { /** * Restores network connectivity for the client, if the client was previously in offline mode. * This operation may be throttled if it is called too frequently. - *

+ *

* Note: The client automatically monitors the device's network connectivity and app foreground * status, so calling setOffline() or setOnline() is normally * unnecessary in most situations. diff --git a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDCountryCode.java b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDCountryCode.java index e1f94a52..67216bfd 100644 --- a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDCountryCode.java +++ b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDCountryCode.java @@ -33,7 +33,6 @@ /** * ISO 3166-1 country code. - *

*

* Enum names of this enum themselves are represented by * ISO 3166-1 alpha-2 @@ -47,7 +46,6 @@ * corresponds to a given alpha-2/alpha-3/numeric code ({@link #getByCode(String)}, * {@link #getByCode(int)}). *

- *

*

  * // List all the country codes.
  * for (CountryCode code : CountryCode.values())
@@ -55,10 +53,10 @@
  * // For example, "[US] United States" is printed.
  * System.out.format("[%s] %s\n", code, code.{@link #getName()});
  * }
- * 

+ *

* // Get a CountryCode instance by ISO 3166-1 code. * CountryCode code = CountryCode.{@link #getByCode(String) getByCode}("JP"); - *

+ *

* // Print all the information. Output will be: * // * // Country name = Japan @@ -72,16 +70,16 @@ * System.out.println("ISO 3166-1 alpha-3 code = " + code.{@link #getAlpha3()}); * System.out.println("ISO 3166-1 numeric code = " + code.{@link #getNumeric()}); * System.out.println("Assignment state = " + code.{@link #getAssignment()}); - *

+ *

* // Convert to a Locale instance. * {@link Locale} locale = code.{@link #toLocale()}; - *

+ *

* // Get a CountryCode by a Locale instance. * code = CountryCode.{@link #getByLocale(Locale) getByLocale}(locale); - *

+ *

* // Get the currency of the country. * {@link Currency} currency = code.{@link #getCurrency()}; - *

+ *

* // Get a list by a regular expression for names. * // * // The list will contain: @@ -1818,7 +1816,6 @@ public Locale toLocale() { * East Timor * [TP, TPTL, 0, * Traditionally reserved] - *

*

* ISO 3166-1 numeric code is unknown. *

@@ -2033,7 +2030,6 @@ public Locale toLocale() { * Zaire * [ZR, ZRCD, 0, * Traditionally reserved] - *

*

* ISO 3166-1 numeric code is unknown. *

@@ -2059,7 +2055,7 @@ enum Assignment { /** * Officially assigned. - *

+ *

* Assigned to a country, territory, or area of geographical interest. */ OFFICIALLY_ASSIGNED, @@ -2067,7 +2063,7 @@ enum Assignment { /** * User assigned. - *

+ *

* Free for assignment at the disposal of users. */ USER_ASSIGNED, @@ -2075,7 +2071,7 @@ enum Assignment { /** * Exceptionally reserved. - *

+ *

* Reserved on request for restricted use. */ EXCEPTIONALLY_RESERVED, @@ -2083,7 +2079,7 @@ enum Assignment { /** * Transitionally reserved. - *

+ *

* Deleted from ISO 3166-1 but reserved transitionally. */ TRANSITIONALLY_RESERVED, @@ -2091,7 +2087,7 @@ enum Assignment { /** * Indeterminately reserved. - *

+ *

* Used in coding systems associated with ISO 3166-1. */ INDETERMINATELY_RESERVED, @@ -2099,7 +2095,7 @@ enum Assignment { /** * Not used. - *

+ *

* Not used in ISO 3166-1 in deference to international property * organization names. */ @@ -2202,20 +2198,17 @@ public Assignment getAssignment() { /** * Convert this {@code CountryCode} instance to a {@link Locale} instance. - *

*

* In most cases, this method creates a new {@code Locale} instance * every time it is called, but some {@code CountryCode} instances return * their corresponding entries in {@code Locale} class. For example, * {@link #CA CountryCode.CA} always returns {@link Locale#CANADA}. *

- *

*

* The table below lists {@code CountryCode} entries whose {@code toLocale()} * do not create new Locale instances but return entries in * {@code Locale} class. *

- *

* * * @@ -2272,7 +2265,6 @@ public Locale toLocale() { /** * Get the currency. - *

*

* This method is an alias of {@link Currency}{@code .}{@link * Currency#getInstance(Locale) getInstance}{@code (}{@link @@ -2280,13 +2272,11 @@ public Locale toLocale() { * returns {@code null} when {@code Currency.getInstance(Locale)} * throws {@code IllegalArgumentException}. *

- *

*

* This method returns {@code null} when the territory represented by * this {@code CountryCode} instance does not have a currency. * {@link #AQ} (Antarctica) is one example. *

- *

*

* In addition, this method returns {@code null} also when the ISO 3166 * code represented by this {@code CountryCode} instance is not @@ -2315,7 +2305,6 @@ public Currency getCurrency() { * Get a {@code CountryCode} that corresponds to the given ISO 3166-1 * alpha-2 or * alpha-3 code. - *

*

* This method calls {@link #getByCode(String, boolean) getByCode}{@code (code, true)}. * Note that the behavior has changed since the version 1.13. In the older versions, @@ -2337,7 +2326,6 @@ public static LDCountryCode getByCode(String code) { * Get a {@code CountryCode} that corresponds to the given ISO 3166-1 * alpha-2 or * alpha-3 code. - *

*

* This method calls {@link #getByCode(String, boolean) getByCode}{@code (code, false)}. *

@@ -2467,7 +2455,6 @@ public static LDCountryCode getByCode(int code) { /** * Get a list of {@code CountryCode} by a name regular expression. - *

*

* This method is almost equivalent to {@link #findByName(Pattern) * findByName}{@code (Pattern.compile(regex))}. @@ -2495,19 +2482,15 @@ public static List findByName(String regex) { /** * Get a list of {@code CountryCode} by a name pattern. - *

*

* For example, the list obtained by the code snippet below: *

- *

*

      * Pattern pattern = Pattern.compile(".*United.*");
      * List<CountryCode> list = CountryCode.findByName(pattern);
- *

*

* contains 6 {@code CountryCode}s as listed below. *

- *

*

    *
  1. {@link #AE} : United Arab Emirates *
  2. {@link #GB} : United Kingdom diff --git a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDUser.java b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDUser.java index 599e9a3a..80549e1c 100644 --- a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDUser.java +++ b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDUser.java @@ -29,12 +29,12 @@ * mandatory property property is the {@code key}, which must uniquely identify each user. For * authenticated users, this may be a username or e-mail address. For anonymous users, this could be * an IP address or session ID. - *

    + *

    * Besides the mandatory {@code key}, {@code LDUser} supports two kinds of optional attributes: * interpreted attributes (e.g. {@code ip} and {@code country}) and custom attributes. LaunchDarkly * can parse interpreted attributes and attach meaning to them. For example, from an {@code ip} * address, LaunchDarkly can do a geo IP lookup and determine the user's country. - *

    + *

    * Custom attributes are not parsed by LaunchDarkly. They can be used in custom rules-- for example, * a custom attribute such as "customer_ranking" can be used to launch a feature to the top 10% of * users on a site. @@ -192,7 +192,6 @@ String getSharedPrefsKey() { /** * A builder that helps construct * {@link LDUser} objects. Builder calls can be chained, enabling the following pattern: - *

    *

          * LDUser user = new LDUser.Builder("key")
          *      .country("US")
    
    From 05c2bc33405c27fc33b1fc83ddd066db165b7a72 Mon Sep 17 00:00:00 2001
    From: Eli Bishop 
    Date: Wed, 13 Nov 2019 20:36:41 -0800
    Subject: [PATCH 03/11] do fail on javadoc errors
    
    ---
     launchdarkly-android-client-sdk/build.gradle | 1 -
     1 file changed, 1 deletion(-)
    
    diff --git a/launchdarkly-android-client-sdk/build.gradle b/launchdarkly-android-client-sdk/build.gradle
    index 1c8885d5..f4dff80d 100644
    --- a/launchdarkly-android-client-sdk/build.gradle
    +++ b/launchdarkly-android-client-sdk/build.gradle
    @@ -117,7 +117,6 @@ task sourcesJar(type: Jar) {
     }
     
     task javadoc(type: Javadoc) {
    -    failOnError false
         source = android.sourceSets.main.java.srcDirs
         classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
     }
    
    From bc6826785bef0793fb0a5304a391bffaaf1071ac Mon Sep 17 00:00:00 2001
    From: Eli Bishop 
    Date: Wed, 13 Nov 2019 20:59:23 -0800
    Subject: [PATCH 04/11] add javadoc step, misc CI cleanup
    
    ---
     .circleci/config.yml | 14 +++++++++++---
     1 file changed, 11 insertions(+), 3 deletions(-)
    
    diff --git a/.circleci/config.yml b/.circleci/config.yml
    index 01879571..a10c45b4 100644
    --- a/.circleci/config.yml
    +++ b/.circleci/config.yml
    @@ -47,7 +47,9 @@ jobs:
               timeout: 1200
               no_output_timeout: 2h
     
    -      - run: ./gradlew :launchdarkly-android-client-sdk:assembleDebug --console=plain -PdisablePreDex
    +      - run:
    +          name: Compile
    +          command: ./gradlew :launchdarkly-android-client-sdk:assembleDebug --console=plain -PdisablePreDex
     
           - run:
               name: Wait for emulator to boot
    @@ -73,12 +75,18 @@ jobs:
                 adb logcat >> ~/artifacts/logcat.txt
     
           - run:
    -          name: Run Tests
    +          name: Run tests
               command: ./gradlew :launchdarkly-android-client-sdk:connectedAndroidTest --console=plain -PdisablePreDex
               no_output_timeout: 2h
     
    -      - run: ./gradlew packageRelease --console=plain -PdisablePreDex
    +      - run:
    +          name: Validate package creation
    +          command: ./gradlew packageRelease --console=plain -PdisablePreDex
     
    +      - run:
    +          name: Validate Javadoc
    +          command: ./gradlew Javadoc
    +      
           - run:
               name: Save test results
               command: |
    
    From 73e10da7a38c6808594281b4828587b656e7de3f Mon Sep 17 00:00:00 2001
    From: Eli Bishop 
    Date: Wed, 13 Nov 2019 22:11:48 -0800
    Subject: [PATCH 05/11] misc javadoc fixes
    
    ---
     .../java/com/launchdarkly/android/LDClient.java    |  2 +-
     .../launchdarkly/android/LDClientInterface.java    |  8 ++++----
     .../java/com/launchdarkly/android/LDConfig.java    |  2 ++
     .../com/launchdarkly/android/LDCountryCode.java    | 14 +++++++-------
     .../android/SummaryEventSharedPreferences.java     |  3 +--
     .../android/response/FlagsResponse.java            |  4 +---
     6 files changed, 16 insertions(+), 17 deletions(-)
    
    diff --git a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDClient.java b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDClient.java
    index 4811f0e1..c89c5ff4 100644
    --- a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDClient.java
    +++ b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDClient.java
    @@ -401,7 +401,7 @@ private  EvaluationDetail variationDetailInternal(String flagKey, T fallba
         /**
          * Closes the client. This should only be called at the end of a client's lifecycle.
          *
    -     * @throws IOException
    +     * @throws IOException declared by the Closeable interface, but will not be thrown by the client
          */
         @Override
         public void close() throws IOException {
    diff --git a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDClientInterface.java b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDClientInterface.java
    index b4d1aa09..4fe73fec 100644
    --- a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDClientInterface.java
    +++ b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDClientInterface.java
    @@ -274,14 +274,14 @@ public interface LDClientInterface extends Closeable {
         ConnectionInformation getConnectionInformation();
     
         /**
    -     *
    -     * @param LDStatusListener
    +     * Unregisters a {@link LDStatusListener} so it will no longer be called on connection status updates.
    +     * @param LDStatusListener the listener to be removed
          */
         void unregisterStatusListener(LDStatusListener LDStatusListener);
     
         /**
    -     *
    -     * @param LDStatusListener
    +     * Registers a {@link LDStatusListener} to be called on connection status updates.
    +     * @param LDStatusListener the listener to be called on a connection status update
          */
         void registerStatusListener(LDStatusListener LDStatusListener);
     
    diff --git a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDConfig.java b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDConfig.java
    index 54539599..64af036a 100644
    --- a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDConfig.java
    +++ b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDConfig.java
    @@ -418,6 +418,7 @@ public LDConfig.Builder setPollingIntervalMillis(int pollingIntervalMillis) {
              *
              * @param backgroundPollingIntervalMillis the feature flag polling interval when in the background,
              *                                        in milliseconds
    +         * @return the builder
              */
             public LDConfig.Builder setBackgroundPollingIntervalMillis(int backgroundPollingIntervalMillis) {
                 this.backgroundPollingIntervalMillis = backgroundPollingIntervalMillis;
    @@ -430,6 +431,7 @@ public LDConfig.Builder setBackgroundPollingIntervalMillis(int backgroundPolling
              * The default value is false (flag updates will be done in the background).
              *
              * @param disableBackgroundUpdating true if the client should skip updating flags when in the background
    +         * @return the builder
              */
             public LDConfig.Builder setDisableBackgroundUpdating(boolean disableBackgroundUpdating) {
                 this.disableBackgroundUpdating = disableBackgroundUpdating;
    diff --git a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDCountryCode.java b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDCountryCode.java
    index 67216bfd..caefea1b 100644
    --- a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDCountryCode.java
    +++ b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDCountryCode.java
    @@ -53,10 +53,10 @@
      * // For example, "[US] United States" is printed.
      * System.out.format("[%s] %s\n", code, code.{@link #getName()});
      * }
    - * 

    + * * // Get a CountryCode instance by ISO 3166-1 code. * CountryCode code = CountryCode.{@link #getByCode(String) getByCode}("JP"); - *

    + * * // Print all the information. Output will be: * // * // Country name = Japan @@ -70,16 +70,16 @@ * System.out.println("ISO 3166-1 alpha-3 code = " + code.{@link #getAlpha3()}); * System.out.println("ISO 3166-1 numeric code = " + code.{@link #getNumeric()}); * System.out.println("Assignment state = " + code.{@link #getAssignment()}); - *

    + * * // Convert to a Locale instance. * {@link Locale} locale = code.{@link #toLocale()}; - *

    + * * // Get a CountryCode by a Locale instance. * code = CountryCode.{@link #getByLocale(Locale) getByLocale}(locale); - *

    + * * // Get the currency of the country. * {@link Currency} currency = code.{@link #getCurrency()}; - *

    + * * // Get a list by a regular expression for names. * // * // The list will contain: @@ -2210,7 +2210,7 @@ public Assignment getAssignment() { * {@code Locale} class. *

    *
CountryCode
- * + * * * * diff --git a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/SummaryEventSharedPreferences.java b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/SummaryEventSharedPreferences.java index f41d0cf2..0947f257 100644 --- a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/SummaryEventSharedPreferences.java +++ b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/SummaryEventSharedPreferences.java @@ -5,9 +5,8 @@ import com.google.gson.JsonElement; /** - * Created by jamesthacker on 4/12/18. + * Used internally by the SDK. */ - public interface SummaryEventSharedPreferences { void clear(); diff --git a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/response/FlagsResponse.java b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/response/FlagsResponse.java index 034fe823..7e677470 100644 --- a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/response/FlagsResponse.java +++ b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/response/FlagsResponse.java @@ -7,9 +7,7 @@ import java.util.List; /** - * Used for cases where the server sends a collection of flags as a key-value object. Uses custom - * deserializer in {@link com.launchdarkly.android.gson.FlagsResponseSerialization} to get a list of - * {@link com.launchdarkly.android.flagstore.Flag} objects. + * Used for cases where the server sends a collection of flags as a key-value object. */ public class FlagsResponse { @NonNull From f90b00db565701e1cfc0fec5c8a6515488cce49e Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Thu, 14 Nov 2019 14:34:16 -0800 Subject: [PATCH 06/11] remove unintentional(?) immediate event flush; clean up event tests --- .../launchdarkly/android/LDClientTest.java | 443 ++++++++---------- .../android/DefaultEventProcessor.java | 2 +- 2 files changed, 196 insertions(+), 249 deletions(-) diff --git a/launchdarkly-android-client-sdk/src/androidTest/java/com/launchdarkly/android/LDClientTest.java b/launchdarkly-android-client-sdk/src/androidTest/java/com/launchdarkly/android/LDClientTest.java index bf5e932d..c16cdb76 100644 --- a/launchdarkly-android-client-sdk/src/androidTest/java/com/launchdarkly/android/LDClientTest.java +++ b/launchdarkly-android-client-sdk/src/androidTest/java/com/launchdarkly/android/LDClientTest.java @@ -28,7 +28,6 @@ import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertNull; import static junit.framework.Assert.assertTrue; import static junit.framework.Assert.fail; @@ -38,6 +37,8 @@ @RunWith(AndroidJUnit4.class) public class LDClientTest { + private static final String mobileKey = "test-mobile-key"; + @Rule public final ActivityTestRule activityTestRule = new ActivityTestRule<>(TestActivity.class, false, true); @@ -191,277 +192,223 @@ public void run() { @Test public void testTrack() throws IOException, InterruptedException { - MockWebServer mockEventsServer = new MockWebServer(); - mockEventsServer.start(); - // Enqueue a successful empty response - mockEventsServer.enqueue(new MockResponse().addHeader("Date", "")); - - HttpUrl baseUrl = mockEventsServer.url("/mobile"); - - LDConfig ldConfig = new LDConfig.Builder() - .setMobileKey("test-mobile-sdk-key") - .setEventsUri(Uri.parse(baseUrl.url().toString())) - .build(); - - // Don't wait as we are not set offline - ldClient = LDClient.init(application, ldConfig, ldUser, 0); - - ldClient.track("test-event"); - ldClient.blockingFlush(); - - RecordedRequest eventPost = mockEventsServer.takeRequest(); - assertEquals("POST", eventPost.getMethod()); - assertEquals("/mobile", eventPost.getPath()); - assertNotNull(eventPost.getHeader("Authorization")); - - Event[] events = TestUtil.getEventDeserializerGson().fromJson(eventPost.getBody().readUtf8(), Event[].class); - assertEquals(2, events.length); - assertTrue(events[0] instanceof IdentifyEvent); - assertTrue(events[1] instanceof CustomEvent); - CustomEvent event = (CustomEvent) events[1]; - assertEquals("userKey", event.userKey); - assertEquals("test-event", event.key); - assertEquals(System.currentTimeMillis(), event.creationDate, 500); - assertNull(event.data); - assertNull(event.metricValue); + try (MockWebServer mockEventsServer = new MockWebServer()) { + mockEventsServer.start(); + // Enqueue a successful empty response + mockEventsServer.enqueue(new MockResponse().addHeader("Date", "")); + + LDConfig ldConfig = baseConfigBuilder(mockEventsServer).build(); + + // Don't wait as we are not set offline + ldClient = LDClient.init(application, ldConfig, ldUser, 0); + + ldClient.track("test-event"); + ldClient.blockingFlush(); + + Event[] events = getEventsFromLastRequest(mockEventsServer, 2); + assertEquals(2, events.length); + assertTrue(events[0] instanceof IdentifyEvent); + assertTrue(events[1] instanceof CustomEvent); + CustomEvent event = (CustomEvent) events[1]; + assertEquals("userKey", event.userKey); + assertEquals("test-event", event.key); + assertEquals(System.currentTimeMillis(), event.creationDate, 500); + assertNull(event.data); + assertNull(event.metricValue); + } } @Test public void testTrackData() throws IOException, InterruptedException { - MockWebServer mockEventsServer = new MockWebServer(); - mockEventsServer.start(); - // Enqueue a successful empty response - mockEventsServer.enqueue(new MockResponse().addHeader("Date", "")); - - HttpUrl baseUrl = mockEventsServer.url("/mobile"); - - LDConfig ldConfig = new LDConfig.Builder() - .setMobileKey("test-mobile-sdk-key") - .setEventsUri(Uri.parse(baseUrl.url().toString())) - .build(); - - // Don't wait as we are not set offline - ldClient = LDClient.init(application, ldConfig, ldUser, 0); - - JsonPrimitive testData = new JsonPrimitive("abc"); - - ldClient.track("test-event", testData); - ldClient.blockingFlush(); - - RecordedRequest eventPost = mockEventsServer.takeRequest(); - assertEquals("POST", eventPost.getMethod()); - assertEquals("/mobile", eventPost.getPath()); - assertNotNull(eventPost.getHeader("Authorization")); - - Event[] events = TestUtil.getEventDeserializerGson().fromJson(eventPost.getBody().readUtf8(), Event[].class); - assertEquals(2, events.length); - assertTrue(events[0] instanceof IdentifyEvent); - assertTrue(events[1] instanceof CustomEvent); - CustomEvent event = (CustomEvent) events[1]; - assertEquals("userKey", event.userKey); - assertEquals("test-event", event.key); - assertEquals(System.currentTimeMillis(), event.creationDate, 500); - assertEquals(testData, event.data); - assertNull(event.metricValue); + try (MockWebServer mockEventsServer = new MockWebServer()) { + mockEventsServer.start(); + // Enqueue a successful empty response + mockEventsServer.enqueue(new MockResponse().addHeader("Date", "")); + + LDConfig ldConfig = baseConfigBuilder(mockEventsServer).build(); + // Don't wait as we are not set offline + try (LDClient client = LDClient.init(application, ldConfig, ldUser, 0)) { + JsonPrimitive testData = new JsonPrimitive("abc"); + + client.track("test-event", testData); + client.blockingFlush(); + + Event[] events = getEventsFromLastRequest(mockEventsServer, 2); + assertEquals(2, events.length); + assertTrue(events[0] instanceof IdentifyEvent); + assertTrue(events[1] instanceof CustomEvent); + CustomEvent event = (CustomEvent) events[1]; + assertEquals("userKey", event.userKey); + assertEquals("test-event", event.key); + assertEquals(System.currentTimeMillis(), event.creationDate, 500); + assertEquals(testData, event.data); + assertNull(event.metricValue); + } + } } @Test public void testTrackDataNull() throws IOException, InterruptedException { - MockWebServer mockEventsServer = new MockWebServer(); - mockEventsServer.start(); - // Enqueue a successful empty response - mockEventsServer.enqueue(new MockResponse().addHeader("Date", "")); - - HttpUrl baseUrl = mockEventsServer.url("/mobile"); - - LDConfig ldConfig = new LDConfig.Builder() - .setMobileKey("test-mobile-sdk-key") - .setEventsUri(Uri.parse(baseUrl.url().toString())) - .build(); - - // Don't wait as we are not set offline - ldClient = LDClient.init(application, ldConfig, ldUser, 0); - - ldClient.track("test-event", null); - ldClient.blockingFlush(); - - RecordedRequest eventPost = mockEventsServer.takeRequest(); - assertEquals("POST", eventPost.getMethod()); - assertEquals("/mobile", eventPost.getPath()); - assertNotNull(eventPost.getHeader("Authorization")); - - Event[] events = TestUtil.getEventDeserializerGson().fromJson(eventPost.getBody().readUtf8(), Event[].class); - assertEquals(2, events.length); - assertTrue(events[0] instanceof IdentifyEvent); - assertTrue(events[1] instanceof CustomEvent); - CustomEvent event = (CustomEvent) events[1]; - assertEquals("userKey", event.userKey); - assertEquals("test-event", event.key); - assertEquals(System.currentTimeMillis(), event.creationDate, 500); - assertNull(event.data); - assertNull(event.metricValue); + try (MockWebServer mockEventsServer = new MockWebServer()) { + mockEventsServer.start(); + // Enqueue a successful empty response + mockEventsServer.enqueue(new MockResponse().addHeader("Date", "")); + + LDConfig ldConfig = baseConfigBuilder(mockEventsServer).build(); + try (LDClient client = LDClient.init(application, ldConfig, ldUser, 0)) { + client.track("test-event", null); + client.blockingFlush(); + + Event[] events = getEventsFromLastRequest(mockEventsServer, 2); + assertEquals(2, events.length); + assertTrue(events[0] instanceof IdentifyEvent); + assertTrue(events[1] instanceof CustomEvent); + CustomEvent event = (CustomEvent) events[1]; + assertEquals("userKey", event.userKey); + assertEquals("test-event", event.key); + assertEquals(System.currentTimeMillis(), event.creationDate, 500); + assertNull(event.data); + assertNull(event.metricValue); + } + } } @Test public void testTrackMetric() throws IOException, InterruptedException { - MockWebServer mockEventsServer = new MockWebServer(); - mockEventsServer.start(); - // Enqueue a successful empty response - mockEventsServer.enqueue(new MockResponse().addHeader("Date", "")); - - HttpUrl baseUrl = mockEventsServer.url("/mobile"); - - LDConfig ldConfig = new LDConfig.Builder() - .setMobileKey("test-mobile-sdk-key") - .setEventsUri(Uri.parse(baseUrl.url().toString())) - .build(); - - // Don't wait as we are not set offline - ldClient = LDClient.init(application, ldConfig, ldUser, 0); - - ldClient.track("test-event", null, 5.5); - ldClient.blockingFlush(); - - RecordedRequest eventPost = mockEventsServer.takeRequest(); - assertEquals("POST", eventPost.getMethod()); - assertEquals("/mobile", eventPost.getPath()); - assertNotNull(eventPost.getHeader("Authorization")); - - Event[] events = TestUtil.getEventDeserializerGson().fromJson(eventPost.getBody().readUtf8(), Event[].class); - assertEquals(2, events.length); - assertTrue(events[0] instanceof IdentifyEvent); - assertTrue(events[1] instanceof CustomEvent); - CustomEvent event = (CustomEvent) events[1]; - assertEquals("userKey", event.userKey); - assertEquals("test-event", event.key); - assertEquals(System.currentTimeMillis(), event.creationDate, 500); - assertNull(event.data); - assertEquals(5.5, event.metricValue, 0); + try (MockWebServer mockEventsServer = new MockWebServer()) { + mockEventsServer.start(); + // Enqueue a successful empty response + mockEventsServer.enqueue(new MockResponse().addHeader("Date", "")); + + LDConfig ldConfig = baseConfigBuilder(mockEventsServer).build(); + try (LDClient client = LDClient.init(application, ldConfig, ldUser, 0)) { + client.track("test-event", null, 5.5); + client.blockingFlush(); + + Event[] events = getEventsFromLastRequest(mockEventsServer, 2); + assertEquals(2, events.length); + assertTrue(events[0] instanceof IdentifyEvent); + assertTrue(events[1] instanceof CustomEvent); + CustomEvent event = (CustomEvent) events[1]; + assertEquals("userKey", event.userKey); + assertEquals("test-event", event.key); + assertEquals(System.currentTimeMillis(), event.creationDate, 500); + assertNull(event.data); + assertEquals(5.5, event.metricValue, 0); + } + } } @Test public void testTrackMetricNull() throws IOException, InterruptedException { - MockWebServer mockEventsServer = new MockWebServer(); - mockEventsServer.start(); - // Enqueue a successful empty response - mockEventsServer.enqueue(new MockResponse().addHeader("Date", "")); - - HttpUrl baseUrl = mockEventsServer.url("/mobile"); - - LDConfig ldConfig = new LDConfig.Builder() - .setMobileKey("test-mobile-sdk-key") - .setEventsUri(Uri.parse(baseUrl.url().toString())) - .build(); - - // Don't wait as we are not set offline - ldClient = LDClient.init(application, ldConfig, ldUser, 0); - - ldClient.track("test-event", null, null); - ldClient.blockingFlush(); - - RecordedRequest eventPost = mockEventsServer.takeRequest(); - assertEquals("POST", eventPost.getMethod()); - assertEquals("/mobile", eventPost.getPath()); - assertNotNull(eventPost.getHeader("Authorization")); - - Event[] events = TestUtil.getEventDeserializerGson().fromJson(eventPost.getBody().readUtf8(), Event[].class); - assertEquals(2, events.length); - assertTrue(events[0] instanceof IdentifyEvent); - assertTrue(events[1] instanceof CustomEvent); - CustomEvent event = (CustomEvent) events[1]; - assertEquals("userKey", event.userKey); - assertEquals("test-event", event.key); - assertEquals(System.currentTimeMillis(), event.creationDate, 500); - assertNull(event.data); - assertNull(event.metricValue); + try (MockWebServer mockEventsServer = new MockWebServer()) { + mockEventsServer.start(); + // Enqueue a successful empty response + mockEventsServer.enqueue(new MockResponse().addHeader("Date", "")); + + LDConfig ldConfig = baseConfigBuilder(mockEventsServer).build(); + try (LDClient client = LDClient.init(application, ldConfig, ldUser, 0)) { + client.track("test-event", null, null); + client.blockingFlush(); + + Event[] events = getEventsFromLastRequest(mockEventsServer, 2); + assertEquals(2, events.length); + assertTrue(events[0] instanceof IdentifyEvent); + assertTrue(events[1] instanceof CustomEvent); + CustomEvent event = (CustomEvent) events[1]; + assertEquals("userKey", event.userKey); + assertEquals("test-event", event.key); + assertEquals(System.currentTimeMillis(), event.creationDate, 500); + assertNull(event.data); + assertNull(event.metricValue); + } + } } @Test public void testTrackDataAndMetric() throws IOException, InterruptedException { - MockWebServer mockEventsServer = new MockWebServer(); - mockEventsServer.start(); - // Enqueue a successful empty response - mockEventsServer.enqueue(new MockResponse().addHeader("Date", "")); - - HttpUrl baseUrl = mockEventsServer.url("/mobile"); - - LDConfig ldConfig = new LDConfig.Builder() - .setMobileKey("test-mobile-sdk-key") - .setEventsUri(Uri.parse(baseUrl.url().toString())) - .build(); - - // Don't wait as we are not set offline - ldClient = LDClient.init(application, ldConfig, ldUser, 0); - - JsonObject testData = new JsonObject(); - testData.add("data", new JsonPrimitive(10)); - - ldClient.track("test-event", testData, -10.0); - ldClient.blockingFlush(); - - RecordedRequest eventPost = mockEventsServer.takeRequest(); - assertEquals("POST", eventPost.getMethod()); - assertEquals("/mobile", eventPost.getPath()); - assertNotNull(eventPost.getHeader("Authorization")); - - Event[] events = TestUtil.getEventDeserializerGson().fromJson(eventPost.getBody().readUtf8(), Event[].class); - assertEquals(2, events.length); - assertTrue(events[0] instanceof IdentifyEvent); - assertTrue(events[1] instanceof CustomEvent); - CustomEvent event = (CustomEvent) events[1]; - assertEquals("userKey", event.userKey); - assertEquals("test-event", event.key); - assertEquals(System.currentTimeMillis(), event.creationDate, 500); - assertEquals(testData, event.data); - assertEquals(-10.0, event.metricValue); + try (MockWebServer mockEventsServer = new MockWebServer()) { + mockEventsServer.start(); + // Enqueue a successful empty response + mockEventsServer.enqueue(new MockResponse().addHeader("Date", "")); + + LDConfig ldConfig = baseConfigBuilder(mockEventsServer).build(); + try (LDClient client = LDClient.init(application, ldConfig, ldUser, 0)) { + JsonObject testData = new JsonObject(); + testData.add("data", new JsonPrimitive(10)); + + client.track("test-event", testData, -10.0); + client.blockingFlush(); + + Event[] events = getEventsFromLastRequest(mockEventsServer, 2); + assertEquals(2, events.length); + assertTrue(events[0] instanceof IdentifyEvent); + assertTrue(events[1] instanceof CustomEvent); + CustomEvent event = (CustomEvent) events[1]; + assertEquals("userKey", event.userKey); + assertEquals("test-event", event.key); + assertEquals(System.currentTimeMillis(), event.creationDate, 500); + assertEquals(testData, event.data); + assertEquals(-10.0, event.metricValue); + } + } } @Test public void variationFlagTrackReasonGeneratesEventWithReason() throws IOException, InterruptedException { - // Setup events server - MockWebServer mockEventsServer = new MockWebServer(); - mockEventsServer.start(); - // Enqueue a successful empty response - mockEventsServer.enqueue(new MockResponse().addHeader("Date", "")); - - HttpUrl baseUrl = mockEventsServer.url("/mobile"); - - String mobileKey = "test-mobile-key"; - LDConfig ldConfig = new LDConfig.Builder() - .setMobileKey(mobileKey) - .setEventsUri(Uri.parse(baseUrl.url().toString())) - .build(); + try (MockWebServer mockEventsServer = new MockWebServer()) { + mockEventsServer.start(); + // Enqueue a successful empty response + mockEventsServer.enqueue(new MockResponse().addHeader("Date", "")); + + LDConfig ldConfig = baseConfigBuilder(mockEventsServer).build(); + + // Setup flag store with test flag + TestUtil.markMigrationComplete(application); + EvaluationReason testReason = EvaluationReason.off(); + FlagStore flagStore = new SharedPrefsFlagStoreFactory(application).createFlagStore(mobileKey + ldUser.getSharedPrefsKey()); + flagStore.applyFlagUpdate(new FlagBuilder("track-reason-flag").trackEvents(true).trackReason(true).reason(testReason).build()); + + try (LDClient client = LDClient.init(application, ldConfig, ldUser, 0)) { + client.boolVariation("track-reason-flag", false); + client.blockingFlush(); + + Event[] events = getEventsFromLastRequest(mockEventsServer, 3); + assertEquals(3, events.length); + assertTrue(events[0] instanceof IdentifyEvent); + assertTrue(events[1] instanceof FeatureRequestEvent); + FeatureRequestEvent event = (FeatureRequestEvent) events[1]; + assertEquals("track-reason-flag", event.key); + assertEquals("userKey", event.userKey); + assertNull(event.variation); + assertNull(event.version); + assertFalse(event.value.getAsBoolean()); + assertFalse(event.defaultVal.getAsBoolean()); + assertEquals(testReason, event.reason); + assertEquals(System.currentTimeMillis(), event.creationDate, 500); + assertTrue(events[2] instanceof SummaryEvent); + } + } + } + + private Event[] getEventsFromLastRequest(MockWebServer server, int expectedCount) throws InterruptedException { + RecordedRequest r = server.takeRequest(); + assertEquals("POST", r.getMethod()); + assertEquals("/mobile", r.getPath()); + assertEquals(LDConfig.AUTH_SCHEME + mobileKey, r.getHeader("Authorization")); + String body = r.getBody().readUtf8(); + System.out.println(body); + Event[] events = TestUtil.getEventDeserializerGson().fromJson(body, Event[].class); + if (events.length != expectedCount) { + assertTrue("count should be " + expectedCount + " for: " + body, false); + } + return events; + } - // Setup flag store with test flag - TestUtil.markMigrationComplete(application); - EvaluationReason testReason = EvaluationReason.off(); - FlagStore flagStore = new SharedPrefsFlagStoreFactory(application).createFlagStore(mobileKey + ldUser.getSharedPrefsKey()); - flagStore.applyFlagUpdate(new FlagBuilder("track-reason-flag").trackEvents(true).trackReason(true).reason(testReason).build()); - - // Don't wait as we are not set offline - ldClient = LDClient.init(application, ldConfig, ldUser, 0); - - ldClient.boolVariation("track-reason-flag", false); - ldClient.blockingFlush(); - - RecordedRequest eventPost = mockEventsServer.takeRequest(); - assertEquals("POST", eventPost.getMethod()); - assertEquals("/mobile", eventPost.getPath()); - assertNotNull(eventPost.getHeader("Authorization")); - - Event[] events = TestUtil.getEventDeserializerGson().fromJson(eventPost.getBody().readUtf8(), Event[].class); - assertEquals(3, events.length); - assertTrue(events[0] instanceof IdentifyEvent); - assertTrue(events[1] instanceof FeatureRequestEvent); - FeatureRequestEvent event = (FeatureRequestEvent) events[1]; - assertEquals("track-reason-flag", event.key); - assertEquals("userKey", event.userKey); - assertNull(event.variation); - assertNull(event.version); - assertFalse(event.value.getAsBoolean()); - assertFalse(event.defaultVal.getAsBoolean()); - assertEquals(testReason, event.reason); - assertEquals(System.currentTimeMillis(), event.creationDate, 500); - assertTrue(events[2] instanceof SummaryEvent); + private LDConfig.Builder baseConfigBuilder(MockWebServer server) { + HttpUrl baseUrl = server.url("/mobile"); + return new LDConfig.Builder() + .setMobileKey(mobileKey) + .setEventsUri(Uri.parse(baseUrl.toString())); } } diff --git a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/DefaultEventProcessor.java b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/DefaultEventProcessor.java index ff4856e6..fb8af6e3 100644 --- a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/DefaultEventProcessor.java +++ b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/DefaultEventProcessor.java @@ -87,7 +87,7 @@ public Thread newThread(@NonNull Runnable r) { } }); - scheduler.scheduleAtFixedRate(consumer, 0, config.getEventsFlushIntervalMillis(), TimeUnit.MILLISECONDS); + scheduler.scheduleAtFixedRate(consumer, config.getEventsFlushIntervalMillis(), config.getEventsFlushIntervalMillis(), TimeUnit.MILLISECONDS); } } From b1d45b98bfe2782fd2801899fbd41e3a8842e23f Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Thu, 14 Nov 2019 14:40:02 -0800 Subject: [PATCH 07/11] remove unreliable test assumption about elapsed time --- .../java/com/launchdarkly/android/LDClientTest.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/launchdarkly-android-client-sdk/src/androidTest/java/com/launchdarkly/android/LDClientTest.java b/launchdarkly-android-client-sdk/src/androidTest/java/com/launchdarkly/android/LDClientTest.java index c16cdb76..f79a014b 100644 --- a/launchdarkly-android-client-sdk/src/androidTest/java/com/launchdarkly/android/LDClientTest.java +++ b/launchdarkly-android-client-sdk/src/androidTest/java/com/launchdarkly/android/LDClientTest.java @@ -212,7 +212,6 @@ public void testTrack() throws IOException, InterruptedException { CustomEvent event = (CustomEvent) events[1]; assertEquals("userKey", event.userKey); assertEquals("test-event", event.key); - assertEquals(System.currentTimeMillis(), event.creationDate, 500); assertNull(event.data); assertNull(event.metricValue); } @@ -240,7 +239,6 @@ public void testTrackData() throws IOException, InterruptedException { CustomEvent event = (CustomEvent) events[1]; assertEquals("userKey", event.userKey); assertEquals("test-event", event.key); - assertEquals(System.currentTimeMillis(), event.creationDate, 500); assertEquals(testData, event.data); assertNull(event.metricValue); } @@ -266,7 +264,6 @@ public void testTrackDataNull() throws IOException, InterruptedException { CustomEvent event = (CustomEvent) events[1]; assertEquals("userKey", event.userKey); assertEquals("test-event", event.key); - assertEquals(System.currentTimeMillis(), event.creationDate, 500); assertNull(event.data); assertNull(event.metricValue); } @@ -292,7 +289,6 @@ public void testTrackMetric() throws IOException, InterruptedException { CustomEvent event = (CustomEvent) events[1]; assertEquals("userKey", event.userKey); assertEquals("test-event", event.key); - assertEquals(System.currentTimeMillis(), event.creationDate, 500); assertNull(event.data); assertEquals(5.5, event.metricValue, 0); } @@ -318,7 +314,6 @@ public void testTrackMetricNull() throws IOException, InterruptedException { CustomEvent event = (CustomEvent) events[1]; assertEquals("userKey", event.userKey); assertEquals("test-event", event.key); - assertEquals(System.currentTimeMillis(), event.creationDate, 500); assertNull(event.data); assertNull(event.metricValue); } @@ -347,7 +342,6 @@ public void testTrackDataAndMetric() throws IOException, InterruptedException { CustomEvent event = (CustomEvent) events[1]; assertEquals("userKey", event.userKey); assertEquals("test-event", event.key); - assertEquals(System.currentTimeMillis(), event.creationDate, 500); assertEquals(testData, event.data); assertEquals(-10.0, event.metricValue); } @@ -385,7 +379,6 @@ public void variationFlagTrackReasonGeneratesEventWithReason() throws IOExceptio assertFalse(event.value.getAsBoolean()); assertFalse(event.defaultVal.getAsBoolean()); assertEquals(testReason, event.reason); - assertEquals(System.currentTimeMillis(), event.creationDate, 500); assertTrue(events[2] instanceof SummaryEvent); } } From c0e71ae1214f6227f2643c467c26bdd1c07ec531 Mon Sep 17 00:00:00 2001 From: Gavin Whelan Date: Mon, 25 Nov 2019 22:21:58 +0000 Subject: [PATCH 08/11] [ch57098] Deprecate LDCountryCode (#141) Deprecate LDCountryCode class and LDUser setters that take LDCountryCode as an argument. --- .../launchdarkly/android/LDCountryCode.java | 2 ++ .../java/com/launchdarkly/android/LDUser.java | 27 ++++++++++++++----- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDCountryCode.java b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDCountryCode.java index caefea1b..a0c2b04a 100644 --- a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDCountryCode.java +++ b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDCountryCode.java @@ -96,6 +96,8 @@ * * @author Takahiko Kawasaki */ +@SuppressWarnings({"deprecation", "DeprecatedIsStillUsed"}) +@Deprecated public enum LDCountryCode { /** * Ascension Island diff --git a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDUser.java b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDUser.java index 80549e1c..718aa0b6 100644 --- a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDUser.java +++ b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDUser.java @@ -211,6 +211,7 @@ public static class Builder { private String email; private String name; private String avatar; + @SuppressWarnings("deprecation") private LDCountryCode country; private final Map custom; @@ -232,6 +233,7 @@ public Builder(String key) { privateAttributeNames = new HashSet<>(); } + @SuppressWarnings("deprecation") public Builder(LDUser user) { this.key = user.getKey(); this.anonymous = user.getAnonymous(); @@ -282,10 +284,12 @@ public Builder privateSecondary(String s) { } /** - * Set the country for a user. The country should be a valid ISO 3166-1 alpha-2 or alpha-3 code. If * it is not a valid ISO-3166-1 code, an attempt will be made to look up the country by its - * name. If that fails, a warning will be logged, and the country will not be set. + * name. If that fails, a warning will be logged, and the country will not be set. In the + * next major release (3.0.0) the SDK will not attempt attempt this lookup, and instead + * treat the country field as a normal String. * * @param s the country for the user * @return the builder @@ -296,11 +300,12 @@ public Builder country(String s) { } /** - * Set the country for a user. The country should be a valid ISO 3166-1 alpha-2 or alpha-3 code. If * it is not a valid ISO-3166-1 code, an attempt will be made to look up the country by its - * name. If that fails, a warning will be logged, and the country will not be set. Private - * attributes are not recorded in events. + * name. If that fails, a warning will be logged, and the country will not be set. In the + * next major release (3.0.0) the SDK will not attempt attempt this lookup, and instead + * treat the country field as a normal String. Private attributes are not recorded in events. * * @param s the country for the user * @return the builder @@ -310,6 +315,8 @@ public Builder privateCountry(String s) { return country(s); } + + @SuppressWarnings("deprecation") private LDCountryCode countryCode(String s) { LDCountryCode countryCode = LDCountryCode.getByCode(s, false); @@ -341,7 +348,11 @@ private LDCountryCode countryCode(String s) { * * @param country the country for the user * @return the builder - */ + * @deprecated As of version 2.9.1, in 3.0.0 the SDK will no longer include the + * LDCountryCode class. Applications should use {@link #country(String)} instead. + * */ + @Deprecated + @SuppressWarnings("deprecation") public Builder country(LDCountryCode country) { this.country = country; return this; @@ -352,7 +363,11 @@ public Builder country(LDCountryCode country) { * * @param country the country for the user * @return the builder + * @deprecated As of version 2.9.1, in 3.0.0 the SDK will no longer include the + * LDCountryCode class. Applications should use {@link #privateCountry(String)} instead. */ + @Deprecated + @SuppressWarnings("deprecation") public Builder privateCountry(LDCountryCode country) { privateAttributeNames.add(COUNTRY); return country(country); From ea19a167aaba71984e59fab70ca5da01b2ba71e8 Mon Sep 17 00:00:00 2001 From: Gavin Whelan Date: Mon, 9 Dec 2019 18:23:10 +0000 Subject: [PATCH 09/11] Catch `SecurityException` when setting alarm in case there are already (#143) the maximum allowed number of alarms on Samsung devices. --- .../com/launchdarkly/android/PollingUpdater.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/PollingUpdater.java b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/PollingUpdater.java index 37e0c1ca..9a0e1405 100644 --- a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/PollingUpdater.java +++ b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/PollingUpdater.java @@ -33,11 +33,15 @@ synchronized static void startPolling(Context context, int initialDelayMillis, i PendingIntent pendingIntent = getPendingIntent(context); AlarmManager alarmMgr = getAlarmManager(context); - alarmMgr.setInexactRepeating( - AlarmManager.ELAPSED_REALTIME, - SystemClock.elapsedRealtime() + initialDelayMillis, - intervalMillis, - pendingIntent); + try { + alarmMgr.setInexactRepeating( + AlarmManager.ELAPSED_REALTIME, + SystemClock.elapsedRealtime() + initialDelayMillis, + intervalMillis, + pendingIntent); + } catch (SecurityException ex) { + Timber.w(ex, "SecurityException when setting background polling alarm"); + } } synchronized static void stop(Context context) { From 23b930ff0ff503a50af8c0ee4dcb294f688deb82 Mon Sep 17 00:00:00 2001 From: Gavin Whelan Date: Fri, 3 Jan 2020 18:25:14 +0000 Subject: [PATCH 10/11] Revert "[ch57098] Deprecate LDCountryCode (#141)" so we can do a patch release first. This reverts commit c0e71ae1214f6227f2643c467c26bdd1c07ec531. --- .../launchdarkly/android/LDCountryCode.java | 2 -- .../java/com/launchdarkly/android/LDUser.java | 27 +++++-------------- 2 files changed, 6 insertions(+), 23 deletions(-) diff --git a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDCountryCode.java b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDCountryCode.java index a0c2b04a..caefea1b 100644 --- a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDCountryCode.java +++ b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDCountryCode.java @@ -96,8 +96,6 @@ * * @author Takahiko Kawasaki */ -@SuppressWarnings({"deprecation", "DeprecatedIsStillUsed"}) -@Deprecated public enum LDCountryCode { /** * Ascension Island diff --git a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDUser.java b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDUser.java index 718aa0b6..80549e1c 100644 --- a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDUser.java +++ b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/android/LDUser.java @@ -211,7 +211,6 @@ public static class Builder { private String email; private String name; private String avatar; - @SuppressWarnings("deprecation") private LDCountryCode country; private final Map custom; @@ -233,7 +232,6 @@ public Builder(String key) { privateAttributeNames = new HashSet<>(); } - @SuppressWarnings("deprecation") public Builder(LDUser user) { this.key = user.getKey(); this.anonymous = user.getAnonymous(); @@ -284,12 +282,10 @@ public Builder privateSecondary(String s) { } /** - * Set the country for a user. In 2.x.x the SDK will attempt to look the country up as a ISO 3166-1 alpha-2 or alpha-3 code. If * it is not a valid ISO-3166-1 code, an attempt will be made to look up the country by its - * name. If that fails, a warning will be logged, and the country will not be set. In the - * next major release (3.0.0) the SDK will not attempt attempt this lookup, and instead - * treat the country field as a normal String. + * name. If that fails, a warning will be logged, and the country will not be set. * * @param s the country for the user * @return the builder @@ -300,12 +296,11 @@ public Builder country(String s) { } /** - * Set the country for a user. In 2.x.x the SDK will attempt to look the country up as a ISO 3166-1 alpha-2 or alpha-3 code. If * it is not a valid ISO-3166-1 code, an attempt will be made to look up the country by its - * name. If that fails, a warning will be logged, and the country will not be set. In the - * next major release (3.0.0) the SDK will not attempt attempt this lookup, and instead - * treat the country field as a normal String. Private attributes are not recorded in events. + * name. If that fails, a warning will be logged, and the country will not be set. Private + * attributes are not recorded in events. * * @param s the country for the user * @return the builder @@ -315,8 +310,6 @@ public Builder privateCountry(String s) { return country(s); } - - @SuppressWarnings("deprecation") private LDCountryCode countryCode(String s) { LDCountryCode countryCode = LDCountryCode.getByCode(s, false); @@ -348,11 +341,7 @@ private LDCountryCode countryCode(String s) { * * @param country the country for the user * @return the builder - * @deprecated As of version 2.9.1, in 3.0.0 the SDK will no longer include the - * LDCountryCode class. Applications should use {@link #country(String)} instead. - * */ - @Deprecated - @SuppressWarnings("deprecation") + */ public Builder country(LDCountryCode country) { this.country = country; return this; @@ -363,11 +352,7 @@ public Builder country(LDCountryCode country) { * * @param country the country for the user * @return the builder - * @deprecated As of version 2.9.1, in 3.0.0 the SDK will no longer include the - * LDCountryCode class. Applications should use {@link #privateCountry(String)} instead. */ - @Deprecated - @SuppressWarnings("deprecation") public Builder privateCountry(LDCountryCode country) { privateAttributeNames.add(COUNTRY); return country(country); From 3a10fdfd0ae66d31adbb75f32c538eee6b57bef3 Mon Sep 17 00:00:00 2001 From: Gavin Whelan Date: Fri, 3 Jan 2020 19:20:56 +0000 Subject: [PATCH 11/11] Update version and add changelog entry for 2.9.1 --- CHANGELOG.md | 6 ++++++ example/build.gradle | 2 +- launchdarkly-android-client-sdk/build.gradle | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e614113a..184d1361 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,12 @@ All notable changes to the LaunchDarkly Android SDK will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org). +## [2.9.1] - 2020-01-03 +### Fixed: +- Removed possibility of fatal `SecurityException` on Samsung devices that would be triggered when the SDK attempted to register an alarm to trigger a future poll when the application process already had 500 alarms registered. This limit is only present on Samsung's versions of Android Lollipop and later. The SDK will now catch this error if it occurs to prevent killing the host application. +- Rarely, the client would deliver its initial "identify" event to LaunchDarkly immediately rather than waiting for the configured flush interval. +- Fixed some malformed Javadoc comments. + ## [2.9.0] - 2019-10-25 ### Added - Added support for new LaunchDarkly experimentation features. See `LDClient.track(String, JsonElement, Double)` for recording numeric metrics. diff --git a/example/build.gradle b/example/build.gradle index 69540ede..64dac3b4 100644 --- a/example/build.gradle +++ b/example/build.gradle @@ -46,7 +46,7 @@ dependencies { implementation 'com.android.support:appcompat-v7:26.1.0' implementation project(path: ':launchdarkly-android-client-sdk') // Comment the previous line and uncomment this one to depend on the published artifact: - //implementation 'com.launchdarkly:launchdarkly-android-client-sdk:2.9.0' + //implementation 'com.launchdarkly:launchdarkly-android-client-sdk:2.9.1' implementation 'com.jakewharton.timber:timber:4.7.1' diff --git a/launchdarkly-android-client-sdk/build.gradle b/launchdarkly-android-client-sdk/build.gradle index f4dff80d..0f9eb19e 100644 --- a/launchdarkly-android-client-sdk/build.gradle +++ b/launchdarkly-android-client-sdk/build.gradle @@ -7,7 +7,7 @@ apply plugin: 'io.codearte.nexus-staging' allprojects { group = 'com.launchdarkly' - version = '2.9.0' + version = '2.9.1' sourceCompatibility = 1.7 targetCompatibility = 1.7 }
CountryCodeLocale