diff --git a/build.gradle b/build.gradle index 7ce5202..ac72c35 100644 --- a/build.gradle +++ b/build.gradle @@ -1,49 +1,41 @@ +apply plugin: 'com.android.library' + buildscript { repositories { mavenCentral() google() + maven { url "https://jitpack.io" } } dependencies { - classpath 'com.android.tools.build:gradle:3.2.1' - classpath 'com.f2prateek.javafmt:javafmt:0.1.6' - classpath 'io.codearte.gradle.nexus:gradle-nexus-staging-plugin:0.11.0' + classpath 'com.android.tools.build:gradle:4.1.0' + classpath 'com.google.gms:google-services:4.3.15' } } // Use -Prelease or $ORG_GRADLE_PROJECT_RELEASE="true" to mark the project as a release -ext.isRelease = hasProperty('release') +ext.isRelease = true -apply plugin: 'com.android.library' -apply plugin: 'com.f2prateek.javafmt' +group = 'com.segment.analytics.android.integrations' +version = '2.3.4' android { - compileSdkVersion 28 - buildToolsVersion '28.0.3' + compileSdkVersion 32 defaultConfig { - minSdkVersion 14 - targetSdkVersion 28 + minSdkVersion 26 + targetSdkVersion 32 } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 } lintOptions { abortOnError false } - - testOptions { - unitTests { - all { - jvmArgs '-noverify' - } - includeAndroidResources = true - } - } } dependencies { @@ -51,10 +43,11 @@ dependencies { mavenCentral() jcenter() google() + maven { url "https://jitpack.io" } } - api 'com.segment.analytics.android:analytics:4.10.4' - implementation 'com.google.firebase:firebase-analytics:18.0.0' + api 'com.segment.analytics.android:analytics:4.11.3' + implementation 'com.google.firebase:firebase-analytics:21.0.0' testImplementation 'com.segment.analytics.android:analytics-tests:4.3.1' testImplementation 'junit:junit:4.12' @@ -74,5 +67,4 @@ dependencies { apply from: rootProject.file('gradle/attach-jar.gradle') apply from: rootProject.file('gradle/upload.gradle') -apply from: rootProject.file('gradle/sign.gradle') -apply from: rootProject.file('gradle/promote.gradle') +//apply from: rootProject.file('gradle/promote.gradle') diff --git a/gradle.properties b/gradle.properties index f97fb0e..c9361c8 100755 --- a/gradle.properties +++ b/gradle.properties @@ -19,3 +19,5 @@ POM_LICENCE_DIST=repo POM_DEVELOPER_ID=segmentio POM_DEVELOPER_NAME=Segment, Inc. + +android.useAndroidX=true diff --git a/gradle/attach-jar.gradle b/gradle/attach-jar.gradle index e17c640..a75cccb 100644 --- a/gradle/attach-jar.gradle +++ b/gradle/attach-jar.gradle @@ -1,12 +1,15 @@ -// Attaches a JAR to the archives artifact for a library android.libraryVariants.all { variant -> - // Only attach a jar for non-debug build types. - if (!variant.buildType.isDebuggable()) { + // Only attach a jar for non-debug build types. def name = variant.buildType.name - def task = project.tasks.create "jar${name.capitalize()}", Jar - task.dependsOn variant.javaCompile - // Include Java classes - task.from variant.javaCompile.destinationDir - artifacts.add('archives', task); - } -} + def task = project.tasks.create("jar${name.capitalize()}", Jar) { + dependsOn variant.javaCompileProvider + // Include Java classes + from variant.javaCompileProvider.get().destinationDirectory + } + artifacts.add('archives', task) + + // Add JVM arguments to the javaCompile task + variant.javaCompileProvider.configure { + options.forkOptions.jvmArgs += ['--add-opens', 'java.base/java.io=ALL-UNNAMED'] + } +} \ No newline at end of file diff --git a/gradle/upload.gradle b/gradle/upload.gradle index b0410fe..0d8c775 100755 --- a/gradle/upload.gradle +++ b/gradle/upload.gradle @@ -14,60 +14,7 @@ * limitations under the License. */ -apply plugin: 'maven' - afterEvaluate { project -> - uploadArchives { - repositories { - mavenDeployer { - beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } - - def userName = System.getenv("NEXUS_USERNAME") - def password = System.getenv("NEXUS_PASSWORD") - - pom.groupId = GROUP - pom.artifactId = POM_ARTIFACT_ID - pom.version = isRelease ? VERSION.replace('-SNAPSHOT', '') : VERSION - - repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { - authentication(userName: userName, password: password) - } - snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") { - authentication(userName: userName, password: password) - } - - pom.project { - name POM_NAME - packaging POM_PACKAGING - description POM_DESCRIPTION - url POM_URL - - scm { - url POM_SCM_URL - connection POM_SCM_CONNECTION - developerConnection POM_SCM_DEV_CONNECTION - } - - licenses { - license { - name POM_LICENCE_NAME - url POM_LICENCE_URL - distribution POM_LICENCE_DIST - } - } - - developers { - developer { - id POM_DEVELOPER_ID - name POM_DEVELOPER_NAME - } - } - } - } - } - } - - task androidJavadocs(type: Javadoc) { source = android.sourceSets.main.java.srcDirs classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0dad794..2c40fbb 100755 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Aug 23 10:10:41 PDT 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip +android.useAndroidX=true \ No newline at end of file diff --git a/src/main/java/com/segment/analytics/android/integrations/firebase/FirebaseIntegration.java b/src/main/java/com/segment/analytics/android/integrations/firebase/FirebaseIntegration.java index cb21720..b621bf9 100644 --- a/src/main/java/com/segment/analytics/android/integrations/firebase/FirebaseIntegration.java +++ b/src/main/java/com/segment/analytics/android/integrations/firebase/FirebaseIntegration.java @@ -6,7 +6,6 @@ import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.os.Bundle; - import com.google.firebase.analytics.FirebaseAnalytics; import com.google.firebase.analytics.FirebaseAnalytics.Event; import com.google.firebase.analytics.FirebaseAnalytics.Param; @@ -18,12 +17,10 @@ import com.segment.analytics.integrations.Logger; import com.segment.analytics.integrations.TrackPayload; import com.segment.analytics.integrations.ScreenPayload; - import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; - import static com.segment.analytics.internal.Utils.hasPermission; import static com.segment.analytics.internal.Utils.isNullOrEmpty; @@ -192,9 +189,13 @@ public void track(TrackPayload track) { public void screen(ScreenPayload screen) { super.screen(screen); - if (this.currentActivity != null) { - firebaseAnalytics.setCurrentScreen(this.currentActivity, screen.name(), null); + Bundle propertiesBundle = new Bundle(); + for (Map.Entry entry : screen.entrySet()) { + propertiesBundle.putString(entry.getKey(), entry.getValue().toString()); } + propertiesBundle.putString(FirebaseAnalytics.Param.SCREEN_NAME, screen.name()); + firebaseAnalytics.logEvent(FirebaseAnalytics.Event.SCREEN_VIEW, propertiesBundle); + logger.verbose("firebaseAnalytics.screen(activity, %s, null);", screen.name()); } private static Bundle formatProperties(Properties properties) { diff --git a/src/test/java/com/segment/analytics/android/integration/firebase/FirebaseTest.java b/src/test/java/com/segment/analytics/android/integration/firebase/FirebaseTest.java deleted file mode 100644 index 091c7af..0000000 --- a/src/test/java/com/segment/analytics/android/integration/firebase/FirebaseTest.java +++ /dev/null @@ -1,290 +0,0 @@ -package com.segment.analytics.android.integration.firebase; - -import android.app.Activity; -import android.content.Context; -import android.os.Bundle; - -import com.google.firebase.analytics.FirebaseAnalytics; -import com.segment.analytics.Properties; -import com.segment.analytics.android.integrations.firebase.FirebaseIntegration; -import com.segment.analytics.integrations.IdentifyPayload; -import com.segment.analytics.integrations.Logger; -import com.segment.analytics.integrations.ScreenPayload; -import com.segment.analytics.integrations.TrackPayload; - -import org.json.JSONException; -import org.json.JSONObject; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentMatcher; -import org.mockito.Mockito; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PowerMockIgnore; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.rule.PowerMockRule; -import org.robolectric.RobolectricTestRunner; -import org.skyscreamer.jsonassert.JSONAssert; -import org.skyscreamer.jsonassert.JSONCompareMode; - -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; - -import static com.segment.analytics.Analytics.LogLevel.VERBOSE; -import static org.mockito.Matchers.argThat; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.isNull; -import static org.mockito.Mockito.verify; - -@RunWith(RobolectricTestRunner.class) -@PowerMockIgnore({ "org.mockito.*", "org.roboelectric.*", "android.*" }) -@PrepareForTest(FirebaseAnalytics.class) -public class FirebaseTest { - - @Rule - public PowerMockRule rule = new PowerMockRule(); - private FirebaseAnalytics firebase; - private FirebaseIntegration integration; - - @Before - public void setUp() { - firebase = PowerMockito.mock(FirebaseAnalytics.class); - Context context = PowerMockito.mock(Context.class); - - PowerMockito.mockStatic(FirebaseAnalytics.class); - Mockito.when(FirebaseAnalytics.getInstance(context)).thenReturn(firebase); - - integration = new FirebaseIntegration(context, Logger.with(VERBOSE)); - } - - @Test - public void identify() { - integration.identify(new IdentifyPayload.Builder().userId("foo").traits(new HashMap()).build()); - verify(firebase).setUserId("foo"); - } - - @Test - public void identifyWithTraits() { - Map traits = new HashMap<>(); - traits.put("age", 20); - traits.put("firstName", "bar"); - traits.put("lastName", "baz"); - traits.put("Sign Up Date", new Date(117, 6, 14)); - traits.put(" extra spaces ", "bar"); - - integration.identify(new IdentifyPayload.Builder().userId("foo").anonymousId("123").traits(traits).build()); - - verify(firebase).setUserId("foo"); - verify(firebase).setUserProperty("firstName", "bar"); - verify(firebase).setUserProperty("lastName", "baz"); - verify(firebase).setUserProperty("Sign_Up_Date", String.valueOf(new Date(117, 6, 14))); - verify(firebase).setUserProperty("extra_spaces", "bar"); - verify(firebase).setUserProperty("age", "20"); - } - - @Test - public void track() { - integration.track(new TrackPayload.Builder().anonymousId("12345").event("foo").build()); - verify(firebase).logEvent(eq("foo"), bundleEq(new Bundle())); - } - - @Test - public void trackWithProperties() { - Properties properties = new Properties() - .putValue("integer", 1) - .putValue("double", 1.0) - .putValue("string", "foo") - .putValue("date", new Date(117, 0, 1)) - .putValue("key with spaces", "bar") - .putValue("key.with.periods", "test") - .putValue("total", 100.0) - .putValue(" extra spaces ", "baz"); - - integration.track(new TrackPayload.Builder().anonymousId("1234").properties(properties).event("foo").build()); - - Bundle expected = new Bundle(); - expected.putInt("integer", 1); - expected.putDouble("double", 1.0); - expected.putString("string", "foo"); - expected.putString("date", String.valueOf(new Date(117, 0, 1))); - expected.putString("key_with_spaces", "bar"); - expected.putString("key_with_periods", "test"); - expected.putDouble("value", 100.0); - expected.putString("currency", "USD"); - expected.putString("extra_spaces", "baz"); - - verify(firebase).logEvent(eq("foo"), bundleEq(expected)); - } - - @Test - public void trackPurchaseWithProducts() { - Properties properties = new Properties() - .putValue("revenue", 100.0) - .putValue("currency", "USD"); - Properties.Product product1 = new Properties.Product( "123", "abc", 10.0); - product1.putName("foo"); - product1.put("category", "bar"); - product1.put("quantity", 2); - properties.putProducts(product1); - - integration.track(new TrackPayload.Builder().anonymousId("1234").properties(properties).event("Order Completed").build()); - - Bundle product = new Bundle(); - product.putString("item_id", "123"); - product.putString("item_name", "foo"); - product.putString("item_category", "bar"); - product.putDouble("price", 10.0); - product.putString("sku", "abc"); - product.putInt("quantity", 2); - - ArrayList items = new ArrayList<>(); - items.add(product); - - Bundle expected = new Bundle(); - expected.putDouble("value", 100.0); - expected.putString("currency", "USD"); - expected.putParcelableArrayList("items", items); - - verify(firebase).logEvent(eq("purchase"), bundleEq(expected)); - } - - @Test - public void trackPurchaseWithNullProducts() { - Properties properties = new Properties() - .putValue("revenue", 100.0) - .putValue("currency", "USD") - .putValue("products", null); - - integration.track(new TrackPayload.Builder().anonymousId("1234").properties(properties).event("Order Completed").build()); - - Bundle expected = new Bundle(); - expected.putDouble("value", 100.0); - expected.putString("currency", "USD"); - expected.putString("items", null); - - verify(firebase).logEvent(eq("purchase"), bundleEq(expected)); - } - - @Test - public void trackWithEventNameTransformation() { - Properties properties = new Properties() - .putValue("integer", 1) - .putValue("double", 1.0) - .putValue("string", "foo") - .putValue("date", new Date(117, 0, 1)) - .putValue("key with spaces", "bar") - .putValue("key.with.periods", "test") - .putValue("total", 100.0) - .putValue(" extra spaces ", "baz"); - - integration.track(new TrackPayload.Builder().anonymousId("1234").properties(properties).event("foo.bar").build()); - - Bundle expected = new Bundle(); - expected.putInt("integer", 1); - expected.putDouble("double", 1.0); - expected.putString("string", "foo"); - expected.putString("date", String.valueOf(new Date(117, 0, 1))); - expected.putString("key_with_spaces", "bar"); - expected.putString("key_with_periods", "test"); - expected.putDouble("value", 100.0); - expected.putString("currency", "USD"); - expected.putString("extra_spaces", "baz"); - - verify(firebase).logEvent(eq("foo_bar"), bundleEq(expected)); - } - - @Test - public void productsSearchedTransformation() { - integration.track(new TrackPayload.Builder().anonymousId("12345").event("Products Searched").build()); - verify(firebase).logEvent(eq("search"), bundleEq(new Bundle())); - } - - @Test - public void trackScreenWithName() { - final Activity activity = PowerMockito.mock(Activity.class); - integration.onActivityStarted(activity); - - integration.screen(new ScreenPayload.Builder().anonymousId("1234").name("home_screen").build()); - - verify(firebase).setCurrentScreen(any(Activity.class), eq("home_screen"), (String) isNull()); - } - - @Test - public void makeKeyWithDash() { - integration.track(new TrackPayload.Builder().anonymousId("12345").event("test-event-dashed").build()); - verify(firebase).logEvent(eq("test_event_dashed"), bundleEq(new Bundle())); - } - - @Test - public void makeKeyWithDot() { - integration.track(new TrackPayload.Builder().anonymousId("12345").event("test.event").build()); - verify(firebase).logEvent(eq("test_event"), bundleEq(new Bundle())); - } - - @Test - public void makeKeyWithSpace() { - integration.track(new TrackPayload.Builder().anonymousId("12345").event("test event").build()); - verify(firebase).logEvent(eq("test_event"), bundleEq(new Bundle())); - } - - @Test - public void makeKeyWithDashAndDot() { - integration.track(new TrackPayload.Builder().anonymousId("12345").event("test-event-dashed-and.dotted").build()); - verify(firebase).logEvent(eq("test_event_dashed_and_dotted"), bundleEq(new Bundle())); - } - - @Test - public void makeKeyWithColon() { - integration.track(new TrackPayload.Builder().anonymousId("12345").event("test:colon").build()); - verify(firebase).logEvent(eq("test_colon"), bundleEq(new Bundle())); - } - - /** - * Uses the string representation of the object. Useful for JSON objects. - * @param expected Expected object - * @return Argument matcher. - */ - private JSONObject jsonEq(JSONObject expected) { - return argThat(new JSONMatcher(expected)); - } - - class JSONMatcher implements ArgumentMatcher { - JSONObject expected; - - JSONMatcher(JSONObject expected) { - this.expected = expected; - } - - @Override - public boolean matches(JSONObject argument) { - try { - JSONAssert.assertEquals(expected, argument, JSONCompareMode.STRICT); - return true; - } catch (JSONException e) { - return false; - } - } - } - - public static Bundle bundleEq(Bundle expected) { - return argThat(new BundleObjectMatcher(expected)); - } - - private static class BundleObjectMatcher implements ArgumentMatcher { - Bundle expected; - - private BundleObjectMatcher(Bundle expected) { - this.expected = expected; - } - - @Override - public boolean matches(Bundle bundle) { - return expected.toString().equals(bundle.toString()); - } - - } -}