LimeLink Android SDK 1.0.1
Min SDK 24 · Compile SDK reference 33 · Java bytecode 8
LimeLink Android SDK handles direct links, App Links, deferred deep links, and explicit view tracking through Kotlin and Java facades. Version 1.0.1 is publicly resolvable from the LimeLink Maven repository and has an immutable GitHub Release.
View previous Android SDK releases
Install
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven {
url = uri("https://hellovelop.github.io/limelink-aos-sdk-binary/repository")
content { includeGroup("org.limelink") }
}
}
}
dependencies {
implementation("org.limelink:limelink-aos-sdk:1.0.1")
}
The public Maven repository supports credential-free Gradle resolution. JitPack, source dependencies, composite builds, Maven Local, debug AARs, and direct release-AAR installation are not production routes.
Initialize
class MyApp : Application() {
private val listener = object : LimeLinkListener {
override fun onDeeplinkReceived(result: LimeLinkResult) {
val destination = result.deeplinkUrl ?: result.originalUrl
if (destination != null && isAllowedDestination(destination)) {
navigateTo(destination)
}
}
override fun onDeferredDeepLinkNotFound() = Unit
override fun onDeeplinkError(error: LimeLinkError) {
showSafeFallback(error.code, error.message)
}
}
override fun onCreate() {
super.onCreate()
LimeLinkSDK.addLinkListener(listener)
val config = LimeLinkConfig.Builder(
"550e8400-e29b-41d4-a716-446655440000"
).setLogging(false).build()
LimeLinkSDK.init(this, config)
}
}
Use the public Project UUID in app configuration; Organization API credentials remain server-side credentials. Automatic deferred lookup starts for every eligible installation.
Manifest and lifecycle
Register the MyApp Application from the initialization example and configure the receiving Activity in AndroidManifest.xml. Merge into your existing manifest; do not create a second Application or replace unrelated launcher filters:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<application android:name=".MyApp">
<activity android:name=".MainActivity"
android:exported="true" android:launchMode="singleTop">
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" android:host="YOUR_LINK_HOST" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="myapp" android:host="open" />
</intent-filter>
</activity>
</application>
</manifest>
Replace YOUR_LINK_HOST with the exact LimeLink or Custom Domain hostname, and myapp://open with your app-owned scheme/host. Register the matching Android package and SHA-256 signing fingerprint in LimeLink. Verify that host's /.well-known/assetlinks.json; autoVerify alone does not establish an association. Restrict paths only when they cover all intended Links—both /{suffix} and /link/{suffix} may be used. HTTPS requires no cleartext traffic exception.
In MainActivity, keep the current Intent updated:
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
setIntent(intent)
}
Normal Activity lifecycle handling owns cold and warm App Links. Only when the host explicitly owns a handoff, call:
LimeLinkSDK.handleIncomingLink(this, intent)
The API accepts actual ACTION_VIEW Intents. Direct links are absolute hierarchical non-web URLs resolved to the host app; HTTP(S) links use Dynamic Lookup. Unsafe, malformed, relative, whitespace, and control-character URLs are rejected. Direct links stay local to the app without resolve or Stats networking.
Receive results
The strongly retained listener registered before init receives Direct, App Link, and Deferred successes through onDeeplinkReceived.
| Field | Contract |
|---|---|
deeplinkUrl | Nullable resolved app destination; null when an App Link is unresolved or unregistered |
source | directDeepLink, universalLink, or deferredDeepLink |
originalUrl | null for direct, inbound HTTPS URL for App Links, backend original URL for Deferred |
isDeferred | Derived from Deferred source |
All public callbacks run on the Android main thread. For an unresolved App Link, deeplinkUrl is null, originalUrl preserves the exact inbound HTTPS URL, source is universalLink, and no separate error callback is emitted. If the app chooses browser fallback, use deeplinkUrl ?: originalUrl, then parse and exactly compare the selected URL's scheme and host against an app-owned allowlist before navigation.
Buffering, ordering, and deduplication
- Pre-initialization accepted links use a process-memory capacity-10, oldest-drop FIFO and start after successful initialization.
- Successful results completed without listeners use a separate capacity-10 FIFO and replay once to the first non-empty listener snapshot.
- Errors and deferred not-found outcomes are live-only and never replayed.
- Work completes independently; a direct result may overtake a network lookup.
- The dedupe key is source plus exact ingress URL. Pending/in-flight duplicates and successful duplicates within five monotonic seconds are suppressed without URL normalization.
- Process death clears in-memory queues.
Manual deferred handling
LimeLinkSDK.handleDeferredDeepLink(this) { result, error ->
when {
result?.deeplinkUrl != null && isAllowedDestination(result.deeplinkUrl) ->
navigateTo(result.deeplinkUrl)
error != null -> showSafeFallback(error.code, error.message)
else -> Unit
}
}
Matched, not-found, and failed outcomes reach both the completion and current listener. Their relative order is unspecified; choose one navigation owner.
Java facade
The Java facade exposes exactly:
LimeLinkJavaSDK.initialize(context, config, listener);
LimeLinkJavaSDK.handleIncomingLink(activity, intent);
LimeLinkJavaSDK.handleDeferredDeepLink(context, callback);
boolean initialized = LimeLinkJavaSDK.isInitialized();
Java initialization must run on the main thread. The Deferred callback provides onMatched, onNotFound, and onFailed.
Explicit stats
Use LimeLinkSDK.trackLinkStatus(context, intent) only for a separate app-owned view event. It is best effort; successful Dynamic Lookup already owns lookup attribution.
Verify and Troubleshoot
- Confirm the Project has one active Android Application with the expected package name, app scheme, and SHA-256 fingerprint.
- Confirm the manifest intent filter and hosted App Links association use the exact Link hostname.
- Test cold and warm App Links plus a direct app-owned scheme; keep
setIntent(intent)inonNewIntent. - Test resolved, unresolved, deferred matched, deferred not-found, and safe error behavior.
If Gradle cannot resolve the package, verify the LimeLink Maven repository and org.limelink content filter before adding any unsupported fallback repository. If callbacks do not arrive, verify initialization/listener order and that the host is not recreating and forwarding the initial URL a second time.
Migrating from 1.0.0
- Treat
deeplinkUrlas nullable. - Handle unresolved App Links as successful results and use the exact
originalUrlonly for an allowlisted browser fallback.
Migrating from 0.4.1
- Replace removed
handleUniversalLink(activity, intent)withhandleIncomingLink(activity, intent). - Replace
resolvedUriwith nullabledeeplinkUrl. - Remove
queryParams,pathParams, andPathParamResponse; parsedeeplinkUrlwhen needed. - Handle the required
sourceand nullableoriginalUrlfields. - Recompile consumers against
1.0.1and apply native FIFO/deduplication semantics.