From 0f9efd45a06748d41dde4046023eeb2243204025 Mon Sep 17 00:00:00 2001
From: Felipe Contreras-Salinas <95327085+fcs-ts@users.noreply.github.com>
Date: Mon, 16 Sep 2024 10:11:12 -0300
Subject: [PATCH] feat: BannerView (#21)
---
.gitignore | 10 +-
.idea/.gitignore | 3 +
.idea/.name | 1 +
.idea/codeStyles/Project.xml | 123 ++++++++++++++++++
.idea/codeStyles/codeStyleConfig.xml | 5 +
.idea/compiler.xml | 6 +
.idea/deploymentTargetSelector.xml | 10 ++
.idea/gradle.xml | 20 +++
.idea/kotlinc.xml | 6 +
.idea/migrations.xml | 10 ++
.idea/misc.xml | 9 ++
.idea/vcs.xml | 6 +
README.md | 47 +++++++
TopsortAnalytics/build.gradle | 3 +
.../topsort/analytics/banners/BannerView.kt | 60 +++++++++
.../java/com/topsort/analytics/banners/run.kt | 18 ++-
.../analytics/model/auctions/Auction.kt | 20 ++-
.../model/auctions/AuctionResponse.kt | 17 ++-
.../service/TopsortAuctionsHttpService.kt | 6 +-
app/build.gradle | 5 +-
.../ExampleInstrumentedTest.kt | 9 +-
app/src/main/AndroidManifest.xml | 17 +--
.../JavaSampleActivity.java | 3 +-
.../{analytics => example}/SampleActivity.kt | 31 ++++-
.../{analytics => example}/TestApplication.kt | 5 +-
app/src/main/res/layout/sample_activity.xml | 28 ++++
.../{analytics => example}/ExampleUnitTest.kt | 2 +-
27 files changed, 434 insertions(+), 46 deletions(-)
create mode 100644 .idea/.gitignore
create mode 100644 .idea/.name
create mode 100644 .idea/codeStyles/Project.xml
create mode 100644 .idea/codeStyles/codeStyleConfig.xml
create mode 100644 .idea/compiler.xml
create mode 100644 .idea/deploymentTargetSelector.xml
create mode 100644 .idea/gradle.xml
create mode 100644 .idea/kotlinc.xml
create mode 100644 .idea/migrations.xml
create mode 100644 .idea/misc.xml
create mode 100644 .idea/vcs.xml
create mode 100644 TopsortAnalytics/src/main/java/com/topsort/analytics/banners/BannerView.kt
rename app/src/androidTest/java/com/topsort/{analytics => example}/ExampleInstrumentedTest.kt (85%)
rename app/src/main/java/com/topsort/{analytics => example}/JavaSampleActivity.java (98%)
rename app/src/main/java/com/topsort/{analytics => example}/SampleActivity.kt (72%)
rename app/src/main/java/com/topsort/{analytics => example}/TestApplication.kt (73%)
create mode 100644 app/src/main/res/layout/sample_activity.xml
rename app/src/test/java/com/topsort/{analytics => example}/ExampleUnitTest.kt (91%)
diff --git a/.gitignore b/.gitignore
index 8fbbbc4..d676f57 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,13 +3,9 @@
.cxx
.externalNativeBuild
.gradle
-.idea
-/.idea/assetWizardSettings.xml
-/.idea/caches
-/.idea/libraries
-/.idea/modules.xml
-/.idea/navEditor.xml
-/.idea/workspace.xml
+.idea/caches
+.idea/workspace.xml
+.idea/shelf
/TopsortAnalytics/build
/build
/captures
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 0000000..40d39ba
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+TopsortAnalytics
\ No newline at end of file
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..7643783
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ xmlns:android
+
+ ^$
+
+
+
+
+
+
+
+
+ xmlns:.*
+
+ ^$
+
+
+ BY_NAME
+
+
+
+
+
+
+ .*:id
+
+ http://schemas.android.com/apk/res/android
+
+
+
+
+
+
+
+
+ .*:name
+
+ http://schemas.android.com/apk/res/android
+
+
+
+
+
+
+
+
+ name
+
+ ^$
+
+
+
+
+
+
+
+
+ style
+
+ ^$
+
+
+
+
+
+
+
+
+ .*
+
+ ^$
+
+
+ BY_NAME
+
+
+
+
+
+
+ .*
+
+ http://schemas.android.com/apk/res/android
+
+
+ ANDROID_ATTRIBUTE_ORDER
+
+
+
+
+
+
+ .*
+
+ .*
+
+
+ BY_NAME
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..79ee123
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..b589d56
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml
new file mode 100644
index 0000000..b268ef3
--- /dev/null
+++ b/.idea/deploymentTargetSelector.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
new file mode 100644
index 0000000..3f45c18
--- /dev/null
+++ b/.idea/gradle.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml
new file mode 100644
index 0000000..fe63bb6
--- /dev/null
+++ b/.idea/kotlinc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/migrations.xml b/.idea/migrations.xml
new file mode 100644
index 0000000..f8051a6
--- /dev/null
+++ b/.idea/migrations.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..8978d23
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index 078b3b1..d95de40 100644
--- a/README.md
+++ b/README.md
@@ -238,4 +238,51 @@ private void reportImpressionWithResolvedBidId() {
}
```
+#### Banners on Android
+
+#### Kotlin
+You should first add the `BannerView` into your activity `xml`. You can do so with
+Android Studio's visual editor, but the end file should like like the following
+```xml
+
+
+
+
+```
+
+Then, you have to call the `BannerView.setup()` function with you auction parameters.
+Notice that since this makes network calls, we need to `launch` it in a co-routine.
+```kotlin
+class SampleActivity : AppCompatActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.sample_activity)
+
+ this.lifecycleScope.launch {
+ val bannerView = findViewById(R.id.bannerView)
+ val bannerConfig =
+ BannerConfig.CategorySingle(slotId = "slot", category = "category")
+ bannerView.setup(
+ bannerConfig,
+ "sample_activity",
+ null,
+ { id, entityType -> onBannerClick(id, entityType) })
+ }
+ }
+}
+```
+
+
[1]: ./LICENSE
diff --git a/TopsortAnalytics/build.gradle b/TopsortAnalytics/build.gradle
index c87c03c..00c3221 100644
--- a/TopsortAnalytics/build.gradle
+++ b/TopsortAnalytics/build.gradle
@@ -52,6 +52,9 @@ dependencies {
//JodaTime
implementation group: 'joda-time', name: 'joda-time', version: '2.12.5'
+ // Image Loading for Banners
+ implementation 'io.coil-kt:coil:2.7.0'
+
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.json:json:20200518'
testImplementation 'org.assertj:assertj-core:3.26.0'
diff --git a/TopsortAnalytics/src/main/java/com/topsort/analytics/banners/BannerView.kt b/TopsortAnalytics/src/main/java/com/topsort/analytics/banners/BannerView.kt
new file mode 100644
index 0000000..1ff9107
--- /dev/null
+++ b/TopsortAnalytics/src/main/java/com/topsort/analytics/banners/BannerView.kt
@@ -0,0 +1,60 @@
+package com.topsort.analytics.banners
+
+import android.content.Context
+import android.util.AttributeSet
+import android.widget.ImageView
+import coil.load
+import com.topsort.analytics.Analytics
+import com.topsort.analytics.model.Placement
+import com.topsort.analytics.model.auctions.EntityType
+
+
+/**
+ * View for displaying banners powered by auctions.
+ *
+ * @constructor The constructor is meant to be called automatically from XML inflation.
+ * You can add this view to your layout by using a `com.topsort.analytics.banners.BannerView` element.
+ *
+ * @param context
+ * @param attrs AttributeSet for the view. Since this view inherits from `ImageView`
+ * you can set attributes as you would with a regular `ImageView`.
+ */
+class BannerView(
+ context: Context,
+ attrs: AttributeSet
+) : ImageView(context, attrs) {
+
+ /**
+ * Setup the banner in the view by running an auction in the background.
+ *
+ * @param config a BannerConfig object that specifies the parameters for the auction
+ * @param path identifier for the activity where the banner is displayed. It's recommended to be the deeplink for the view.
+ * @param location optional name for the location within the view where the banner is displayed.
+ * @param onClick callback for when the banner is clicked. Usually this should navigate to an activity related to the banner (e.g. the product page for the product shown in the banner).
+ * @receiver
+ */
+ suspend fun setup(
+ config: BannerConfig,
+ path: String,
+ location: String?,
+ onClick: (String, EntityType) -> Unit
+ ) {
+ val result = runBannerAuction(config)
+ if (result != null) {
+ this.load(result.url)
+ this.viewTreeObserver.addOnGlobalLayoutListener {
+ Analytics.reportImpressionPromoted(
+ resolvedBidId = result.resolvedBidId,
+ placement = Placement(path = path, location = location)
+ )
+ }
+ this.setOnClickListener {
+ Analytics.reportClickPromoted(
+ resolvedBidId = result.resolvedBidId,
+ placement = Placement(path = path, location = location)
+ )
+ onClick(result.id, result.type)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/TopsortAnalytics/src/main/java/com/topsort/analytics/banners/run.kt b/TopsortAnalytics/src/main/java/com/topsort/analytics/banners/run.kt
index fa0fc06..c40135f 100644
--- a/TopsortAnalytics/src/main/java/com/topsort/analytics/banners/run.kt
+++ b/TopsortAnalytics/src/main/java/com/topsort/analytics/banners/run.kt
@@ -2,7 +2,11 @@ package com.topsort.analytics.banners
import com.topsort.analytics.model.auctions.Auction
import com.topsort.analytics.model.auctions.AuctionRequest
+import com.topsort.analytics.model.auctions.AuctionResponse
import com.topsort.analytics.service.TopsortAuctionsHttpService
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
/**
* Run a banner auction with a single slot
@@ -10,16 +14,20 @@ import com.topsort.analytics.service.TopsortAuctionsHttpService
* @param config the banner configuration that specifies which kind of banner auction to run
* @return A BannerResponse if the auction successfully returned a winner or null if not.
*/
-fun runBannerAuction(config: BannerConfig): BannerResponse? {
+suspend fun runBannerAuction(config: BannerConfig): BannerResponse? {
val auction = buildBannerAuction(config)
val request = AuctionRequest(listOf(auction))
- val response = TopsortAuctionsHttpService.runAuctions(request)
+ var response: AuctionResponse? = null;
+ val auctionJob = CoroutineScope(Dispatchers.IO).launch {
+ response = TopsortAuctionsHttpService.runAuctions(request)
+ }
+ auctionJob.join()
if ((response?.results?.isNotEmpty() == true)) {
- if (response.results[0].winners.isNotEmpty()) {
- val winner = response.results[0].winners[0]
+ if (response!!.results[0].winners.isNotEmpty()) {
+ val winner = response!!.results[0].winners[0]
return BannerResponse(
id = winner.id,
- url = winner.asset!!.url,
+ url = winner.asset!![0].url,
type = winner.type,
resolvedBidId = winner.resolvedBidId
)
diff --git a/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/Auction.kt b/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/Auction.kt
index b131806..7154286 100644
--- a/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/Auction.kt
+++ b/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/Auction.kt
@@ -23,7 +23,7 @@ data class Auction private constructor(
put("products", JSONObject.wrap(products))
}
if (category != null) {
- put("category", JSONObject.wrap(category))
+ put("category", category.toJsonObject())
}
if (searchQuery != null) {
put("searchQuery", searchQuery)
@@ -214,7 +214,23 @@ data class Auction private constructor(
val id: String? = null,
val ids: List? = null,
val disjunctions: List>? = null,
- )
+ ) {
+ fun toJsonObject(): JSONObject {
+ val builder = JSONObject()
+ with(builder) {
+ if (id != null) {
+ put("id", id)
+ }
+ if (ids != null) {
+ put("ids", JSONObject.wrap(ids))
+ }
+ if (disjunctions != null) {
+ put("disjunctions", JSONObject.wrap(disjunctions))
+ }
+ }
+ return builder
+ }
+ }
data class GeoTargeting(
val location: String,
diff --git a/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/AuctionResponse.kt b/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/AuctionResponse.kt
index cdc3c9e..0097a05 100644
--- a/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/AuctionResponse.kt
+++ b/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/AuctionResponse.kt
@@ -44,26 +44,33 @@ data class AuctionResponse private constructor(
val type: EntityType,
val id: String,
val resolvedBidId: String,
- val asset: Asset? = null,
+ val asset: List? = null,
) {
companion object {
fun fromJsonObject(json: JSONObject): AuctionWinnerItem {
+ val assetArray = json.optJSONArray("asset")
+ var assets: List? = null
+ if (assetArray != null) {
+ assets = (0 until assetArray.length()).map {
+ Asset.fromJsonObject(assetArray.getJSONObject(it))
+ }
+ }
return AuctionWinnerItem(
rank = json.getInt("rank"),
type = EntityType.fromValue(json.getString("type")),
id = json.getString("id"),
resolvedBidId = json.getString("resolvedBidId"),
- asset = Asset.fromJsonObject(json),
+ asset = assets,
)
}
}
}
+
data class Asset(val url: String) {
companion object {
- fun fromJsonObject(json: JSONObject): Asset? {
- val asset = json.optJSONObject("asset") ?: return null
- val url = asset.getString("url")
+ fun fromJsonObject(json: JSONObject): Asset {
+ val url = json.getString("url")
return Asset(url = url)
}
}
diff --git a/TopsortAnalytics/src/main/java/com/topsort/analytics/service/TopsortAuctionsHttpService.kt b/TopsortAnalytics/src/main/java/com/topsort/analytics/service/TopsortAuctionsHttpService.kt
index ea81b45..ce98f7a 100644
--- a/TopsortAnalytics/src/main/java/com/topsort/analytics/service/TopsortAuctionsHttpService.kt
+++ b/TopsortAnalytics/src/main/java/com/topsort/analytics/service/TopsortAuctionsHttpService.kt
@@ -1,5 +1,6 @@
package com.topsort.analytics.service
+import android.util.Log
import com.topsort.analytics.Cache
import com.topsort.analytics.core.HttpClient
import com.topsort.analytics.core.HttpResponse
@@ -17,12 +18,15 @@ internal object TopsortAuctionsHttpService {
val response = executeRunAuctions(auctionRequest)
if (response.isSuccessful()) {
return AuctionResponse.fromJson(response.body)
+ } else {
+ Log.w("TopsortAuctionsHttpService", "Auction message: " + response.message)
+ Log.w("TopsortAuctionsHttpService", "Auction response: " + response.body.toString())
}
return null
}
private fun executeRunAuctions(auctionRequest: AuctionRequest): HttpResponse {
- if(!this::httpClient.isInitialized){
+ if (!this::httpClient.isInitialized) {
httpClient = HttpClient("${baseApiUrl}${AUCTION_ENDPOINT}")
}
val json = auctionRequest.toJsonObject().toString()
diff --git a/app/build.gradle b/app/build.gradle
index 63dd637..938e1b9 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -9,11 +9,11 @@ plugins {
def properties = { k -> "\"${project.properties.get(k)}\"" }
android {
- namespace 'com.topsort.analytics'
+ namespace 'com.topsort.example'
compileSdk 34
defaultConfig {
- applicationId "com.topsort.analytics"
+ applicationId "com.topsort.example"
minSdk 24
targetSdk 34
versionCode 1
@@ -54,6 +54,7 @@ tasks.withType(Detekt).configureEach {
dependencies {
implementation 'androidx.core:core-ktx:1.13.1'
+ implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.8.4'
implementation 'com.google.android.material:material:1.12.0'
implementation project(path: ':TopsortAnalytics')
diff --git a/app/src/androidTest/java/com/topsort/analytics/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/topsort/example/ExampleInstrumentedTest.kt
similarity index 85%
rename from app/src/androidTest/java/com/topsort/analytics/ExampleInstrumentedTest.kt
rename to app/src/androidTest/java/com/topsort/example/ExampleInstrumentedTest.kt
index 9329903..8b087b7 100644
--- a/app/src/androidTest/java/com/topsort/analytics/ExampleInstrumentedTest.kt
+++ b/app/src/androidTest/java/com/topsort/example/ExampleInstrumentedTest.kt
@@ -1,11 +1,10 @@
-package com.topsort.analytics
+package com.topsort.example
-import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
-
+import androidx.test.platform.app.InstrumentationRegistry
+import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.Assert.assertEquals
/**
* Instrumented test, which will execute on an Android device.
@@ -18,6 +17,6 @@ class ExampleInstrumentedTest {
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
- assertEquals("com.topsort.analytics", appContext.packageName)
+ assertEquals("com.topsort.example", appContext.packageName)
}
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index e13d4bf..cfd043e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -3,6 +3,7 @@
xmlns:tools="http://schemas.android.com/tools">
-
-
-
-
-
-
-
-
-
+ tools:targetApi="34">
-
+
diff --git a/app/src/main/java/com/topsort/analytics/JavaSampleActivity.java b/app/src/main/java/com/topsort/example/JavaSampleActivity.java
similarity index 98%
rename from app/src/main/java/com/topsort/analytics/JavaSampleActivity.java
rename to app/src/main/java/com/topsort/example/JavaSampleActivity.java
index 986cb4b..4e30265 100644
--- a/app/src/main/java/com/topsort/analytics/JavaSampleActivity.java
+++ b/app/src/main/java/com/topsort/example/JavaSampleActivity.java
@@ -1,10 +1,11 @@
-package com.topsort.analytics;
+package com.topsort.example;
import android.os.Bundle;
import androidx.activity.ComponentActivity;
import androidx.annotation.Nullable;
+import com.topsort.analytics.Analytics;
import com.topsort.analytics.model.Entity;
import com.topsort.analytics.model.EntityType;
import com.topsort.analytics.model.Placement;
diff --git a/app/src/main/java/com/topsort/analytics/SampleActivity.kt b/app/src/main/java/com/topsort/example/SampleActivity.kt
similarity index 72%
rename from app/src/main/java/com/topsort/analytics/SampleActivity.kt
rename to app/src/main/java/com/topsort/example/SampleActivity.kt
index f3f870d..a090c40 100644
--- a/app/src/main/java/com/topsort/analytics/SampleActivity.kt
+++ b/app/src/main/java/com/topsort/example/SampleActivity.kt
@@ -1,16 +1,35 @@
-package com.topsort.analytics
+package com.topsort.example
-import android.app.Activity
import android.os.Bundle
+import android.util.Log
+import androidx.appcompat.app.AppCompatActivity
+import androidx.lifecycle.lifecycleScope
+import com.topsort.analytics.Analytics
+import com.topsort.analytics.banners.BannerConfig
+import com.topsort.analytics.banners.BannerView
import com.topsort.analytics.model.Entity
import com.topsort.analytics.model.EntityType
import com.topsort.analytics.model.Placement
import com.topsort.analytics.model.PurchasedItem
+import kotlinx.coroutines.launch
+import com.topsort.analytics.model.auctions.EntityType as BannerEntityType
-class SampleActivity : Activity() {
+class SampleActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
+ setContentView(R.layout.sample_activity)
+
+ this.lifecycleScope.launch {
+ val bannerView = findViewById(R.id.bannerView)
+ val bannerConfig =
+ BannerConfig.CategorySingle(slotId = "slot", category = "category")
+ bannerView.setup(
+ bannerConfig,
+ "sample_activity",
+ null,
+ { id, entityType -> onBannerClick(id, entityType) })
+ }
reportPurchaseWithResolvedBidId()
reportClickWithResolvedBidId()
@@ -21,6 +40,7 @@ class SampleActivity : Activity() {
reportImpression()
}
+
private fun reportPurchaseWithResolvedBidId() {
val item = PurchasedItem(
resolvedBidId = "WyJiX01mazE1IiwiMTJhNTU4MjgtOGVhZC00Mjk5LTgzMjctY2ViYjAwMmEwZmE4IiwibGlzdGluZ3MiLCJkZWZhdWx0IiwiIl0=",
@@ -99,3 +119,8 @@ class SampleActivity : Activity() {
)
}
}
+
+fun onBannerClick(id: String, entityType: BannerEntityType) {
+ Log.i("BannerClick", "Clicked banner for $entityType with id $id")
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/topsort/analytics/TestApplication.kt b/app/src/main/java/com/topsort/example/TestApplication.kt
similarity index 73%
rename from app/src/main/java/com/topsort/analytics/TestApplication.kt
rename to app/src/main/java/com/topsort/example/TestApplication.kt
index 9b9f643..995cc31 100644
--- a/app/src/main/java/com/topsort/analytics/TestApplication.kt
+++ b/app/src/main/java/com/topsort/example/TestApplication.kt
@@ -1,6 +1,8 @@
-package com.topsort.analytics
+package com.topsort.example
import android.app.Application
+import com.topsort.analytics.Analytics
+import com.topsort.analytics.banners.BannerConfig
class TestApplication : Application() {
@@ -14,5 +16,6 @@ class TestApplication : Application() {
opaqueUserId = sessionId,
token = BuildConfig.TOKEN
)
+
}
}
diff --git a/app/src/main/res/layout/sample_activity.xml b/app/src/main/res/layout/sample_activity.xml
new file mode 100644
index 0000000..9302dac
--- /dev/null
+++ b/app/src/main/res/layout/sample_activity.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/test/java/com/topsort/analytics/ExampleUnitTest.kt b/app/src/test/java/com/topsort/example/ExampleUnitTest.kt
similarity index 91%
rename from app/src/test/java/com/topsort/analytics/ExampleUnitTest.kt
rename to app/src/test/java/com/topsort/example/ExampleUnitTest.kt
index ccf0b36..f7921fa 100644
--- a/app/src/test/java/com/topsort/analytics/ExampleUnitTest.kt
+++ b/app/src/test/java/com/topsort/example/ExampleUnitTest.kt
@@ -1,4 +1,4 @@
-package com.topsort.analytics
+package com.topsort.example
import org.junit.Assert.assertEquals
import org.junit.Test