Skip to main content
Version: 5.x

Migrating the Android client from v4

This page takes an app from any 4.x release of the Android client to 5.3.0. For a fresh integration, use the Android guide instead.

Upgrade the client and the relay together

5.3.0 speaks frame version 2 and needs a v5 relay. A v4 client cannot talk to a v5 relay (the relay answers 478), and 5.3.0 cannot talk to a v4 relay. Plan the app release alongside the relay upgrade.

Dependency and packages​

The artifact was renamed, and the MTE core now arrives transitively:

// build.gradle.kts
dependencies {
// was: implementation("com.eclypses:eclypses-aws-mte-relay-client-android-release:4.x")
implementation("com.eclypses:mte-relay-client-android:5.3.0")
implementation("com.squareup.okhttp3:okhttp:4.12.0")
// Volley, slf4j and logback no longer need declaring for the relay
}

The package moved from com.eclypses.mte.relay to com.eclypses.relay:

import com.eclypses.relay.Relay // was: com.eclypses.mte.relay.Relay
import com.eclypses.relay.RelayResponseListener // was: com.eclypses.mte.relay.callback.RelayResponseListener

Remove any keep rules you added for the relay. 5.3.0 ships its own consumer R8 rules, including the MTE core's; a minified release build needs nothing from you.

Getting the instance​

// v4 — a pairing callback at construction
val relay = Relay.getInstance(context, object : RelayResponseListener {
override fun onCompletion(success: Boolean, message: String) { }
})

// 5.3.0 — no listener; pairing happens on the first request
val relay = Relay.getInstance(applicationContext)

The licence is built in. getInstance throws RelayException if it cannot be validated.

headersToEncrypt is now unencryptedHeaders, and means the opposite​

v4 encrypted only the headers you listed. 5.3.0 encrypts every header and leaves in the clear only those you list. Porting a v4 list unchanged would send exactly the headers you meant to protect in the clear, so in most cases pass null. List a header only when something between your app and the relay has to read it. Never list Authorization.

Content-Type, Content-Length, Host, X-MTE-Relay-Route and X-MTE-Relay-Client are reserved and always encrypted; listing one throws IllegalArgumentException.

Requests: Volley is gone​

addToMteRequestQueue and RelayVolleyRequestListener were removed; OkHttp is the only transport. If your app uses OkHttp, the smallest change is interceptor mode. Your client, calls and callbacks stay as they are:

val client = OkHttpClient.Builder()
.addInterceptor(Relay.getInstance(applicationContext).getOkHttpInterceptor())
.build()

client.newCall(request).enqueue(yourExistingCallback) // request addressed to the relay host

A failure of the relay's own arrives at your onFailure as a RelayCallException whose cause is the specific exception.

Or send through the relay directly (wrapper mode, also required for file transfer and SSE):

relay.send(request, null, null, object : RelayOkHttpRequestListener {
override fun onResponse(response: Response) { } // 2xx
override fun onError(response: Response) { } // the origin replied non-2xx
override fun onFailure(request: Request, cause: Throwable) { } // no HTTP response at all
})

Callbacks arrive on a background thread; Volley delivered them on the main thread, so post UI work there yourself.

File upload​

The route moved into RelayFileRequestProperties, which also gained pathnamePrefix:

// v4
val props = RelayFileRequestProperties(serverUrl, headers, headersToEncrypt, streamCallback)
relay.uploadFile(props, route, responseListener, progressCallback)

// 5.3.0
val props = RelayFileRequestProperties(
serverUrl, // the relay host
route, // e.g. "/api/files/upload"
null, // pathnamePrefix
headers, // must include Content-Length: the exact body size
null, // unencryptedHeaders — leave encrypted
streamCallback, // RelayStreamCallback: write the body, then close the stream
)
relay.uploadFile(props, responseListener, progressCallback)

The relay's advertised request-body limit now applies to streamed uploads too. An upload over it is refused before anything is sent, with RelayRequestTooLargeException.

File download​

// v4
val props = RelayFileRequestProperties(serverUrl, route, downloadPath, headers, headersToEncrypt)

// 5.3.0 — note the order: downloadPath comes BEFORE pathnamePrefix
val props = RelayFileRequestProperties(
serverUrl,
route,
downloadFile.absolutePath, // downloadPath
null, // pathnamePrefix
headers,
null, // unencryptedHeaders
)
relay.downloadFile(props, responseListener)

Both new constructors take a String in the third and fourth positions, so swapping them compiles and fails at runtime with a 404. Keep the order above.

Re-pairing and settings​

// v4
relay.rePairWithRelayServer(relayUrl, listener)
relay.adjustRelaySettings(serverUrl, streamChunkSize, pairPoolSize, persistPairs)

// 5.3.0
relay.rePairWithRelayServer("https://your-relay-server.com", null,
object : RelayResponseListener {
override fun onCompletion(success: Boolean, message: String) { }
})

val settings = RelayClientSettings(5, 8, 15, 300, 1.0)
// minPairs, basePairs, maxPairs, keepAliveIntervalSeconds, acquisitionWaitTime
relay.adjustRelaySettings("https://your-relay-server.com", null, settings,
object : RelayResponseListener {
override fun onCompletion(success: Boolean, message: String) { }
})

The stream chunk size and persistPairs are gone.

Logging​

The static logging methods no longer take a server URL:

Relay.enableFileLogging(true) // was: enableFileLogging(serverUrl, true)
val log = Relay.readLogFile() // was: readLogFile(serverUrl)
Relay.clearLogFile()

A healthy start logs Using Relay Version 5.3.0 and Mte Version 4.2.1.