diff --git a/launchdarkly-android-client-sdk/src/androidTest/java/com/launchdarkly/sdk/android/LDClientPluginsTest.java b/launchdarkly-android-client-sdk/src/androidTest/java/com/launchdarkly/sdk/android/LDClientPluginsTest.java index 017c55e9..8f08239b 100644 --- a/launchdarkly-android-client-sdk/src/androidTest/java/com/launchdarkly/sdk/android/LDClientPluginsTest.java +++ b/launchdarkly-android-client-sdk/src/androidTest/java/com/launchdarkly/sdk/android/LDClientPluginsTest.java @@ -151,7 +151,19 @@ public PluginMetadata getMetadata() { @NonNull @Override public String getName() { - return "mock-plugin"; + return "mock-plugin-name"; + } + + @NonNull + @Override + public String getVersion() { + return "mock-plugin-version"; + } + + @NonNull + @Override + public String getId() { + return "mock-plugin-id"; } }; } diff --git a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/LDClient.java b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/LDClient.java index d334d837..d081870e 100644 --- a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/LDClient.java +++ b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/LDClient.java @@ -11,21 +11,23 @@ import com.launchdarkly.sdk.EvaluationReason; import com.launchdarkly.sdk.LDContext; import com.launchdarkly.sdk.LDValue; +import com.launchdarkly.sdk.android.DataModel.Flag; import com.launchdarkly.sdk.android.env.EnvironmentReporterBuilder; import com.launchdarkly.sdk.android.env.IEnvironmentReporter; import com.launchdarkly.sdk.android.integrations.EnvironmentMetadata; import com.launchdarkly.sdk.android.integrations.Hook; import com.launchdarkly.sdk.android.integrations.IdentifySeriesResult; import com.launchdarkly.sdk.android.integrations.Plugin; +import com.launchdarkly.sdk.android.integrations.RegistrationCompleteResult; import com.launchdarkly.sdk.android.integrations.SdkMetadata; import com.launchdarkly.sdk.android.subsystems.ApplicationInfo; import com.launchdarkly.sdk.android.subsystems.Callback; -import com.launchdarkly.sdk.android.DataModel.Flag; import com.launchdarkly.sdk.android.subsystems.EventProcessor; import com.launchdarkly.sdk.android.subsystems.PersistentDataStore; import java.io.Closeable; import java.io.IOException; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -198,7 +200,7 @@ public static Future init(@NonNull Application application, resultFuture.setException(e); return resultFuture; } - }; + } primaryClient = createdPrimaryClient; // this indirect way of setting primaryClient is simply to make it easier to reference // it within an inner class below, since it is "effectively final" @@ -223,13 +225,27 @@ public static Future init(@NonNull Application application, } } + List pluginFailures = new ArrayList<>(); for (Plugin plugin : instance.plugins) { try { plugin.register(instance, metadata); } catch (Exception e) { + pluginFailures.add(new RegistrationCompleteResult.Failure.PluginFailure(plugin.getMetadata().getName(), e.getMessage(), e)); logger.error("Exception thrown registering plugin " + plugin.getMetadata().getName() + "."); } } + + RegistrationCompleteResult pluginsRegistrationResult = pluginFailures.isEmpty() + ? RegistrationCompleteResult.success() + : RegistrationCompleteResult.failure(pluginFailures); + + for (Plugin plugin : instance.plugins) { + try { + plugin.onPluginsReady(pluginsRegistrationResult, metadata); + } catch (Exception e) { + logger.error("Exception thrown executing onPluginsReady for plugin " + plugin.getMetadata().getName() + "."); + } + } } final AtomicInteger initCounter = new AtomicInteger(config.getMobileKeys().size()); diff --git a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/integrations/Plugin.java b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/integrations/Plugin.java index f42a9e72..a4119611 100644 --- a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/integrations/Plugin.java +++ b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/integrations/Plugin.java @@ -26,7 +26,7 @@ public abstract class Plugin { * the SDK is configured with multiple environments. Use the metadata to distinguish * environments. * - * @param client for the plugin to use + * @param client for the plugin to use * @param metadata metadata about the environment where the plugin is running. */ public abstract void register(LDClient client, EnvironmentMetadata metadata); @@ -40,11 +40,15 @@ public abstract class Plugin { * environments. * * @param metadata metadata about the environment where the plugin is running. - * @return + * @return a non-null, possibly empty, list of {@link Hook} instances */ @NonNull public List getHooks(EnvironmentMetadata metadata) { // default impl return Collections.emptyList(); } + + public void onPluginsReady(RegistrationCompleteResult result, EnvironmentMetadata metadata) { + // default: do nothing + } } diff --git a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/integrations/PluginMetadata.java b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/integrations/PluginMetadata.java index 1b9b36d7..2d54b1f6 100644 --- a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/integrations/PluginMetadata.java +++ b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/integrations/PluginMetadata.java @@ -4,6 +4,16 @@ public abstract class PluginMetadata { + @NonNull + public String getId() { + return ""; + } + @NonNull public abstract String getName(); + + @NonNull + public String getVersion() { + return ""; + } } diff --git a/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/integrations/RegistrationCompleteResult.kt b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/integrations/RegistrationCompleteResult.kt new file mode 100644 index 00000000..45b0b71e --- /dev/null +++ b/launchdarkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/integrations/RegistrationCompleteResult.kt @@ -0,0 +1,18 @@ +package com.launchdarkly.sdk.android.integrations + +import com.launchdarkly.sdk.android.integrations.RegistrationCompleteResult.Failure.PluginFailure + +sealed class RegistrationCompleteResult { + object Success : RegistrationCompleteResult() + data class Failure(val failures: List) : RegistrationCompleteResult() { + data class PluginFailure(val pluginName: String, val message: String?, val cause: Throwable?) + } + + companion object { + @JvmStatic + fun success() = Success + + @JvmStatic + fun failure(failures: List) = Failure(failures) + } +}