diff --git a/.gitmodules b/.gitmodules index 6bdac6cd9..9a67b0087 100644 --- a/.gitmodules +++ b/.gitmodules @@ -79,6 +79,9 @@ [submodule "kits/revealmobile-kit"] path = kits/revealmobile-kit url = git@github.com:mparticle-integrations/mparticle-android-integration-revealmobile.git +[submodule "kits/rokt-kit"] + path = kits/rokt-kit + url = git@github.com:mparticle-integrations/mparticle-android-integration-rokt.git [submodule "kits/singular-kit"] path = kits/singular-kit url = git@github.com:mparticle-integrations/mparticle-android-integration-singular.git diff --git a/android-core/build.gradle b/android-core/build.gradle index 3943a17f5..59b16add6 100644 --- a/android-core/build.gradle +++ b/android-core/build.gradle @@ -164,8 +164,8 @@ dependencies { androidTestImplementation project(':testutils') if (useOrchestrator()) { - androidTestImplementation 'androidx.test:runner:1.4.0' - androidTestUtil 'androidx.test:orchestrator:1.4.2' + androidTestImplementation 'androidx.test:runner:1.5.2' + androidTestUtil 'androidx.test:orchestrator:1.5.0' } androidTestImplementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" androidTestImplementation "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version" diff --git a/android-core/src/main/java/com/mparticle/MParticle.java b/android-core/src/main/java/com/mparticle/MParticle.java index 0203271db..b7abdec18 100644 --- a/android-core/src/main/java/com/mparticle/MParticle.java +++ b/android-core/src/main/java/com/mparticle/MParticle.java @@ -6,6 +6,7 @@ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.graphics.Typeface; import android.location.Location; import android.location.LocationManager; import android.net.Uri; @@ -51,12 +52,13 @@ import com.mparticle.media.MediaCallbacks; import com.mparticle.messaging.MPMessagingAPI; import com.mparticle.messaging.ProviderCloudMessage; -import com.mparticle.segmentation.SegmentListener; +import com.mparticle.rokt.RoktEmbeddedView; import org.jetbrains.annotations.NotNull; import org.json.JSONObject; import java.io.File; +import java.lang.ref.WeakReference; import java.math.BigDecimal; import java.util.HashMap; import java.util.HashSet; @@ -111,6 +113,7 @@ public class MParticle { protected boolean locationTrackingEnabled = false; @NonNull protected Internal mInternal = new Internal(); + protected Rokt rokt = new Rokt(); private IdentityStateListener mDeferredModifyPushRegistrationListener; @NonNull private WrapperSdkVersion wrapperSdkVersion = new WrapperSdkVersion(WrapperSdk.WrapperNone, null); @@ -1170,6 +1173,10 @@ public void logNotificationOpened(@NonNull Intent intent) { public Internal Internal() { return mInternal; } + @NonNull + public Rokt Rokt() { + return rokt; + } void refreshConfiguration() { Logger.debug("Refreshing configuration..."); @@ -1703,6 +1710,7 @@ public interface ServiceProviders { int SWRVE = 1145; int BLUESHIFT = 1144; int NEURA = 147; + int ROKT = 181; @NonNull String BROADCAST_ACTIVE = "MPARTICLE_SERVICE_PROVIDER_ACTIVE_"; @NonNull @@ -1774,6 +1782,46 @@ public interface ResetListener { } + /** + * Rokt Integration + * */ + public class Rokt{ + protected Rokt(){ + + } + public void selectPlacements(String viewName, + Map attributes, + Runnable onUnload, + Runnable onLoad, + Runnable onShouldHideLoadingIndicator, + Runnable onShouldShowLoadingIndicator, + Map> placeHolders, + Map> fontTypefaces) { + if (mConfigManager.isEnabled()) { + mKitManager.execute(viewName, + attributes, + onUnload, + onLoad, + onShouldHideLoadingIndicator, + onShouldShowLoadingIndicator, + placeHolders, + fontTypefaces); + } + } + public void selectPlacements(String viewName, + Map attributes) { + if (mConfigManager.isEnabled()) { + mKitManager.execute(viewName, + attributes, + null, + null, + null, + null, + null, + null); + } + } + } /** * @hidden */ diff --git a/android-core/src/main/java/com/mparticle/internal/KitFrameworkWrapper.java b/android-core/src/main/java/com/mparticle/internal/KitFrameworkWrapper.java index 9bf00f726..68d3e4720 100644 --- a/android-core/src/main/java/com/mparticle/internal/KitFrameworkWrapper.java +++ b/android-core/src/main/java/com/mparticle/internal/KitFrameworkWrapper.java @@ -3,6 +3,7 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; +import android.graphics.Typeface; import android.location.Location; import android.net.Uri; import android.os.Bundle; @@ -19,6 +20,7 @@ import com.mparticle.identity.IdentityApiRequest; import com.mparticle.identity.MParticleUser; import com.mparticle.internal.listeners.InternalListenerManager; +import com.mparticle.rokt.RoktEmbeddedView; import org.json.JSONArray; @@ -646,6 +648,27 @@ public void reset() { } } + @Override + public void execute(String viewName, + Map attributes, + Runnable onUnload, + Runnable onLoad, + Runnable onShouldHideLoadingIndicator, + Runnable onShouldShowLoadingIndicator, + Map> placeHolders, + Map> fontTypefaces) { + if (mKitManager != null) { + mKitManager.execute(viewName, + attributes, + onUnload, + onLoad, + onShouldHideLoadingIndicator, + onShouldShowLoadingIndicator, + placeHolders, + fontTypefaces); + } + } + static class CoreCallbacksImpl implements CoreCallbacks { KitFrameworkWrapper mKitFrameworkWrapper; ConfigManager mConfigManager; diff --git a/android-core/src/main/java/com/mparticle/internal/KitManager.java b/android-core/src/main/java/com/mparticle/internal/KitManager.java index 2f7bfda51..0f64bfbb4 100644 --- a/android-core/src/main/java/com/mparticle/internal/KitManager.java +++ b/android-core/src/main/java/com/mparticle/internal/KitManager.java @@ -3,6 +3,7 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; +import android.graphics.Typeface; import android.location.Location; import android.net.Uri; import android.os.Bundle; @@ -17,6 +18,7 @@ import com.mparticle.consent.ConsentState; import com.mparticle.identity.IdentityApiRequest; import com.mparticle.identity.MParticleUser; +import com.mparticle.rokt.RoktEmbeddedView; import org.json.JSONArray; @@ -120,6 +122,15 @@ public interface KitManager { void reset(); + void execute(String viewName, + Map attributes, + Runnable onUnload, + Runnable onLoad, + Runnable onShouldHideLoadingIndicator, + Runnable onShouldShowLoadingIndicator, + Map> placeHolders, + Map> fontTypefaces); + enum KitStatus { NOT_CONFIGURED, STOPPED, diff --git a/android-core/src/main/kotlin/com/mparticle/rokt/RoktEmbeddedView.kt b/android-core/src/main/kotlin/com/mparticle/rokt/RoktEmbeddedView.kt new file mode 100644 index 000000000..590969b67 --- /dev/null +++ b/android-core/src/main/kotlin/com/mparticle/rokt/RoktEmbeddedView.kt @@ -0,0 +1,13 @@ +package com.mparticle.rokt + +import android.content.Context +import android.util.AttributeSet +import android.widget.FrameLayout + +class RoktEmbeddedView : FrameLayout { + constructor(context: Context) : super(context) + + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) + + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) +} \ No newline at end of file diff --git a/android-core/src/test/kotlin/com/mparticle/MParticleTest.kt b/android-core/src/test/kotlin/com/mparticle/MParticleTest.kt index 142c2bcfc..9181872aa 100644 --- a/android-core/src/test/kotlin/com/mparticle/MParticleTest.kt +++ b/android-core/src/test/kotlin/com/mparticle/MParticleTest.kt @@ -1,5 +1,6 @@ package com.mparticle +import android.graphics.Typeface import android.os.Looper import android.os.SystemClock import android.webkit.WebView @@ -17,6 +18,7 @@ import com.mparticle.internal.MessageManager import com.mparticle.media.MPMediaAPI import com.mparticle.messaging.MPMessagingAPI import com.mparticle.mock.MockContext +import com.mparticle.rokt.RoktEmbeddedView import com.mparticle.testutils.AndroidUtils import com.mparticle.testutils.RandomUtils import org.junit.Assert @@ -25,10 +27,16 @@ import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.ArgumentMatchers +import org.mockito.ArgumentMatchers.any import org.mockito.Mockito +import org.mockito.Mockito.mock +import org.mockito.Mockito.never +import org.mockito.Mockito.verify +import org.mockito.Mockito.`when` import org.powermock.api.mockito.PowerMockito import org.powermock.core.classloader.annotations.PrepareForTest import org.powermock.modules.junit4.PowerMockRunner +import java.lang.ref.WeakReference import java.util.LinkedList import java.util.concurrent.ExecutorService import java.util.concurrent.Executors @@ -461,6 +469,53 @@ class MParticleTest { } } + @Test + fun testSelectPlacements_withFullParams_whenEnabled() { + var instance: MParticle = InnerMockMParticle() + MParticle.setInstance(instance) + `when`(instance.mConfigManager.isEnabled).thenReturn(true) + + val attributes = mutableMapOf() + attributes["key"] = "value" + + val placeholders: Map> = HashMap() + val fonts: Map> = HashMap() + + val onLoad: Runnable = mock(Runnable::class.java) + val onUnload: Runnable = mock(Runnable::class.java) + val onHide: Runnable = mock(Runnable::class.java) + val onShow: Runnable = mock(Runnable::class.java) + + instance.rokt!!.selectPlacements("testView", attributes, onUnload, onLoad, onHide, onShow, placeholders, fonts) + + verify(instance.mKitManager)?.execute("testView", attributes, onUnload, onLoad, onHide, onShow, placeholders, fonts) + } + + @Test + fun testSelectPlacements_withBasicParams_whenEnabled() { + var instance: MParticle = InnerMockMParticle() + MParticle.setInstance(instance) + `when`(instance.mConfigManager.isEnabled()).thenReturn(true) + + val attributes = mutableMapOf() + attributes.put("a", "b") + + instance.rokt.selectPlacements("basicView", attributes) + + verify(instance.mKitManager).execute("basicView", attributes, null, null, null, null, null, null) + } + + @Test + fun testSelectPlacements_withBasicParams_whenDisabled() { + var instance: MParticle = InnerMockMParticle() + MParticle.setInstance(instance) + `when`(instance.mConfigManager.isEnabled()).thenReturn(false) + + instance.rokt.selectPlacements("basicView", HashMap()) + + verify(instance.mKitManager, never()).execute(any(), any(), any(), any(), any(), any(), any(), any()) + } + inner class InnerMockMParticle : MParticle() { init { mConfigManager = ConfigManager(MockContext()) diff --git a/android-core/src/test/kotlin/com/mparticle/external/ApiVisibilityTest.kt b/android-core/src/test/kotlin/com/mparticle/external/ApiVisibilityTest.kt index 3017d6bbf..7f5b88619 100644 --- a/android-core/src/test/kotlin/com/mparticle/external/ApiVisibilityTest.kt +++ b/android-core/src/test/kotlin/com/mparticle/external/ApiVisibilityTest.kt @@ -17,7 +17,7 @@ class ApiVisibilityTest { publicMethodCount++ } } - Assert.assertEquals(65, publicMethodCount) + Assert.assertEquals(66, publicMethodCount) } @Test diff --git a/android-kit-base/src/main/java/com/mparticle/kits/KitIntegration.java b/android-kit-base/src/main/java/com/mparticle/kits/KitIntegration.java index 929c93a8e..0be1bc655 100644 --- a/android-kit-base/src/main/java/com/mparticle/kits/KitIntegration.java +++ b/android-kit-base/src/main/java/com/mparticle/kits/KitIntegration.java @@ -4,6 +4,7 @@ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.graphics.Typeface; import android.location.Location; import android.net.Uri; import android.os.Bundle; @@ -17,6 +18,7 @@ import com.mparticle.commerce.CommerceEvent; import com.mparticle.consent.ConsentState; import com.mparticle.identity.MParticleUser; +import com.mparticle.rokt.RoktEmbeddedView; import org.json.JSONObject; @@ -608,4 +610,16 @@ public interface UserAttributeListener { public interface BatchListener { List logBatch(JSONObject jsonObject); } + + public interface RoktListener { + void execute(String viewName, + Map attributes, + Runnable onUnload, + Runnable onLoad, + Runnable onShouldHideLoadingIndicator, + Runnable onShouldShowLoadingIndicator, + Map> placeHolders, + Map> fontTypefaces, + FilteredMParticleUser user); + } } diff --git a/android-kit-base/src/main/java/com/mparticle/kits/KitIntegrationFactory.java b/android-kit-base/src/main/java/com/mparticle/kits/KitIntegrationFactory.java index 93dd7fcec..fe772a0c8 100644 --- a/android-kit-base/src/main/java/com/mparticle/kits/KitIntegrationFactory.java +++ b/android-kit-base/src/main/java/com/mparticle/kits/KitIntegrationFactory.java @@ -64,6 +64,7 @@ private void setupKnownIntegrations() { knownIntegrations.put(MParticle.ServiceProviders.SWRVE, "com.mparticle.kits.SwrveKit"); knownIntegrations.put(MParticle.ServiceProviders.BLUESHIFT, "com.mparticle.kits.BlueshiftKit"); knownIntegrations.put(MParticle.ServiceProviders.NEURA, "com.mparticle.kits.NeuraKit"); + knownIntegrations.put(MParticle.ServiceProviders.ROKT, "com.mparticle.kits.RoktKit"); } public KitIntegration createInstance(KitManagerImpl manager, KitConfiguration configuration) throws JSONException, ClassNotFoundException { diff --git a/android-kit-base/src/main/java/com/mparticle/kits/KitManagerImpl.java b/android-kit-base/src/main/java/com/mparticle/kits/KitManagerImpl.java index f4af5a035..8148a7d3e 100644 --- a/android-kit-base/src/main/java/com/mparticle/kits/KitManagerImpl.java +++ b/android-kit-base/src/main/java/com/mparticle/kits/KitManagerImpl.java @@ -3,6 +3,7 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; +import android.graphics.Typeface; import android.location.Location; import android.net.Uri; import android.os.Bundle; @@ -35,6 +36,7 @@ import com.mparticle.internal.MPUtility; import com.mparticle.internal.ReportingManager; import com.mparticle.kits.mappings.CustomMapping; +import com.mparticle.rokt.RoktEmbeddedView; import org.json.JSONArray; import org.json.JSONException; @@ -1319,6 +1321,42 @@ public void reset() { } } + @Override + public void execute(String viewName, + Map attributes, + Runnable onUnload, + Runnable onLoad, + Runnable onShouldHideLoadingIndicator, + Runnable onShouldShowLoadingIndicator, + Map> placeHolders, + Map> fontTypefaces) { + for (KitIntegration provider : providers.values()) { + try { + if (provider instanceof KitIntegration.RoktListener && !provider.isDisabled()) { + MParticleUser user = MParticle.getInstance().Identity().getCurrentUser(); + Map objectAttributes = new HashMap<>(); + + for (Map.Entry entry : attributes.entrySet()) { + objectAttributes.put(entry.getKey(), entry.getValue()); + } + + user.setUserAttributes(objectAttributes); + ((KitIntegration.RoktListener) provider).execute(viewName, + attributes, + onUnload, + onLoad, + onShouldHideLoadingIndicator, + onShouldShowLoadingIndicator, + placeHolders, + fontTypefaces, + FilteredMParticleUser.getInstance(user.getId(), provider)); + } + } catch (Exception e) { + Logger.warning("Failed to call execute for kit: " + provider.getName() + ": " + e.getMessage()); + } + } + } + public void runOnKitThread(Runnable runnable) { if (mKitHandler == null) { mKitHandler = new Handler(kitHandlerThread.getLooper()); diff --git a/settings-kits.gradle b/settings-kits.gradle index 48bd25d0c..5a27af3da 100644 --- a/settings-kits.gradle +++ b/settings-kits.gradle @@ -29,6 +29,7 @@ include ( ':kits:radar-kit', ':kits:responsys-kit', ':kits:revealmobile-kit', + ':kits:rokt-kit', ':kits:singular-kit', ':kits:skyhook-kit', //Swrve hosts kit diff --git a/testutils/src/main/java/com/mparticle/mock/MockMParticle.java b/testutils/src/main/java/com/mparticle/mock/MockMParticle.java index 31c88db10..ab1e34fea 100644 --- a/testutils/src/main/java/com/mparticle/mock/MockMParticle.java +++ b/testutils/src/main/java/com/mparticle/mock/MockMParticle.java @@ -35,4 +35,11 @@ class MockInternal extends Internal { super(); } } + + class MockRokt extends Rokt { + + MockRokt() { + super(); + } + } }