API reference
Every public class, method, property and enum in lander-android 0.1.0.
Everything public is in the link.lander.android package:
import link.lander.android.*| Type | Kind |
|---|---|
Lander | Entry point (a Kotlin object; static methods from Java) |
LanderLink | A link delivered to the app |
LanderShortLink | A link created with createLink |
LanderLinkOptions | The fields of a link to create, with a builder for Java |
LanderConfidence | Enum: how sure Lander is |
LanderException | Error from calls that need the API |
LanderLinkListener, LanderSubscription, LanderCallback | Callback types for Java |
Lander
object LanderKotlin calls members on Lander directly. From Java, every non suspending member is a static method (Lander.handleIntent(intent)); suspending functions have callback overloads.
Lander.VERSION
const val VERSION: String // "0.1.0"The SDK version, sent as sdkVersion in the launch report and as X-Lander-Sdk: android/0.1.0 on every request.
Lander.DEFAULT_BASE_URL
const val DEFAULT_BASE_URL: String // "https://api.golander.link"Lander.initialize
@JvmStatic @JvmOverloads
fun initialize(
context: Context,
apiKey: String,
baseUrl: String = DEFAULT_BASE_URL,
enableLogging: Boolean = false,
)Starts the SDK. Call it once, in Application.onCreate. Returns immediately; the install ID is loaded and the launch reported with POST /v1/sdk/init in the background.
Prop
Type
- Throws
IllegalArgumentExceptionwhenapiKey, trimmed, is a secret key or not a publishable key (pk_test_orpk_live_followed by at least 24 letters or digits). The key is never included in the message. - Never throws for network errors.
- A second call is ignored.
- Registers activity lifecycle callbacks on the
Application: events are flushed when the app goes to the background, a failed first launch report is retried when it comes back, and links of activities restored after process death are not delivered again.
Lander.handleIntent
@JvmStatic
fun handleIntent(intent: Intent?)Hands an intent to Lander. Call it from onCreate and onNewIntent of every activity with Lander intent filters.
- Reads the URL of
ACTION_VIEWintents; other intents carry no link. The first call of the process tells the SDK whether the app was launched by a link. - Marks the intent with an extra, so a recreated activity (rotation, process death, Recents) does not deliver the link again. Intents with
FLAG_ACTIVITY_LAUNCHED_FROM_HISTORYare ignored. - The same URL twice within two seconds counts once.
- Safe before
initialize: the link is kept until the SDK starts. Any thread.
Lander.deepLinks
@JvmStatic
val deepLinks: Flow<LanderLink>Every link the app receives: App Links, custom scheme URLs and deferred links.
- Safe to collect at any time, even before
initialize. - Links that arrive while nobody collects are buffered and replayed, in order, to the next collector.
- Every active collector gets live links; buffered links go to the first one.
- Includes the launch link unless
getInitialLinkclaimed it first. - Unknown links and links that could not be resolved are delivered with
isResolved == falseand only the URI set. - Does not include links returned by
claimHandoff.
Lander.addDeepLinkListener
@JvmStatic
fun addDeepLinkListener(listener: LanderLinkListener): LanderSubscriptiondeepLinks for Java or Kotlin without coroutines. The listener is called on the main thread, starting with buffered links. Call remove() on the returned subscription to stop.
Lander.getInitialLink
suspend fun getInitialLink(): LanderLink?
@JvmStatic
fun getInitialLink(callback: LanderCallback<LanderLink?>)The link that launched the app, or null. Waits until the launch intent reached handleIntent (or the first activity resumed), then for the resolve request when the app was opened by a link, and on a first launch for the launch report (a deferred link may come back). Delivered once: returns null if deepLinks or an earlier call already delivered it, and after this call deepLinks will not deliver it.
Throws IllegalStateException before initialize.
Lander.createLink
suspend fun createLink(
path: String = "/",
params: Map<String, Any> = emptyMap(),
title: String? = null,
campaign: String? = null,
channel: String? = null,
tags: List<String> = emptyList(),
iosFallbackUrl: String? = null,
androidFallbackUrl: String? = null,
webFallbackUrl: String? = null,
ogTitle: String? = null,
ogDescription: String? = null,
ogImageUrl: String? = null,
expiresAt: Date? = null,
): LanderShortLink
suspend fun createLink(options: LanderLinkOptions): LanderShortLink
@JvmStatic
fun createLink(options: LanderLinkOptions, callback: LanderCallback<LanderShortLink>)Creates a short link with POST /v1/sdk/links. The slug is random and the domain is the project's default domain.
Prop
Type
- Throws
IllegalArgumentExceptionwhenpathdoes not start with/or aparamsvalue is not aString,NumberorBoolean. - Throws
LanderExceptionwhen the request fails. Retries network errors, timeouts, 408, 429 (exceptlink_quota_exceeded) and 5xx up to 3 attempts with oneIdempotency-Key, waiting at most 10 seconds in total. - Throws
IllegalStateExceptionbeforeinitialize.
Lander.claimHandoff
suspend fun claimHandoff(userId: String): LanderLink?
@JvmStatic
fun claimHandoff(userId: String, callback: LanderCallback<LanderLink?>)After sign in, returns the link your backend bound to userId with POST /v1/handoffs, or null when nothing is pending. The link has isDeferred == true, confidence == DETERMINISTIC and method == "authenticated_handoff". It is returned only, never also emitted on deepLinks.
- Throws
IllegalArgumentExceptionwhenuserId, trimmed, is empty or longer than 256 characters. - Throws
LanderExceptionwhen the request fails after retries, or with codeinstall_not_registeredwhen the install could not be reported to Lander yet. - Throws
IllegalStateExceptionbeforeinitialize.
Lander.trackEvent
@JvmStatic @JvmOverloads
fun trackEvent(name: String, properties: Map<String, Any?> = emptyMap(), linkId: String? = null)Records a custom event. Fire and forget: validates, queues and returns. Events are stored on the device and sent in batches of up to 100 to POST /v1/sdk/events, with retries.
- Throws
IllegalArgumentExceptionfor anamethat is empty or over 100 characters, alinkIdthat is not a UUID, orpropertiesthat are not JSON values. - Never throws for network errors.
- Throws
IllegalStateExceptionbeforeinitialize.
Lander.installId
@JvmStatic
val installId: String?The random UUID v4 of this install, once loaded (shortly after initialize). Stored in noBackupFilesDir, so it never moves to another device.
LanderLink
class LanderLink(
val uriString: String,
val linkId: String? = null,
val url: String? = null,
val path: String? = null,
val params: Map<String, Any> = emptyMap(),
val campaign: String? = null,
val channel: String? = null,
val isDeferred: Boolean = false,
val confidence: LanderConfidence = LanderConfidence.UNATTRIBUTED,
val method: String? = null,
)A link delivered to the app. When Lander knows the link, the fields mirror the API's ResolvedLink; otherwise only the URI is set.
| Property | Type | Meaning |
|---|---|---|
uriString | String | The URL that opened the app, exactly as Android delivered it. For a deferred link, the link's own URL. |
uri | Uri | uriString parsed as an android.net.Uri. |
linkId | String? | Lander link ID, or null when unknown to Lander. |
url | String? | Canonical short link. |
path | String? | The in app route set on the link. |
params | Map<String, Any> | Link params with the opened URL's query parameters merged over them. Values are String, Number or Boolean. |
campaign, channel | String? | Attribution labels. |
isDeferred | Boolean | Recovered after an install or handed off after sign in. |
confidence | LanderConfidence | How sure Lander is. |
method | String? | app_link, universal_link, install_referrer, landing_page, authenticated_handoff or probabilistic_match. null when unresolved. |
isResolved | Boolean | linkId != null. |
route | String | path when resolved, otherwise the raw URL's path and query; for custom scheme URLs the host is the first path segment (acmeshop://product/123 gives /product/123). |
LanderLink.unresolved(uri: String) builds an unresolved link, handy in tests. equals compares every field; toString() summarizes the link for logs.
LanderShortLink
class LanderShortLink(
val id: String,
val url: String,
val domain: String,
val slug: String,
val path: String,
val params: Map<String, Any> = emptyMap(),
val title: String? = null,
val campaign: String? = null,
val channel: String? = null,
val tags: List<String> = emptyList(),
val expiresAt: Date? = null,
val createdAt: Date? = null,
)A link created with createLink. uri is url as an android.net.Uri. toString() returns url. Two short links are equal when id and url are.
LanderLinkOptions
class LanderLinkOptions private constructor(...) {
class Builder {
fun path(path: String): Builder
fun param(key: String, value: Any): Builder
fun params(params: Map<String, Any>): Builder
fun title(title: String?): Builder
fun campaign(campaign: String?): Builder
fun channel(channel: String?): Builder
fun tags(tags: List<String>): Builder
fun iosFallbackUrl(url: String?): Builder
fun androidFallbackUrl(url: String?): Builder
fun webFallbackUrl(url: String?): Builder
fun ogTitle(title: String?): Builder
fun ogDescription(description: String?): Builder
fun ogImageUrl(url: String?): Builder
fun expiresAt(date: Date?): Builder
fun build(): LanderLinkOptions
}
}The same fields as createLink's parameters, readable as properties. build() throws IllegalArgumentException for a path without a leading / or a param value that is not a String, Number or Boolean.
LanderConfidence
enum class LanderConfidence(val wireName: String) {
DETERMINISTIC("deterministic"),
PROBABILISTIC("probabilistic"),
UNATTRIBUTED("unattributed"),
}| Value | Meaning |
|---|---|
DETERMINISTIC | Matched by an exact identifier: an App Link open, a Play Install Referrer token, the Continue in app page or an authenticated handoff. |
PROBABILISTIC | Matched by coarse signals within a short window. Only for iOS deferred links of projects that opted in. |
UNATTRIBUTED | No link could be tied to this open. Unresolved links always have this. |
LanderConfidence.parse(value) maps the API's string to a value, with anything unknown as UNATTRIBUTED.
LanderException
class LanderException(
val code: String,
override val message: String,
val statusCode: Int? = null,
val retryAfter: kotlin.time.Duration? = null,
) : Exception(message)Thrown by calls that need an answer from the API (createLink, claimHandoff). initialize and trackEvent never throw it.
| Property | Meaning |
|---|---|
code | The API's error code (for example rate_limited), or network_error, timeout, invalid_response or install_not_registered for client side failures. |
message | Human readable. |
statusCode | HTTP status, or null when no response was received. |
retryAfter | The server's Retry-After, when it sent one. |
retryAfterMillis | retryAfter in milliseconds, for Java. |
isRetryable | true for no response, invalid_response, 408, 429 (except link_quota_exceeded) and 5xx. |
Java callbacks
fun interface LanderLinkListener {
fun onDeepLink(link: LanderLink)
}
fun interface LanderSubscription {
fun remove()
}
interface LanderCallback<T> {
fun onSuccess(result: T)
fun onError(error: Exception)
}Listeners and callbacks are called on the main thread. onError receives a LanderException for API and network failures, or an IllegalArgumentException / IllegalStateException for programming errors.