Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions android-java/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ After you have completed the [common prerequisites] you will need the following:
## Documentation

- [Install Guide](https://docs.ditto.live/sdk/latest/install-guides/java/android)
- [API Reference](https://software.ditto.live/android/Ditto/4.11.1/api-reference/)
- [API Reference](https://software.ditto.live/android/Ditto/5.0.0/api-reference/)
- [SDK Release Notes](https://docs.ditto.live/sdk/latest/release-notes/java)

[common prerequisites]: https://github.com/getditto/quickstart#common-prerequisites
Expand All @@ -23,8 +23,8 @@ After you have completed the [common prerequisites] you will need the following:
Assuming you have Android Studio and other prerequisites installed, you can
build and run the app by following these steps:

1. Create an application at <https://portal.ditto.live/>. Make note of the app ID and online playground token.
2. Copy the `.env.sample` file at the top level of the `quickstart` repo to `.env` and add your App ID, Online Playground Token, Auth URL, and Websocket URL.
1. Create an application at <https://portal.ditto.live/>. Make note of the database ID (used to be called app ID) and online playground token.
2. Copy the `.env.sample` file at the top level of the `quickstart` repo to `.env` and add your Database ID (used to be called AppId), Online Playground Token, and Auth URL.
Comment thread
biozal marked this conversation as resolved.
3. Launch Android Studio and open the `quickstart/android-java` directory.
4. In Android Studio, select a connected Android device, or create and launch an Android emulator and select it as the destination, then choose the **Run > Run 'app'** menu item.

Expand All @@ -36,8 +36,9 @@ Compatible with Android Automotive OS (AAOS)

## A Guided Tour of the Android App Source Code

The Android app is a simple to-do list app that demonstrates how to use the Ditto Android SDK to sync data with other devices.
It is implemented using Java and Android Views using an Activity and a programmatically implemented RecyclerView.
The Android app is a simple to-do list app that demonstrates how to use the Ditto Android SDK to sync data with other devices. It is implemented using Java and Android Views using an Activity and a programmatically implemented RecyclerView.

The Ditto v5 SDK ships as a Kotlin module (`com.ditto:ditto-kotlin-android`) and exposes some APIs as `suspend` functions. To keep the application code idiomatic Java, this project uses a small Kotlin bridge file, `DittoHelper.kt`, that wraps the suspending APIs with `runBlocking` and exposes `@JvmStatic` entry points. All application logic — `MainActivity`, `Task`, and `TaskAdapter` — remains in Java.

It is assumed that the reader is familiar with Android development and with Java/Activity/RecyclerView, but needs some guidance on how to use Ditto. The following is a summary of the key parts of integration with Ditto.

Expand All @@ -54,7 +55,7 @@ This line in `gradle/libs.versions.toml` specifies which version of the Ditto
SDK to use:

```kotlin
ditto = "4.11.1"
ditto = "5.0.0"
```

To use a newer version of the SDK, change the version number on this line.
50 changes: 17 additions & 33 deletions android-java/app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import com.android.build.api.variant.BuildConfigField
import java.io.FileInputStream
import java.io.FileNotFoundException
import java.util.Properties
import org.jetbrains.kotlin.gradle.dsl.JvmTarget

plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
}

fun loadEnvProperties(): Properties {
Expand All @@ -19,8 +18,7 @@ fun loadEnvProperties(): Properties {
val requiredEnvVars = listOf(
"DITTO_APP_ID",
"DITTO_PLAYGROUND_TOKEN",
"DITTO_AUTH_URL",
"DITTO_WEBSOCKET_URL"
"DITTO_AUTH_URL"
)

for (envVar in requiredEnvVars) {
Expand All @@ -33,27 +31,30 @@ fun loadEnvProperties(): Properties {
}

// Define BuildConfig.DITTO_APP_ID, BuildConfig.DITTO_PLAYGROUND_TOKEN,
// BuildConfig.DITTO_CUSTOM_AUTH_URL, BuildConfig.DITTO_WEBSOCKET_URL
// based on values in the .env file
// and BuildConfig.DITTO_AUTH_URL based on values in the .env file
//
// More information can be found here:
// https://docs.ditto.live/sdk/latest/install-guides/java/android#integrating-and-initializing
fun envValue(prop: Properties, key: String): String {
return prop[key]?.toString()?.trim('"') ?: ""
}

androidComponents {
onVariants {
val prop = loadEnvProperties()
it.buildConfigFields.put(
"DITTO_APP_ID",
BuildConfigField(
"String",
"\"${prop["DITTO_APP_ID"]}\"",
"\"${envValue(prop, "DITTO_APP_ID")}\"",
"Ditto application ID"
)
)
it.buildConfigFields.put(
"DITTO_PLAYGROUND_TOKEN",
BuildConfigField(
"String",
"\"${prop["DITTO_PLAYGROUND_TOKEN"]}\"",
"\"${envValue(prop, "DITTO_PLAYGROUND_TOKEN")}\"",
"Ditto online playground authentication token"
)
)
Expand All @@ -62,19 +63,10 @@ androidComponents {
"DITTO_AUTH_URL",
BuildConfigField(
"String",
"\"${prop["DITTO_AUTH_URL"]}\"",
"\"${envValue(prop, "DITTO_AUTH_URL")}\"",
"Ditto Auth URL"
)
)

it.buildConfigFields.put(
"DITTO_WEBSOCKET_URL",
BuildConfigField(
"String",
"\"${prop["DITTO_WEBSOCKET_URL"]}\"",
"Ditto Websocket URL"
)
)
}
}

Expand All @@ -86,7 +78,7 @@ android {
defaultConfig {
applicationId = "com.example.dittotasks"
minSdk = 24
targetSdk = 34
targetSdk = 35
versionCode = 1
versionName = "1.0"

Expand All @@ -109,12 +101,8 @@ android {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = "11"
}
buildFeatures {
buildConfig = true
compose = true
}
// This ensures Ditto can produce meaningful stack traces
packaging {
Expand All @@ -125,16 +113,16 @@ android {
}
}

kotlin {
compilerOptions {
jvmTarget.set(JvmTarget.JVM_11)
}
}

dependencies {

implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.activity.compose)
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.ui)
implementation(libs.androidx.ui.graphics)
implementation(libs.androidx.ui.tooling.preview)
implementation(libs.androidx.material3)
implementation(libs.ditto)
implementation(libs.androidx.recyclerview)
implementation(libs.material)
Expand All @@ -143,8 +131,4 @@ dependencies {
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
androidTestImplementation("androidx.test.espresso:espresso-contrib:3.6.1")
androidTestImplementation(platform(libs.androidx.compose.bom))
androidTestImplementation(libs.androidx.ui.test.junit4)
debugImplementation(libs.androidx.ui.tooling)
debugImplementation(libs.androidx.ui.test.manifest)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com.example.dittotasks

import com.ditto.kotlin.Ditto
import com.ditto.kotlin.DittoAuthenticationProvider
import com.ditto.kotlin.DittoConfig
import com.ditto.kotlin.DittoException
import com.ditto.kotlin.DittoFactory
import com.ditto.kotlin.DittoQueryResult
import com.ditto.kotlin.DittoStoreObserver
import com.ditto.kotlin.DittoSyncSubscription
import kotlinx.coroutines.runBlocking
import java.util.function.Consumer

/**
* Bridges Ditto v5 Kotlin SDK suspend functions for Java callers.
*/
object DittoHelper {

@JvmStatic
fun createDitto(appId: String, serverUrl: String): Ditto {
val config = DittoConfig(
databaseId = appId,
connect = DittoConfig.Connect.Server(serverUrl)
)
return DittoFactory.create(config)
}
Comment thread
biozal marked this conversation as resolved.

@JvmStatic
fun setupAuth(ditto: Ditto, token: String) {
ditto.auth?.let { auth ->
auth.expirationHandler = { dittoInstance, _ ->
dittoInstance.auth?.login(token, DittoAuthenticationProvider.development())
}
}
}

@JvmStatic
@Throws(DittoException::class)
fun execute(ditto: Ditto, query: String, args: Map<String, Any?>) {
runBlocking {
ditto.store.execute(query, args)
}
Comment thread
biozal marked this conversation as resolved.
}

@JvmStatic
fun registerSubscription(ditto: Ditto, query: String): DittoSyncSubscription {
return ditto.sync.registerSubscription(query)
}

@JvmStatic
fun registerObserver(
ditto: Ditto,
query: String,
callback: Consumer<DittoQueryResult>
): DittoStoreObserver {
return ditto.store.registerObserver(query) { result ->
callback.accept(result)
}
}

@JvmStatic
fun startSync(ditto: Ditto) {
ditto.sync.start()
}

@JvmStatic
fun stopSync(ditto: Ditto) {
ditto.sync.stop()
}

@JvmStatic
fun isSyncActive(ditto: Ditto): Boolean {
return ditto.sync.isActive
}
}
Loading
Loading