# Android integration

In plain English: this page is a collection of how-tos for the Amply Android SDK beyond "just get it running." It covers where to initialize, deeplink intent filters, lifecycle (the SDK handles this for you), and the permissions that affect what data the SDK can collect. A PM can skim headings to understand which knobs exist; an engineer copies the Kotlin snippets.

**Use this when** the Android SDK is initialized and you need to wire up a specific flow. **Don't use this when** you haven't finished the Quickstart yet — start there.

## Before you start

* Android SDK 24+ target.
* An `Application` subclass — create one if you don't already have it.

## Initialize in your Application class

The SDK needs the `Application` instance because it hooks Android's lifecycle to auto-manage sessions. This is the main difference from iOS, where you call `pauseSession` / `resumeSession` yourself.

**Signatures** (from `Amply`):

```kotlin
// Android
Amply(config: AmplyConfig, application: Application)
```

```kotlin
// MyApplication.kt
import android.app.Application
import tools.amply.sdk.Amply
import tools.amply.sdk.config.amplyConfig

class MyApplication : Application() {

    lateinit var amply: Amply
        private set

    override fun onCreate() {
        super.onCreate()

        val config = amplyConfig {
            api {
                appId = "your.app.id"
                apiKeyPublic = "your_public_key"
                apiKeySecret = "your_secret_key"
            }
        }

        amply = Amply(config, this)
    }
}
```

Register it in `AndroidManifest.xml`:

```xml
<application
    android:name=".MyApplication"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:theme="@style/Theme.App">
    <!-- activities -->
</application>
```

### Accessing the instance

Expose it through the `Application` context:

```kotlin
// Anywhere with a Context
val amply = (context.applicationContext as MyApplication).amply
amply.track("screen_viewed")
```

Consider wrapping this in a small helper (`App.amply(context)`) so the cast doesn't leak through your codebase.

## Lifecycle is automatic

Once the SDK has your `Application`, it listens to process lifecycle events and manages sessions for you. You do **not** need to call `pauseSession`, `resumeSession`, or `stopSession` in `onPause`/`onStop` — those methods don't exist on the Android SDK.

What this means in practice:

* Session starts the first time your app enters the foreground after init.
* Session pauses shortly after the last Activity leaves the foreground.
* A new session begins when the user returns after the timeout.

## Registering deeplink intent filters

The SDK delivers campaign deeplinks to your listener regardless of scheme, but Android still needs to know how to route URLs from outside your process (notification taps, browser handoff). Declare an intent filter on the Activity that should receive them.

```xml
<!-- AndroidManifest.xml -->
<activity
    android:name=".MainActivity"
    android:launchMode="singleTask"
    android:exported="true">
    <intent-filter android:autoVerify="false">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="yourapp" android:host="promo" />
    </intent-filter>
</activity>
```

Use the same scheme (`yourapp://`) when authoring campaign deeplink URLs in the Amply dashboard.

## Receiving campaign deeplinks

Register a listener after SDK init. Return `true` if you handled the URL, `false` to fall through.

**Signature:**

```kotlin
fun registerDeepLinkListener(listener: DeepLinkListener)
// DeepLinkListener.onDeepLink(url: String, info: Map<String, Any>): Boolean
```

```kotlin
// MyApplication.onCreate()
amply.registerDeepLinkListener { url, info ->
    when {
        url.startsWith("yourapp://promo/") -> {
            val promoId = url.removePrefix("yourapp://promo/")
            Router.openPromo(this, promoId)
            true
        }
        else -> false
    }
}
```

### Handling external deeplinks

When the user taps a URL in another app, Android delivers it as an `Intent` to your declared Activity. Amply's listener handles campaign-triggered deeplinks; external ones still go through standard `Intent` handling:

```kotlin
// MainActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    intent?.data?.let { uri -> handleUri(uri) }
}

override fun onNewIntent(intent: Intent) {
    super.onNewIntent(intent)
    intent.data?.let { uri -> handleUri(uri) }
}

private fun handleUri(uri: Uri) {
    // Your navigation
}
```

## Permissions

### Advertising ID (optional)

To collect the Google Advertising ID, add the dependency:

```kotlin
// app/build.gradle.kts
dependencies {
    implementation("com.google.android.gms:play-services-ads-identifier:18.0.1")
}
```

Starting with Android 13, the Play Services library also requires a manifest permission, which is added automatically by the library's manifest merger. No further code is needed — the SDK picks up the ID when available.

### Internet

The SDK requires `android.permission.INTERNET`, which is included by default in apps targeting recent SDK versions. Verify it's not stripped by a restrictive manifest.

## Listening to SDK system events

Useful during development to see when config loads, when sessions start, and which campaigns evaluate.

**Signature:**

```kotlin
fun setSystemEventsListener(listener: SystemEventsListener)
// SystemEventsListener.onEvent(event: EventInterface)
```

```kotlin
amply.setSystemEventsListener { event ->
    Log.d("Amply", "${event.name} ${event.properties}")
}
```

## Log level

```kotlin
amply.setLogLevel("debug")   // 'none' | 'error' | 'warn' | 'info' | 'debug'
```

Leave it at `warn` or lower in production builds.

## Push notification preflight popup

Asking Android 13+ for `POST_NOTIFICATIONS` directly means a single dialog. The pattern most apps use is a soft-preflight popup via an Amply campaign, which routes to a deeplink that triggers the system permission.

```kotlin
// In your deeplink listener
amply.registerDeepLinkListener { url, _ ->
    if (url == "yourapp://permissions/push") {
        requestPostNotificationsPermission()
        true
    } else false
}
```

For the full recipe, see [Soft push permission](/recipes/soft-push-permission.md).

## Related

* [Android quickstart](/developer-guide/quickstart-android.md) — initial setup, not covered here.
* [Tracking events](/developer-guide/tracking-events.md) — payload shapes and common patterns.
* [Handling deeplinks](/developer-guide/handling-deeplinks.md) — cross-platform deeplink routing patterns.
* [Soft push permission](/recipes/soft-push-permission.md) — full preflight recipe.
* [SDK reference: Android](/reference/sdk-android.md) — full method list.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.amply.tools/developer-guide/android-integration.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
