diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..767d44e --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,41 @@ +License Agreement + +Thank You for Your interest in our Tealium Remote Command Library (the "Software"), owned and licensed by Tealium Inc. (“Tealium,” "Our," “We,” or “Us”). Please read this license agreement (the "Agreement") carefully, as it contains the terms and conditions that govern Your use of and access to the Software. + +You may not access the Software if You are Our direct competitor, except with Our prior written consent. In addition, You may not access the Software for purposes of monitoring the availability, performance, or functionality, of any of our products and services or for any other benchmarking or competitive purposes. + +BY DOWNLOADING THE SOFTWARE OR BY EXECUTING A TEALIUM PROVIDED ORDER FORM THAT REFERENCES THIS AGREEMENT, YOU AGREE TO BE BOUND BY AND COMPLY WITH THIS AGREEMENT. IF YOU ARE ENTERING INTO THIS AGREEMENT ON BEHALF OF A COMPANY OR OTHER LEGAL ENTITY, YOU REPRESENT THAT YOU HAVE THE AUTHORITY TO BIND SUCH ENTITY AND ITS AFFILIATES TO THIS AGREEMENT, IN WHICH CASE THE TERMS "YOU" OR "YOUR" WILL REFER TO SUCH ENTITY AND ITS AFFILIATES. IF YOU DO NOT HAVE SUCH AUTHORITY, OR IF YOU DO NOT AGREE WITH THE TERMS OF THIS AGREEMENT, YOU MUST NOT USE THE SOFTWARE. + +The term of Your license to use the Software (the "Term") will begin when You accept this Agreement as set forth above and will continue until terminated pursuant to the provisions of the "Cancellation and Termination" section below. During the Term, We grant You a non-exclusive, non-transferable, royalty-free, limited license (with no right to sublicense) to use the Software to do the following: + +develop software applications and functionality designed to be used in conjunction with Tealium's products and services; +conduct quality assurance testing to ensure compatibility between your software application and Tealium's products and services; and +conduct support testing to troubleshoot compatibility between your software application and Tealium's products and services. + +During the Term, Tealium further grants to You a non-exclusive, non-transferable, royalty-free, limited world-wide license (with no right to sublicense) to market, reproduce, and distribute applications incorporating the integration You develop under this Agreement, either directly or through multiple levels of distributors, Your end users, but only under an end-user license agreement with terms that are as protective of Tealium's rights as this Agreement. + +We do not grant any other rights to the Software. You may only use the Software during the Term, we reserve all rights not expressly granted under this Agreement, and there are no implied rights or other rights We grant hereunder, whether by estoppel or otherwise. You may not: (i) copy or reproduce the Software (except for reasonable archival purposes); (ii) modify or create any derivative works of the Software; (iii) decompile, disassemble, or reverse engineer the Software (except to the extent expressly permitted under applicable law); or (iv) remove or alter any trademark, logo, copyright or other proprietary notices, legends, symbols or labels in the Software. Further, You may not use the Software for any illegal or unauthorized purpose. + +Tealium will retain all title, ownership, and Intellectual Property Rights in the Software and any derivative works thereof. “Intellectual Property Rights” will mean all patent, copyright, trade secret, trademark and other proprietary and intellectual property rights, including moral rights. The Software is protected by copyright and other intellectual property laws and by international treaties. You agree that We will own all suggestions, enhancements requests, feedback, recommendations, or other input provided by You or any other party relating to the Software. Other than the use licenses expressly granted in this Agreement, neither this Agreement nor its performance transfers from Us to You any Tealium intellectual property. + +General Conditions and Restrictions +Your use of the Software is at Your sole risk. +You agree that Tealium is under no obligation to provide You with support for the Software, or to provide You with updates or error corrections ("Updates") to the Software. If Tealium, at its sole discretion, decides to provide You with Updates, Updates will be considered part of Software, and subject to the terms of this Agreement. +You agree not to reproduce, duplicate, copy, sell, resell, or exploit any portion or feature of the Software or access to the Software without express written permission from Tealium. + +No Warranty +THE SOFTWARE IS PROVIDED ON AN “AS IS” AND “AS AVAILABLE” BASIS, AND TEALIUM EXPRESSLY DISCLAIMS ANY WARRANTIES AND CONDITIONS OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, QUIET ENJOYMENT, ACCURACY, OR NON-INFRINGEMENT. WITHOUT LIMITING THE FOREGOING, TEALIUM DOES NOT WARRANT THAT THE SERVICE WILL MEET YOUR SPECIFIC REQUIREMENTS, THAT THE SERVICE WILL BE UNINTERRUPTED, TIMELY, SECURE, OR ERROR-FREE, THAT THE RESULTS THAT MAY BE OBTAINED FROM THE USE OF THE SOFTWARE WILL BE COMPLETE, ACCURATE, OR RELIABLE, THAT THE QUALITY OF ANY PRODUCTS, SERVICES, INFORMATION, OR OTHER MATERIAL PURCHASED OR OBTAINED BY YOU THROUGH THE SOFTWARE WILL MEET YOUR EXPECTATIONS, OR THAT ANY ERRORS IN THE SOFTWARE WILL BE CORRECTED. + +Limitation of Liability +YOU EXPRESSLY UNDERSTAND AND AGREE THAT TEALIUM WILL NOT BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL OR EXEMPLARY DAMAGES, INCLUDING BUT NOT LIMITED TO DAMAGES FOR LOSS OF PROFITS, GOODWILL, USE, DATA OR OTHER INTANGIBLE LOSSES (EVEN IF TEALIUM HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES), INCLUDING ANY SUCH DAMAGES RESULTING FROM THE USE OR THE INABILITY TO USE THE SOFTWARE; THE COST OF PROCUREMENT OF SUBSTITUTE GOODS AND SERVICES RESULTING FROM ANY GOODS, DATA, INFORMATION OR SERVICES PURCHASED OR OBTAINED OR MESSAGES RECEIVED OR TRANSACTIONS ENTERED INTO THROUGH OR FROM THE SOFTWARE; UNAUTHORIZED ACCESS TO OR ALTERATION OF YOUR TRANSMISSIONS OR DATA; STATEMENTS OR CONDUCT OF ANY THIRD PARTY ON THE SOFTWARE; TERMINATION OF YOUR ACCOUNT; OR ANY OTHER MATTER RELATING TO THE SOFTWARE. + +NOTWITHSTANDING ANYTHING TO THE CONTRARY CONTAINED HEREIN, TEALIUM’S LIABILITY TO YOU FOR ANY DAMAGES ARISING FROM OR RELATING TO THE SOFTWARE (FOR ANY CAUSE WHATSOEVER AND REGARDLESS OF THE FORM OF THE ACTION) WILL AT ALL TIMES BE LIMITED TO THE GREATER OR EITHER (1) THE AMOUNT YOU PAID TO TEALIUM IN THE SIX (6) MONTHS IMMEDIATELY PRECEDING THE INCIDENT GIVING RISE TO THE CLAIM OR (2) ONE HUNDRED FIFTY DOLLARS (USD 150.00). + +Cancellation and Termination +Tealium, in its sole discretion, may terminate your license, for any reason at any time. +You, in your sole discretion, may terminate this Agreement immediately upon written notice to Tealium. +Upon termination or expiration of this Agreement, You will immediately cease use of and destroy the original and all copies of the Software in Your possession or control. Upon Tealium's written request, You will confirm to Tealium in writing that You have complied with all provisions of this Agreement. +Either party may terminate this Agreement upon written notice to the other party, for any material breach by the other party, if such breach is not cured within thirty (30) days after the non-breaching party provides the allegedly breaching party with written notice of such breach. + +Miscellaneous +This Agreement will be governed by the laws of the State of California without giving effect to any conflicts of laws principles that may require the application of the law of a different jurisdiction. For any dispute or proceeding arising from or relating to this Agreement, You agree to submit to the jurisdiction of, and agree that venue is proper in, the state courts located in San Diego County, California, and in the federal courts located in the Southern District of California. The failure of Tealium to exercise or enforce any right or provision of this Agreement will not constitute a waiver of such right or provision. This Agreement constitutes the entire agreement between You and Tealium and governs Your use of the Service, superseding any prior agreements between You and Tealium (including, but not limited to, any prior versions of the Agreement). \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index c19a6e9..5d12e7e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,7 +1,5 @@ apply plugin: 'com.android.application' - apply plugin: 'kotlin-android' - apply plugin: 'kotlin-android-extensions' android { @@ -25,12 +23,15 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation project (path: ':appsflyer') + + implementation 'com.tealium:library:5.7.1' + releaseImplementation 'com.tealium.remotecommands:appsflyer:0.0.2' + debugImplementation project (path: ':appsflyer') + implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation 'androidx.appcompat:appcompat:1.0.2' implementation 'androidx.core:core-ktx:1.0.2' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' - implementation 'com.tealium:library:5.7.0' testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' diff --git a/app/src/main/java/com/tealium/example/TealiumHelper.kt b/app/src/main/java/com/tealium/example/TealiumHelper.kt index 3038a7e..75d67ab 100644 --- a/app/src/main/java/com/tealium/example/TealiumHelper.kt +++ b/app/src/main/java/com/tealium/example/TealiumHelper.kt @@ -5,6 +5,7 @@ import android.os.Build import android.webkit.WebView import com.tealium.library.Tealium import com.tealium.remotecommands.appsflyer.AppsFlyerRemoteCommand +import com.tealium.remotecommands.appsflyer.Config object TealiumHelper { @@ -22,7 +23,13 @@ object TealiumHelper { config.forceOverrideLogLevel = "dev" tealium = Tealium.createInstance(instanceName, config) - val appsFlyerRemoteCommand = AppsFlyerRemoteCommand(instanceName, application, appsFlyerDevKey = devKey) + val appsFlyerRemoteCommand = AppsFlyerRemoteCommand( + application, + instanceName, + devKey, + configSettings = mapOf(Config.DEBUG to (config.forceOverrideLogLevel == "dev")) + ) + tealium.addRemoteCommand(appsFlyerRemoteCommand) } @@ -33,5 +40,4 @@ object TealiumHelper { fun trackEvent(tealiumEvent: String, data: Map? = null) { Tealium.getInstance(instanceName)?.trackEvent(tealiumEvent, data) } - } \ No newline at end of file diff --git a/appsflyer/build.gradle b/appsflyer/build.gradle index 14f3b59..2376cd2 100644 --- a/appsflyer/build.gradle +++ b/appsflyer/build.gradle @@ -33,8 +33,8 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.0.2' implementation 'androidx.core:core-ktx:1.0.2' implementation "com.tealium:library:$tealium_version" - implementation 'com.appsflyer:af-android-sdk:5.0.0' - implementation 'com.android.installreferrer:installreferrer:1.1.1' + implementation 'com.appsflyer:af-android-sdk:5.2.0' + implementation 'com.android.installreferrer:installreferrer:1.1.2' testImplementation 'junit:junit:4.12' testImplementation "org.robolectric:robolectric:4.2" @@ -52,7 +52,7 @@ publishing { mavenJava(MavenPublication) { groupId 'com.tealium.remotecommands' artifactId 'appsflyer' - version '0.0.1' + version '0.0.2' artifact("$buildDir/outputs/aar/appsflyer-release.aar") } } @@ -60,7 +60,6 @@ publishing { maven { url "s3://maven.tealiumiq.com/android/releases/" credentials(AwsCredentials) { - // Dummy credentials provided in project's gradle.properties; these will be overridden by your global settings in ~/.gradle/gradle.properties accessKey AWS_ACCESS_KEY secretKey AWS_SECRET_KEY } diff --git a/appsflyer/src/main/java/com/tealium/remotecommands/appsflyer/AppsFlyerConstants.kt b/appsflyer/src/main/java/com/tealium/remotecommands/appsflyer/AppsFlyerConstants.kt index a392351..b55769a 100644 --- a/appsflyer/src/main/java/com/tealium/remotecommands/appsflyer/AppsFlyerConstants.kt +++ b/appsflyer/src/main/java/com/tealium/remotecommands/appsflyer/AppsFlyerConstants.kt @@ -86,4 +86,5 @@ object DeepLink { object Tracking { const val DISABLE_DEVICE_TRACKING = "disable_device_tracking" const val STOP_TRACKING = "stop_tracking" + const val GCD_IS_FIRST_LAUNCH = "is_first_launch" } diff --git a/appsflyer/src/main/java/com/tealium/remotecommands/appsflyer/AppsFlyerRemoteCommand.kt b/appsflyer/src/main/java/com/tealium/remotecommands/appsflyer/AppsFlyerRemoteCommand.kt index 1efe07f..6d98680 100644 --- a/appsflyer/src/main/java/com/tealium/remotecommands/appsflyer/AppsFlyerRemoteCommand.kt +++ b/appsflyer/src/main/java/com/tealium/remotecommands/appsflyer/AppsFlyerRemoteCommand.kt @@ -1,5 +1,6 @@ package com.tealium.remotecommands.appsflyer +import android.app.Activity import android.app.Application import android.util.Log import com.tealium.internal.tagbridge.RemoteCommand @@ -13,27 +14,28 @@ open class AppsFlyerRemoteCommand : RemoteCommand { private val TAG = this::class.java.simpleName - lateinit var tracker: AppsFlyerTrackable - private var application: Application? = null + var tracker: AppsFlyerTrackable + private var application: Application lateinit var instanceName: String @JvmOverloads constructor( + application: Application, instanceName: String, - application: Application? = null, + appsFlyerDevKey: String, + configSettings: Map? = null, commandId: String = DEFAULT_COMMAND_ID, description: String = DEFAULT_COMMAND_DESCRIPTION, - appsFlyerDevKey: String? = null, - configSettings: Map? = null + tracker: AppsFlyerTrackable = AppsFlyerTracker( + application, + instanceName, + appsFlyerDevKey, + configSettings + ) ) : super(commandId, description) { - application?.let { app -> - appsFlyerDevKey?.let { devKey -> - this.application = app - this.instanceName = instanceName - tracker = AppsFlyerTracker(app, instanceName, devKey, configSettings) - } - } + this.tracker = tracker + this.application = application } companion object { @@ -65,9 +67,6 @@ open class AppsFlyerRemoteCommand : RemoteCommand { Commands.INITIALIZE -> { initialize(payload) } - Commands.LAUNCH -> { - tracker.trackLaunch() - } Commands.TRACK_LOCATION -> { trackLocation(payload) } @@ -167,8 +166,9 @@ open class AppsFlyerRemoteCommand : RemoteCommand { devKey?.let { devKey -> configSettings?.let { tracker = AppsFlyerTracker(appContext, instanceName, devKey, it) + } ?: run { + tracker = AppsFlyerTracker(appContext, instanceName, devKey) } - tracker = AppsFlyerTracker(appContext, instanceName, devKey) } } ?: run { Log.e( diff --git a/appsflyer/src/main/java/com/tealium/remotecommands/appsflyer/AppsFlyerTrackable.kt b/appsflyer/src/main/java/com/tealium/remotecommands/appsflyer/AppsFlyerTrackable.kt index 3af6848..db35ec8 100644 --- a/appsflyer/src/main/java/com/tealium/remotecommands/appsflyer/AppsFlyerTrackable.kt +++ b/appsflyer/src/main/java/com/tealium/remotecommands/appsflyer/AppsFlyerTrackable.kt @@ -5,7 +5,6 @@ import android.app.Application interface AppsFlyerTrackable { fun initialize(application: Application, devKey: String, configSettings: Map? = null) - fun trackLaunch() fun trackLocation(latitude: Double, longitude: Double) fun setHost(host: String, hostPrefix: String? = "") fun trackEvent(eventType: String, eventParameters: Map? = null) diff --git a/appsflyer/src/main/java/com/tealium/remotecommands/appsflyer/AppsFlyerTracker.kt b/appsflyer/src/main/java/com/tealium/remotecommands/appsflyer/AppsFlyerTracker.kt index 8e7f1b1..907bfdc 100644 --- a/appsflyer/src/main/java/com/tealium/remotecommands/appsflyer/AppsFlyerTracker.kt +++ b/appsflyer/src/main/java/com/tealium/remotecommands/appsflyer/AppsFlyerTracker.kt @@ -13,8 +13,6 @@ class AppsFlyerTracker( configSettings: Map? = null ) : AppsFlyerTrackable { - private val TAG = this::class.java.simpleName - init { initialize(application, devKey, configSettings) } @@ -51,12 +49,8 @@ class AppsFlyerTracker( enableDebugLog(settings[Config.DEBUG] as Boolean) } } - AppsFlyerLib.getInstance().init(devKey, createConversionListener(), application) - AppsFlyerLib.getInstance().startTracking(application) - } - - override fun trackLaunch() { - AppsFlyerLib.getInstance().trackAppLaunch(application, devKey) + AppsFlyerLib.getInstance().init(devKey, createConversionListener(), application.applicationContext) + AppsFlyerLib.getInstance().startTracking(application.applicationContext) } override fun trackLocation(latitude: Double, longitude: Double) { @@ -113,12 +107,15 @@ class AppsFlyerTracker( AppsFlyerLib.getInstance().setDebugLog(shouldEnable) } - private fun createConversionListener(): AppsFlyerConversionListener { return object : AppsFlyerConversionListener { - override fun onConversionDataSuccess(conversionData: MutableMap?) { + override fun onConversionDataSuccess(conversionData: MutableMap) { val tealium: Tealium? = Tealium.getInstance(instanceName) - tealium?.trackEvent("conversion_data_received", conversionData) + + if (conversionData.containsKey(Tracking.GCD_IS_FIRST_LAUNCH) && + (conversionData[Tracking.GCD_IS_FIRST_LAUNCH] as Boolean)) { + tealium?.trackEvent("conversion_data_received", conversionData) + } } override fun onConversionDataFail(errorMessage: String) { diff --git a/appsflyer/src/test/java/com/tealium/remotecommands/appsflyer/AppsFlyerRemoteCommandTest.kt b/appsflyer/src/test/java/com/tealium/remotecommands/appsflyer/AppsFlyerRemoteCommandTest.kt index 77686e1..2037d82 100644 --- a/appsflyer/src/test/java/com/tealium/remotecommands/appsflyer/AppsFlyerRemoteCommandTest.kt +++ b/appsflyer/src/test/java/com/tealium/remotecommands/appsflyer/AppsFlyerRemoteCommandTest.kt @@ -1,7 +1,7 @@ package com.tealium.remotecommands.appsflyer +import android.app.Application import io.mockk.* -import io.mockk.impl.annotations.InjectMockKs import io.mockk.impl.annotations.MockK import org.json.JSONArray import org.json.JSONObject @@ -16,16 +16,22 @@ class AppsFlyerRemoteCommandTest { val COMMAND_NAME_KEY = "command_name" + @MockK + lateinit var mockApplication: Application + @MockK lateinit var mockTracker: AppsFlyerTrackable - @InjectMockKs - var appsFlyerRemoteCommand: AppsFlyerRemoteCommand = AppsFlyerRemoteCommand("test") + lateinit var appsFlyerRemoteCommand: AppsFlyerRemoteCommand @Before fun setUp() { MockKAnnotations.init(this, relaxUnitFun = true) - appsFlyerRemoteCommand.tracker = mockTracker + appsFlyerRemoteCommand = AppsFlyerRemoteCommand( + mockApplication, + "test", + "testKey", + tracker = mockTracker) } @Test @@ -40,22 +46,6 @@ class AppsFlyerRemoteCommandTest { Assert.assertEquals("add_to_cart", commands[2]) } - @Test - fun testTrackLaunch() { - val payload = JSONObject() - payload.put(COMMAND_NAME_KEY, Commands.LAUNCH) - - appsFlyerRemoteCommand.parseCommands(arrayOf(Commands.LAUNCH), payload) - - every { mockTracker.trackLaunch() } just Runs - - verify { - mockTracker.trackLaunch() - } - - confirmVerified(mockTracker) - } - @Test fun testInvokeTrackLocation() { val payload = JSONObject() diff --git a/appsflyer/src/test/java/com/tealium/remotecommands/appsflyer/StandardEventsTest.kt b/appsflyer/src/test/java/com/tealium/remotecommands/appsflyer/StandardEventsTest.kt index e0d05aa..1118378 100644 --- a/appsflyer/src/test/java/com/tealium/remotecommands/appsflyer/StandardEventsTest.kt +++ b/appsflyer/src/test/java/com/tealium/remotecommands/appsflyer/StandardEventsTest.kt @@ -1,9 +1,9 @@ package com.tealium.remotecommands.appsflyer +import android.app.Application import com.appsflyer.AFInAppEventParameterName import com.appsflyer.AFInAppEventType import io.mockk.* -import io.mockk.impl.annotations.InjectMockKs import io.mockk.impl.annotations.MockK import org.json.JSONObject import org.junit.Assert @@ -15,16 +15,24 @@ import org.robolectric.RobolectricTestRunner @RunWith(RobolectricTestRunner::class) class StandardEventsTest { + @MockK + lateinit var mockApplication: Application + @MockK lateinit var mockTracker: AppsFlyerTrackable - @InjectMockKs - var appsFlyerRemoteCommand: AppsFlyerRemoteCommand = AppsFlyerRemoteCommand("test") + + lateinit var appsFlyerRemoteCommand: AppsFlyerRemoteCommand @Before fun setUp() { MockKAnnotations.init(this, relaxUnitFun = true) - appsFlyerRemoteCommand.tracker = mockTracker + appsFlyerRemoteCommand = AppsFlyerRemoteCommand( + mockApplication, + "test", + "testKey", + tracker = mockTracker + ) } @Test diff --git a/build.gradle b/build.gradle index 0d52ece..447516c 100644 --- a/build.gradle +++ b/build.gradle @@ -27,15 +27,10 @@ allprojects { maven { url "http://maven.tealiumiq.com/android/releases/" - credentials(AwsCredentials) { - accessKey AWS_ACCESS_KEY - secretKey AWS_SECRET_KEY - } } - } } task clean(type: Delete) { delete rootProject.buildDir -} +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 81494c5..376270d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,7 +18,4 @@ android.useAndroidX=true # Automatically convert third-party libraries to use AndroidX android.enableJetifier=true # Kotlin code style for this project: "official" or "obsolete": -kotlin.code.style=official - -AWS_ACCESS_KEY="DUMMY-CREDENTIALS" -AWS_SECRET_KEY="DUMMY-CREDENTIALS" \ No newline at end of file +kotlin.code.style=official \ No newline at end of file