Skip to content

Commit 00e8c9a

Browse files
committed
Recombee Kotlin SDK
1 parent ed9cb15 commit 00e8c9a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+3824
-0
lines changed

.gitignore

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
.gradle
2+
build/
3+
!gradle/wrapper/gradle-wrapper.jar
4+
!**/src/main/**/build/
5+
!**/src/test/**/build/
6+
7+
### IntelliJ IDEA ###
8+
.idea/modules.xml
9+
.idea/jarRepositories.xml
10+
.idea/compiler.xml
11+
.idea/libraries/
12+
*.iws
13+
*.iml
14+
*.ipr
15+
out/
16+
!**/src/main/**/out/
17+
!**/src/test/**/out/
18+
19+
### Eclipse ###
20+
.apt_generated
21+
.classpath
22+
.factorypath
23+
.project
24+
.settings
25+
.springBeans
26+
.sts4-cache
27+
bin/
28+
!**/src/main/**/bin/
29+
!**/src/test/**/bin/
30+
31+
### NetBeans ###
32+
/nbproject/private/
33+
/nbbuild/
34+
/dist/
35+
/nbdist/
36+
/.nb-gradle/
37+
38+
### VS Code ###
39+
.vscode/
40+
41+
### Mac OS ###
42+
.DS_Store

