Rio Android SDK helps Android applications connect to Rio Cloud services. This document explains how to integrate the SDK and use its core features.
Use this section if you want to get up and running quickly.
dependencies {
implementation 'com.github.rettersoft:rio-android-sdk:{latest-version}'
}import android.app.Application
import com.rettermobile.rio.Rio
import com.rettermobile.rio.service.RioNetworkConfig
import com.rettermobile.rio.util.RioRegion
class App : Application() {
lateinit var rio: Rio
override fun onCreate() {
super.onCreate()
rio = Rio(
applicationContext = applicationContext,
projectId = "<YOUR_PROJECT_ID>",
culture = "en-us",
config = RioNetworkConfig.build {
region = RioRegion.EU_WEST_1
sslPinningEnabled = true
}
)
}
}rio.authenticateWithCustomToken("<CUSTOM_TOKEN>") { isSuccess, throwable ->
if (!isSuccess) return@authenticateWithCustomToken
rio.makeStaticCall<MyResponse>(
options = RioCloudObjectOptions(
classId = "<CLASS_ID>",
method = "<METHOD_NAME>",
body = MyRequest()
),
onSuccess = { response ->
val data = response.body
},
onError = { error ->
// handle error
}
)
}- Android
minSdk 23+ - Kotlin-based Android project
- A valid Rio
projectIdfrom Rio Console
Add JitPack to your settings.gradle or root build.gradle repositories.
allprojects {
repositories {
google()
mavenCentral()
maven { url 'https://jitpack.io' }
}
}dependencies {
implementation 'com.github.rettersoft:rio-android-sdk:{latest-version}'
}Latest release: JitPack - rio-android-sdk
-keep class com.rettermobile** { *; }
-keep class com.rettermobile.* { *; }
Create the SDK once when your app starts (usually in Application).
import android.app.Application
import com.google.gson.GsonBuilder
import com.rettermobile.rio.Rio
import com.rettermobile.rio.service.RioNetworkConfig
import com.rettermobile.rio.util.RioRegion
class App : Application() {
lateinit var rio: Rio
override fun onCreate() {
super.onCreate()
rio = Rio(
applicationContext = applicationContext,
projectId = "<YOUR_PROJECT_ID>",
culture = "en-us",
config = RioNetworkConfig.build {
// Region-based setup
region = RioRegion.EU_WEST_1
// Alternative: customDomain = "api.example.com"
sslPinningEnabled = true
gson = GsonBuilder().create()
}
)
}
}Notes:
- You must provide either
regionorcustomDomain. customDomainmust not includehttp://orhttps://.
Common RioNetworkConfig fields:
sslPinningEnabled: Enables/disables public key pinning. Default istrue.sslPins: Provide your own host+pin (sha256/...) pairs instead of default pins.pinnedPemCertificate: Optional PEM content string. If provided, interceptor-level certificate matching is also enforced.interceptor: Add an application interceptor.networkInterceptor: Add a network interceptor.headerInterceptor: Add custom headers to every request.connectionSpec: Customize TLS connection specs.logLevel: OkHttp logging level.
The SDK supports public key pinning by default. You can additionally enforce PEM certificate pinning.
Rules:
- If
pinnedPemCertificateis null/empty, PEM validation is skipped. - If
pinnedPemCertificateis provided, SDK checks whether any certificate in TLS peer chain matches your PEM certificate. - If there is no match, request fails with
SSLPeerUnverifiedException.
val pemContent = applicationContext.assets
.open("server_cert.pem")
.bufferedReader()
.use { it.readText() }
val config = RioNetworkConfig.build {
region = RioRegion.EU_WEST_1
sslPinningEnabled = true
pinnedPemCertificate = pemContent
}rio.authenticateWithCustomToken("<CUSTOM_TOKEN>") { isSuccess, throwable ->
if (isSuccess) {
// signed in
} else {
// handle error
}
}rio.signOut { isSuccess, throwable ->
if (isSuccess) {
// signed out
} else {
// handle error
}
}rio.setOnClientAuthStatusChangeListener { status, user ->
// status: SIGNED_IN, SIGNED_OUT, AUTHENTICATING
}import com.rettermobile.rio.cloud.RioCloudObjectOptions
rio.getCloudObject(
RioCloudObjectOptions(
classId = "<CLASS_ID>",
instanceId = "<INSTANCE_ID>" // or key = "field" to "value"
),
onSuccess = { cloudObject ->
// cloudObject.call(...)
},
onError = { throwable ->
// handle error
}
)import com.rettermobile.rio.cloud.RioCallMethodOptions
cloudObject.call<MyResponse>(
RioCallMethodOptions(
method = "<METHOD_NAME>",
body = MyRequest(),
),
onSuccess = { response ->
val body = response.body
},
onError = { throwable ->
// handle error
}
)rio.makeStaticCall<MyResponse>(
options = RioCloudObjectOptions(
classId = "<CLASS_ID>",
method = "<METHOD_NAME>",
body = MyRequest()
),
onSuccess = { response ->
// success
},
onError = { throwable ->
// handle error
}
)cloudObject.listInstances(
onSuccess = { listResponse ->
// list data
},
onError = { throwable ->
// handle error
}
)You can subscribe to user, role, or public state channels from a cloud object.
cloudObject.public.subscribe(
eventFired = { json ->
// latest state json
},
errorFired = { throwable ->
// handle error
}
)
// Clear listeners when no longer needed
cloudObject.unsubscribeStates()You can set global retry config while creating SDK:
import com.rettermobile.rio.service.RioRetryConfig
val retryConfig = RioRetryConfig(
delay = 50,
count = 3,
rate = 1.5
)
val rio = Rio(
applicationContext = applicationContext,
projectId = "<YOUR_PROJECT_ID>",
config = RioNetworkConfig.build { region = RioRegion.EU_WEST_1 },
retryConfig = retryConfig
)You can also override retry per call via RioCallMethodOptions.retry.
Error callback may return RioErrorResponse:
import com.rettermobile.rio.cloud.RioErrorResponse
val onError: (Throwable?) -> Unit = { throwable ->
if (throwable is RioErrorResponse) {
val code = throwable.code
val raw = throwable.rawBody
val parsed = throwable.body<MyErrorModel>()
}
}rio.logEnable(true)
rio.setLoggerListener { message ->
// forward logs to your logging system
}- Keep a single
Rioinstance (singleton-style). - Always handle error callbacks for network/auth flows.
- Clean up realtime listeners when screen/lifecycle ends (
unsubscribeStates). - For pinning-enabled production setups, define a certificate rotation strategy.