README.md

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
# Recombee API Client
2+
3+
A Kotlin client (SDK) for easy use of the [Recombee](https://www.recombee.com/) recommendation API in Android applications.
4+
5+
If you don't have an account at Recombee yet, you can create a free account [here](https://www.recombee.com/).
6+
7+
Documentation of the API can be found at [docs.recombee.com](https://docs.recombee.com/).
8+
9+
## Installation
10+
11+
The client will available in the Maven Central Repository in the upcoming days.
12+
13+
## How to use
14+
15+
This library allows you to request recommendations and send interactions between users and items (views, bookmarks, purchases ...) to Recombee. It uses the **public token** for authentication.
16+
17+
It is intentionally not possible to change the item catalog (properties of items) with the public token, so you should use one of the following ways to send it to Recombee:
18+
19+
- Use one of the server-side SDKs (Node.js, PHP, Java...). The synchronization can done for example by a peridodically run script. See [this section](https://docs.recombee.com/gettingstarted.html#managing-item-catalog) for more details.
20+
- Set a catalog feed at [Recombee web admin](https://admin.recombee.com/).
21+
22+
### Sending interactions
23+
24+
```kotlin
25+
import com.recombee.apiclientkotlin.RecombeeClient
26+
import com.recombee.apiclientkotlin.util.Region
27+
import com.recombee.apiclientkotlin.requests.*
28+
29+
30+
// Initialize client with name of your database and PUBLIC token
31+
val client = RecombeeClient(
32+
databaseId = "id-of-your-db",
33+
publicToken = "...db-public-token...",
34+
region = Region.UsWest
35+
)
36+
37+
// Interactions take the ID of the user and the ID of the item
38+
client.send(AddBookmark("user-13434", "item-256"))
39+
client.send(AddCartAddition("user-4395", "item-129"))
40+
client.send(AddDetailView("user-9318", "item-108"))
41+
client.send(AddPurchase("user-7499", "item-750"))
42+
client.send(AddRating("user-3967", "item-365", 0.5))
43+
client.send(SetViewPortion("user-4289", "item-487", 0.3))
44+
```
45+
46+
### Requesting recommendations
47+
48+
You can [recommend items to user](https://docs.recombee.com/api.html#recommend-items-to-user), [recommend items to item](https://docs.recombee.com/api.html#recommend-items-to-item) or even [recommend Item Segments](https://docs.recombee.com/api#recommend-item-segments-to-user) such as categories, genres or artists.
49+
50+
It is possible to use callbacks (`send` method) or coroutines (`sendAsync` method).
51+
52+
#### Callbacks
53+
54+
There are two callbacks (both are optional):
55+
- `onResponse`: Callback function invoked in case of successful response.
56+
57+
- `onFailure`: Callback function invoked with an *ApiException* in case of a failure.
58+
59+
```kotlin
60+
val request = RecommendItemsToUser(
61+
userId = "user-x",
62+
count = 10,
63+
scenario = "homepage-for-you",
64+
returnProperties = true
65+
)
66+
67+
client.send(request,
68+
{ recommendationResponse -> // response of type RecommendationResponse
69+
for (recommendedItem in recommendationResponse.recomms) {
70+
println("ID: ${recommendedItem.id} Values: ${recommendedItem.getValues()}")
71+
}
72+
},
73+
{ exception ->
74+
println("Exception: $exception")
75+
// use fallback ...
76+
}
77+
)
78+
```
79+
80+
81+
#### Coroutines
82+
83+
```kotlin
84+
// Assuming this is inside a CoroutineScope
85+
86+
val request = RecommendItemsToUser(
87+
userId = "user-x",
88+
count = 10,
89+
scenario = "homepage-for-you",
90+
returnProperties = true
91+
)
92+
93+
val result = client.sendAsync(request)
94+
95+
result.onSuccess { recommendationResponse ->
96+
for (recommendedItem in recommendationResponse.recomms) {
97+
println("ID: ${recommendedItem.id} Values: ${recommendedItem.getValues()}")
98+
}
99+
}.onFailure { exception ->
100+
println("Exception: $exception")
101+
// use fallback ...
102+
}
103+
104+
```
105+
106+
### Personalized search
107+
108+
[Personalized full-text search](https://docs.recombee.com/api.html#search-items) is requested in the same way as recommendations.
109+
110+
#### Callbacks
111+
112+
```kotlin
113+
val request = SearchItems(
114+
userId = "user-x",
115+
searchQuery = "..user's search query",
116+
count = 10,
117+
scenario = "search",
118+
returnProperties = true
119+
)
120+
121+
client.send(request,
122+
{ searchResponse -> // response of type SearchResponse
123+
for (recommendedItem in searchResponse.recomms) {
124+
println("ID: ${recommendedItem.id} Values: ${recommendedItem.getValues()}")
125+
}
126+
},
127+
{ exception ->
128+
println("Exception: $exception")
129+
// use fallback ...
130+
}
131+
)
132+
```
133+
134+
135+
#### Coroutines
136+
137+
```kotlin
138+
// Assuming this is inside a CoroutineScope
139+
140+
val request = SearchItems(
141+
userId = "user-x",
142+
searchQuery = "..user's search query",
143+
count = 10,
144+
scenario = "search",
145+
returnProperties = true
146+
)
147+
148+
val result = client.sendAsync(request)
149+
150+
result.onSuccess { searchResponse ->
151+
for (recommendedItem in searchResponse.recomms) {
152+
println("ID: ${recommendedItem.id} Values: ${recommendedItem.getValues()}")
153+
}
154+
}.onFailure { exception ->
155+
println("Exception: $exception")
156+
// use fallback ...
157+
}
158+
```
159+
160+
### Recommend Next Items
161+
162+
Recombee can return items that shall be shown to a user as next recommendations when the user e.g. scrolls the page down (infinite scroll) or goes to the next page. See [Recommend next items](https://docs.recombee.com/api.html#recommend-next-items) for more info.
163+
164+
```kotlin
165+
client.sendAsync(RecommendItemsToUser("user-1", 5))
166+
.onSuccess { firstResponse ->
167+
168+
client.sendAsync(RecommendNextItems(firstResponse.recommId, 5))
169+
.onSuccess { secondResponse ->
170+
// Show next recommendations
171+
}
172+
}
173+
```
174+
175+
### Optional parameters
176+
177+
Recommendation requests accept various optional parameters (see [the docs](https://docs.recombee.com/api.html#recommendations)). Following example shows some of them:
178+
179+
```kotlin
180+
val request = RecommendItemsToUser(
181+
userId = "user-13434",
182+
count = 5,
183+
scenario = "homepage-for-you", // Label particular usage
184+
returnProperties = true, // Return properties of the recommended items
185+
includedProperties = listOf("title", "img_url", "url", "price"), // Properties to be included in the response
186+
filter = "'title' != null AND 'availability' == \"in stock\"" // Filter condition
187+
)
188+
```
189+
190+
## Exception handling
191+
192+
Following types of exceptions can be produced:
193+
- *ResponseException*: Recombee API returned an error code (e.g. due to passing an invalid value to a parameter)
194+
- *ApiIOException*: Request did not succeed
195+
- In case of an timeout a subtype *ApiTimeoutException* is produced
196+
197+
*ApiException* is the base class of both *ResponseException* and *ApiIOException*.

build.gradle.kts

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import org.gradle.api.publish.maven.MavenPublication
2+
import org.gradle.kotlin.dsl.*
3+
4+
buildscript {
5+
repositories {
6+
mavenCentral()
7+
}
8+
dependencies {
9+
classpath("io.codearte.gradle.nexus:gradle-nexus-staging-plugin:0.22.0")
10+
}
11+
}
12+
13+
plugins {
14+
kotlin("jvm") version "1.9.21"
15+
`maven-publish`
16+
signing
17+
id("io.codearte.nexus-staging") version "0.22.0"
18+
}
19+
20+
group = "com.recombee"
21+
version = "4.1.0"
22+
23+
repositories {
24+
mavenCentral()
25+
google()
26+
}
27+
28+
dependencies {
29+
testImplementation("org.jetbrains.kotlin:kotlin-test")
30+
testImplementation("org.junit.jupiter:junit-jupiter:5.10.1")
31+
testImplementation("org.mockito:mockito-core:5.8.0")
32+
33+
implementation("com.squareup.okhttp3:okhttp:4.12.0")
34+
implementation("com.google.code.gson:gson:2.10.1")
35+
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0")
36+
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0")
37+
}
38+
39+
tasks.test {
40+
useJUnitPlatform()
41+
}
42+
43+
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
44+
kotlinOptions {
45+
jvmTarget = "1.8"
46+
freeCompilerArgs = listOf("-Xjvm-default=all")
47+
}
48+
}
49+
50+
tasks.withType<JavaCompile> {
51+
sourceCompatibility = JavaVersion.VERSION_1_8.toString()
52+
targetCompatibility = JavaVersion.VERSION_1_8.toString()
53+
}
54+
55+
kotlin {
56+
explicitApi()
57+
}
58+
59+
// Retrieve credentials and other properties
60+
val ossrhUsername: String by project
61+
val ossrhPassword: String by project
62+
63+
// Nexus Staging Plugin Configuration
64+
configure<io.codearte.gradle.nexus.NexusStagingExtension> {
65+
packageGroup = "com.recombee"
66+
username = ossrhUsername
67+
password = ossrhPassword
68+
}
69+
70+
publishing {
71+
publications {
72+
create<MavenPublication>("mavenKotlin") {
73+
from(components["kotlin"])
74+
75+
pom {
76+
name.set("Recombee API Client in Kotlin")
77+
description.set("A client library for easy use of the Recombee recommendation API in Android applications")
78+
url.set("https://recombee.com")
79+
licenses {
80+
license {
81+
name.set("MIT License")
82+
url.set("https://opensource.org/licenses/MIT")
83+
}
84+
}
85+
developers {
86+
developer {
87+
id.set("ondra_fiedler")
88+
name.set("Ondrej Fiedler")
89+
email.set("ondrej.fiedler@recombee.com")
90+
}
91+
}
92+
scm {
93+
connection.set("scm:git:git@github.com:Recombee/kotlin-api-client.git")
94+
developerConnection.set("scm:git:git@github.com:Recombee/kotlin-api-client.git")
95+
url.set("https://github.com/Recombee/kotlin-api-client")
96+
}
97+
}
98+
}
99+
}
100+
101+
repositories {
102+
maven {
103+
val releasesRepoUrl = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/"
104+
url = uri(releasesRepoUrl)
105+
credentials {
106+
username = ossrhUsername
107+
password = ossrhPassword
108+
}
109+
}
110+
}
111+
}

gradle.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
kotlin.code.style=official

gradle/wrapper/gradle-wrapper.jar

62.2 KB
Binary file not shown.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
distributionBase=GRADLE_USER_HOME
2+
distributionPath=wrapper/dists
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
4+
networkTimeout=10000
5+
validateDistributionUrl=true
6+
zipStoreBase=GRADLE_USER_HOME
7+
zipStorePath=wrapper/dists

0 commit comments

Comments
 (0)