# API reference

> Every public type, property and method in the Grovs Android SDK 3.1.

Source: https://docs.grovs.io/docs/sdk/android/api-reference

Members are on the `Grovs` companion object, so Kotlin calls them as `Grovs.configure(...)` and Java as `Grovs.Companion.configure(...)`. Push helpers for your own messaging service are on [`GrovsMessaging`](#grovsmessaging). Every method works from any thread.

## At a glance

| Area                   | Member                                                                        | Kind      | What it does                                 |
| ---------------------- | ----------------------------------------------------------------------------- | --------- | -------------------------------------------- |
| **Setup**              | [`configure`](#configure)                                                     | method    | Configures and authenticates the SDK         |
|                        | [`setSDK`](#setsdk)                                                           | method    | Turns collection on or off                   |
|                        | [`setDebug`](#setdebug)                                                       | method    | Sets the log level                           |
| **Deep links**         | [`onStart`](#onstart)                                                         | method    | Resolves the launch link                     |
|                        | [`onNewIntent`](#onnewintent)                                                 | method    | Resolves links while running                 |
|                        | [`setOnDeeplinkReceivedListener`](#setondeeplinkreceivedlistener)             | method    | Registers the deep link listener             |
|                        | [`openedLinkDetails`](#openedlinkdetails)                                     | property  | Last link that opened the app                |
| **Users**              | [`identifier`](#identifier)                                                   | property  | Your ID for the current user                 |
|                        | [`attributes`](#attributes)                                                   | property  | Attributes of the current user               |
| **Links**              | [`generateLink`](#generatelink)                                               | method    | Creates a smart link                         |
|                        | [`linkDetails`](#linkdetails)                                                 | method    | Details of a link by path                    |
| **Events**             | [`track`](#track)                                                             | method    | Tracks a custom event                        |
|                        | [`trackScreenView`](#trackscreenview)                                         | method    | Tracks a screen view                         |
|                        | [`trackNavigation`](#tracknavigation)                                         | method    | Tracks Jetpack Navigation destinations       |
|                        | [`setGlobalTags`](#setglobaltags)                                             | method    | Tags added to every event                    |
|                        | [`setScreenAliases`](#setscreenaliases)                                       | method    | Renames screens for the dashboard            |
| **Revenue**            | [`logInAppPurchase`](#loginapppurchase)                                       | method    | Logs a Google Play purchase                  |
|                        | [`logCustomPurchase`](#logcustompurchase)                                     | method    | Logs a purchase outside Google Play          |
| **Push notifications** | [`pushToken`](#pushtoken)                                                     | property  | FCM token for push campaigns                 |
|                        | [`handleNotificationOpen`](#handlenotificationopen)                           | method    | Handles a tap intent the launcher didn't get |
|                        | [`isGrovsNotification`](#isgrovsnotification)                                 | method    | Checks if Grovs sent a push                  |
|                        | [`GrovsMessaging`](#grovsmessaging)                                           | class     | Calls for your own messaging service         |
|                        | [`MessagingService`](#messagingservice)                                       | class     | The SDK's messaging service                  |
| **In-app messages**    | [`setInAppListener`](#setinapplistener)                                       | method    | Receives in-app message events               |
|                        | [`pauseInAppMessages`](#pauseinappmessages)                                   | method    | Holds messages back                          |
|                        | [`resumeInAppMessages`](#resumeinappmessages)                                 | method    | Lets messages show again                     |
|                        | [`discardInAppMessages`](#discardinappmessages)                               | method    | Drops waiting messages                       |
|                        | [`setInAppExcludedScreens`](#setinappexcludedscreens)                         | method    | Screens where no message shows               |
|                        | [`setInAppDebugLogging`](#setinappdebuglogging)                               | method    | Logs why campaigns were skipped              |
| **Types**              | [`DeeplinkDetails`](#deeplinkdetails)                                         | class     | A resolved deep link                         |
|                        | [`GrovsDeeplinkListener`](#grovsdeeplinklistener)                             | interface | Deep link callback                           |
|                        | [`GrovsLinkGenerationListener`](#grovslinkgenerationlistener)                 | interface | `generateLink` callback                      |
|                        | [`GrovsLinkDetailsListener`](#grovslinkdetailslistener)                       | interface | `linkDetails` callback                       |
|                        | [`GrovsInAppListener`](#grovsinapplistener)                                   | interface | In-app message callbacks                     |
|                        | [`GrovsInAppListenerAdapter`](#grovsinapplisteneradapter)                     | class     | `GrovsInAppListener` for Java                |
|                        | [`GrovsException`](#grovsexception)                                           | class     | Link and SDK failures                        |
|                        | [`GrovsErrorCode`](#grovserrorcode)                                           | enum      | Failure categories                           |
|                        | [`TrackingParams`](#trackingparams)                                           | class     | UTM parameters                               |
|                        | [`CustomRedirects`](#customredirects)                                         | class     | Per-platform link redirects                  |
|                        | [`CustomLinkRedirect`](#customlinkredirect)                                   | class     | One platform redirect                        |
|                        | [`PaymentEventType`](#paymenteventtype)                                       | enum      | Buy, cancel or refund                        |
|                        | [`InstantCompat`](#instantcompat)                                             | class     | Point in time for API 21                     |
|                        | [`LogLevel`](#loglevel)                                                       | enum      | Log verbosity                                |
| **Deprecated**         | [`displayMessagesFragment`](#displaymessagesfragment)                         | method    | Shows nothing                                |
|                        | [`numberOfUnreadMessages`](#numberofunreadmessages)                           | method    | Always `0`                                   |
|                        | [`setOnAutomaticNotificationsListener`](#setonautomaticnotificationslistener) | method    | Never called                                 |
|                        | [`GrovsNotificationsListener`](#grovsnotificationslistener)                   | interface | Never called                                 |
|                        | [`handleGrovsNotification`](#handlegrovsnotification)                         | method    | Use `GrovsMessaging.handleMessage`           |

---

## Setup

### configure

Kind: method

```kotlin
fun configure(application: Application, apiKey: String, useTestEnvironment: Boolean, baseURL: String? = null)
fun configure(application, apiKey, useTestEnvironment, baseURL, autoTrackScreenViews: Boolean)
fun configure(application, apiKey, useTestEnvironment, baseURL, autoTrackScreenViews, clipboardDomains: List<String>?)
fun configure(application, apiKey, useTestEnvironment, baseURL, autoTrackScreenViews, clipboardDomains, enabled: Boolean)
```

Configures and authenticates the SDK. Call once per launch, in `Application.onCreate()`.

| Name                   | Type            | Description                                                                                                                                              |
| ---------------------- | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `application`          | `Application`   | Your `Application` instance.                                                                                                                             |
| `apiKey`               | `String`        | Project API key from the Grovs dashboard.                                                                                                                |
| `useTestEnvironment`   | `Boolean`       | `true` targets the test environment, `false` production.                                                                                                 |
| `baseURL`              | `String?`       | Domain of a self-hosted backend, for example `"https://sdk.example.com"`. The SDK appends the API path. `null` targets the Grovs cloud.                  |
| `autoTrackScreenViews` | `Boolean`       | Track Activity and Fragment screen views automatically. Defaults to `true`.                                                                              |
| `clipboardDomains`     | `List<String>?` | Extra link hosts accepted by clipboard-assisted deferred deep linking, for example `listOf("links.example.com")`. Grovs-owned hosts are always accepted. |
| `enabled`              | `Boolean`       | Whether the SDK may collect and send anything this launch. Defaults to `true`.                                                                           |

- Calling it again replaces the previous configuration.
- Shorter overloads use `autoTrackScreenViews = true`, `clipboardDomains = null` and `enabled = true`.
- `enabled` isn't persisted. Pass your stored consent value every launch.

Calls made before `configure`:

| Calls                                                           | Effect                                                                                             |
| --------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
| Links passed to `onStart` or `onNewIntent`                      | Dropped, not held. Configure in `Application.onCreate()` so it runs before your launcher activity. |
| A Grovs push tap                                                | Held (the latest one) and handled once `configure` runs                                            |
| `identifier`, `attributes`, `pushToken`                         | Kept and sent once the SDK authenticates                                                           |
| `setInAppListener` and the other in-app calls                   | Kept, and survive later `configure` calls                                                          |
| `generateLink`, `linkDetails`                                   | Report a not-configured `GrovsException`                                                           |
| `track`, `trackScreenView`, `setGlobalTags`, `setScreenAliases` | Ignored                                                                                            |

### setSDK

Kind: method

```kotlin
fun setSDK(enabled: Boolean)
```

Turns collection on or off at runtime, for example when consent changes. See [Privacy & Consent](https://docs.grovs.io/docs/sdk/android/privacy).

- Call it only after `configure`.
- While disabled, the SDK doesn't authenticate, resolve the device, read the clipboard, or send events, screen views or purchases. Outstanding requests are cancelled.
- It holds `identifier`, `attributes`, `pushToken` and screen alias updates. Queued events stay on the device.
- Disabling closes an in-app message on screen and drops unreported push opens.
- Enabling authenticates if needed and sends everything held.

### setDebug

Kind: method

```kotlin
fun setDebug(level: LogLevel)
```

Sets the [log level](#loglevel). Default `ERROR`.

- Logs go through `android.util.Log` with tag `Logger`. Every message is prefixed `🔗GROVS`.

---

## Deep links

See [Deep Linking](https://docs.grovs.io/docs/sdk/android/deep-linking).

### onStart

Kind: method

```kotlin
fun onStart(launcherActivity: Activity? = null)
```

Forward from your launcher activity's `onStart()`. **Required** for the SDK to resolve the link the app was opened with.

### onNewIntent

Kind: method

```kotlin
fun onNewIntent(intent: Intent?, launcherActivity: Activity? = null)
```

Forward from your launcher activity's `onNewIntent()`. **Required** for links delivered while the app is running.

### setOnDeeplinkReceivedListener

Kind: method

```kotlin
fun setOnDeeplinkReceivedListener(launcherActivity: Activity?, listener: GrovsDeeplinkListener)
```

Registers the listener that gets [`DeeplinkDetails`](#deeplinkdetails) for every resolved link, including deferred links matched after install.

- Called on the main thread.

### openedLinkDetails

Kind: property

```kotlin
val openedLinkDetails: DeeplinkDetails?
```

The link the app was most recently opened from, or `null`.

- Observe it as a `StateFlow` with `Grovs.Companion::openedLinkDetails.flow` (import `io.grovs.utils.flow`). See [Using Kotlin Flow](https://docs.grovs.io/docs/sdk/android/deep-linking#using-kotlin-flow).

---

## Users

### identifier

Kind: property

```kotlin
var identifier: String?
```

Your identifier for the current user, typically your `user_id`. Shown in the dashboard and reports, and used to match [test messages](https://docs.grovs.io/docs/sdk/android/in-app-messages#test-messages).

- Set before `configure`, it's kept and sent once the SDK authenticates.
- While the SDK is disabled, the latest value is held until it's enabled.

### attributes

Kind: property

```kotlin
var attributes: Map<String, Any>?
```

Attributes of the current user, shown in the dashboard. In-app campaigns can filter on them and personalize text with them.

- Set before `configure`, they're kept and sent once the SDK authenticates.
- Held while the SDK is disabled.

---

## Links

Both methods come in a coroutine form and a callback form.

- The coroutine form resumes on the caller's dispatcher and throws [`GrovsException`](#grovsexception) on failure.
- The callback form runs the listener on the main thread. If the SDK isn't configured, or authentication is still retrying, the listener is called synchronously on the calling thread with a `GrovsException`.

### generateLink

Kind: method

```kotlin
suspend fun generateLink(
    title: String? = null,
    subtitle: String? = null,
    imageURL: String? = null,
    data: Map<String, Serializable>? = null,
    tags: List<String>? = null,
    customRedirects: CustomRedirects? = null,
    showPreviewIos: Boolean? = null,
    showPreviewAndroid: Boolean? = null,
    copyToClipboardIos: Boolean? = null,
    copyToClipboardAndroid: Boolean? = null,
    tracking: TrackingParams? = null
): String

fun generateLink(
    /* same parameters */,
    lifecycleOwner: LifecycleOwner? = null,
    listener: GrovsLinkGenerationListener
)
```

Creates a smart link. See [Link Creation](https://docs.grovs.io/docs/sdk/android/link-creation).

| Name                     | Type                          | Description                                                                                                                                                                                                           |
| ------------------------ | ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `title`                  | `String?`                     | Link preview title.                                                                                                                                                                                                   |
| `subtitle`               | `String?`                     | Link preview subtitle.                                                                                                                                                                                                |
| `imageURL`               | `String?`                     | Link preview image URL.                                                                                                                                                                                               |
| `data`                   | `Map<String, Serializable>?`  | Custom payload delivered on deep link open.                                                                                                                                                                           |
| `tags`                   | `List<String>?`               | Tags for filtering and analytics.                                                                                                                                                                                     |
| `customRedirects`        | `CustomRedirects?`            | Per-platform [redirect overrides](#customredirects).                                                                                                                                                                  |
| `showPreviewIos`         | `Boolean?`                    | Show the preview page on iOS. `null` uses the project default.                                                                                                                                                        |
| `showPreviewAndroid`     | `Boolean?`                    | Show the preview page on Android. `null` uses the project default.                                                                                                                                                    |
| `copyToClipboardIos`     | `Boolean?`                    | Copy the link on the iOS preview page, for [clipboard-assisted deferred deep linking](https://docs.grovs.io/docs/sdk/android/deep-linking#clipboard-assisted-deferred-deep-linking). `null` uses the project setting. |
| `copyToClipboardAndroid` | `Boolean?`                    | Same, for Android.                                                                                                                                                                                                    |
| `tracking`               | `TrackingParams?`             | [UTM campaign, source and medium](#trackingparams).                                                                                                                                                                   |
| `lifecycleOwner`         | `LifecycleOwner?`             | Callback form only. Scopes the callback to a lifecycle.                                                                                                                                                               |
| `listener`               | `GrovsLinkGenerationListener` | Callback form only. Gets the link or a `GrovsException`.                                                                                                                                                              |

**Returns** the URL (coroutine form).

### linkDetails

Kind: method

```kotlin
suspend fun linkDetails(path: String): Map<String, Any>
fun linkDetails(path: String, lifecycleOwner: LifecycleOwner? = null, listener: GrovsLinkDetailsListener)
```

Gets details for a link generated in the current environment, by path.

**Returns** the details (coroutine form). Failures throw, or reach the listener, as a `GrovsException`.

---

## Events

See [Events & Screen Tracking](https://docs.grovs.io/docs/sdk/android/analytics).

### track

Kind: method · Since 3.0

```kotlin
fun track(name: String, properties: Map<String, Any>? = null, tags: List<String>? = null)
```

Tracks a custom event.

- The name can't be blank or a [reserved name](https://docs.grovs.io/docs/sdk/android/analytics#event-name-rules). Rejected events are logged and dropped.
- Accepted events can trigger [in-app messages](https://docs.grovs.io/docs/sdk/android/in-app-messages).
- Property rules and limits: [Tracking custom events](https://docs.grovs.io/docs/sdk/android/analytics#tracking-custom-events).

### trackScreenView

Kind: method · Since 3.0

```kotlin
fun trackScreenView(screenName: String, properties: Map<String, Any>? = null)
```

Tracks a screen view.

- A repeat of the same screen within one second is dropped.

### trackNavigation

Kind: method · Since 3.0

```kotlin
fun trackNavigation(navController: NavController)
```

Tracks every destination change of a Jetpack Navigation `NavController` as a screen view. See [Jetpack Navigation](https://docs.grovs.io/docs/sdk/android/analytics#jetpack-navigation).

- Call once per controller. Repeat calls are ignored.
- Only a weak reference is kept.

### setGlobalTags

Kind: method · Since 3.0

```kotlin
fun setGlobalTags(tags: List<String>? = null)
```

Sets tags merged onto every later event. Pass `null` to clear them.

### setScreenAliases

Kind: method · Since 3.0

```kotlin
fun setScreenAliases(aliases: Map<String, String>)
```

Maps Activity and Fragment class names to dashboard names, for example `mapOf("MainActivity" to "Home")`.

---

## Revenue

See [Revenue](https://docs.grovs.io/docs/sdk/android/revenue).

### logInAppPurchase

Kind: method

```kotlin
fun logInAppPurchase(originalJson: String)
```

Logs a Google Play Billing purchase. Pass `purchase.originalJson`.

- The SDK reads the product ID and purchase token.
- The backend verifies the purchase and resolves price and currency through the Google Play Developer API.
- Purchases are de-duplicated on purchase token.

### logCustomPurchase

Kind: method

```kotlin
fun logCustomPurchase(
    type: PaymentEventType,
    priceInCents: Int,
    currency: String,
    productId: String,
    startDate: InstantCompat? = InstantCompat.now()
)
```

Logs a purchase, cancellation or refund made outside Google Play Billing.

| Name           | Type               | Description                                             |
| -------------- | ------------------ | ------------------------------------------------------- |
| `type`         | `PaymentEventType` | [`BUY`, `CANCEL` or `REFUND`](#paymenteventtype).       |
| `priceInCents` | `Int`              | Price in cents.                                         |
| `currency`     | `String`           | ISO 4217 code.                                          |
| `productId`    | `String`           | Your product identifier.                                |
| `startDate`    | `InstantCompat?`   | Defaults to now. See [`InstantCompat`](#instantcompat). |

---

## Push notifications

Setup: [Push Notifications](https://docs.grovs.io/docs/sdk/android/push-notifications).

### pushToken

Kind: property

```kotlin
var pushToken: String?
```

The FCM token, for push campaigns. See [Ask for permission and pass the token](https://docs.grovs.io/docs/sdk/android/push-notifications#3-ask-for-permission-and-pass-the-token).

- Held before `configure` and while the SDK is disabled.
- Token refreshes reach it through the SDK's [`MessagingService`](#messagingservice), or [`GrovsMessaging.onNewToken`](#grovsmessaging) from your own service.

### handleNotificationOpen

Kind: method · Since 3.1

```kotlin
fun handleNotificationOpen(intent: Intent?): Boolean
```

Handles the intent of a tapped Grovs push. Only needed when the tap doesn't reach the launcher activity's `onStart` or `onNewIntent`, for example a splash activity that doesn't forward its extras.

**Returns** `true` when the intent is a Grovs push.

- Reports a campaign open (`push_open`, once per device and campaign) and delivers the push to your [`GrovsDeeplinkListener`](#grovsdeeplinklistener).
- `data` is the push's data merged over the link's data if there is one. The push's keys win.
- The same tap seen again through `onStart` or `onNewIntent` isn't reported or delivered twice.

### isGrovsNotification

Kind: method · Since 3.1

```kotlin
fun isGrovsNotification(data: Map<String, String>): Boolean
fun isGrovsNotification(intent: Intent?): Boolean
```

Checks whether Grovs sent the push, without handling it. Pass `RemoteMessage.data`, or the intent a tap opened.

**Returns** `true` when `grovs_campaign_id` is present and not blank.

### GrovsMessaging

Kind: class · Since 3.1

```kotlin
object GrovsMessaging {
    @JvmStatic var showForegroundNotifications: Boolean = true
    @JvmStatic fun handleMessage(context: Context, message: RemoteMessage): Boolean
    @JvmStatic fun onNewToken(token: String)
}
```

For an app with its own `FirebaseMessagingService`. See [If your app has its own FirebaseMessagingService](https://docs.grovs.io/docs/sdk/android/push-notifications#if-your-app-has-its-own-firebasemessagingservice).

| Member                        | Description                                                                                                       |
| ----------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `showForegroundNotifications` | Show Grovs pushes that arrive while the app is open. Defaults to `true`. Background pushes are shown by Firebase. |
| `handleMessage`               | Call from `onMessageReceived`. Shows a Grovs push and returns `true`; returns `false` for any other message.      |
| `onNewToken`                  | Call from `onNewToken`. Same as setting [`pushToken`](#pushtoken).                                                |

### MessagingService

Kind: class · Since 3.1

```kotlin
open class MessagingService : FirebaseMessagingService()
```

`io.grovs.handlers.MessagingService`, declared in the SDK's manifest. It shows Grovs pushes received in the foreground and forwards token refreshes. Extend it if your app needs its own messaging service, and remove the SDK's declaration with `tools:node="remove"`.

---

## In-app messages

See [In-app messages](https://docs.grovs.io/docs/sdk/android/in-app-messages). Every method here works before `configure` and keeps its effect across later `configure` calls.

### setInAppListener

Kind: method · Since 3.1

```kotlin
fun setInAppListener(listener: GrovsInAppListener?)
```

Receives in-app message events (shown, clicked, dismissed, answered, failed) and can stop a message. See [`GrovsInAppListener`](#grovsinapplistener).

- Held **strongly**. Pass `null` to release it.
- Messages show without it.

### pauseInAppMessages

Kind: method · Since 3.1

```kotlin
fun pauseInAppMessages()
```

Holds in-app messages back, during a checkout or video, say. The highest priority one that comes due waits.

### resumeInAppMessages

Kind: method · Since 3.1

```kotlin
fun resumeInAppMessages()
```

Lets messages show again, starting with the one that waited, if it still qualifies.

### discardInAppMessages

Kind: method · Since 3.1

```kotlin
@JvmOverloads
fun discardInAppMessages(dismissCurrent: Boolean = false)
```

Drops waiting and delayed messages and stays paused. With `dismissCurrent = true`, also closes the message on screen (reason `app`).

### setInAppExcludedScreens

Kind: method · Since 3.1

```kotlin
fun setInAppExcludedScreens(screens: List<String>)
```

Sets screens where no message shows. Messages wait until the user leaves.

- Use tracked screen names: from `trackScreenView`, or the name automatic tracking reports (after aliases).
- Case is ignored. Each call replaces the list.

### setInAppDebugLogging

Kind: method · Since 3.1

```kotlin
fun setInAppDebugLogging(enabled: Boolean)
```

Logs each campaign considered for an event and why it was skipped. Writes to Logcat at INFO under the tag `GrovsInApp`, whatever the [`setDebug`](#setdebug) level.

---

## Types

### DeeplinkDetails

Kind: class

```kotlin
class DeeplinkDetails(
    var link: String?,
    var data: Map<String, Object>?,
    var tracking: Map<String, Object>?
)
```

A resolved deep link, passed to [`GrovsDeeplinkListener`](#grovsdeeplinklistener).

| Name       | Type                   | Description                                             |
| ---------- | ---------------------- | ------------------------------------------------------- |
| `link`     | `String?`              | The link that opened the app, or `null` if unavailable. |
| `data`     | `Map<String, Object>?` | The custom payload attached to the link.                |
| `tracking` | `Map<String, Object>?` | Attribution and campaign metadata for the link.         |

### GrovsDeeplinkListener

Kind: interface

```kotlin
fun interface GrovsDeeplinkListener {
    fun onDeeplinkReceived(deeplinkDetails: DeeplinkDetails)
}
```

Passed to [`setOnDeeplinkReceivedListener`](#setondeeplinkreceivedlistener). A functional interface, so a Kotlin lambda works. Runs on the main thread.

### GrovsLinkGenerationListener

Kind: interface

```kotlin
fun interface GrovsLinkGenerationListener {
    fun onLinkGenerated(link: String?, error: GrovsException?)
}
```

Callback for [`generateLink`](#generatelink). Runs on the main thread, except not-configured and still-retrying errors arrive on the calling thread.

### GrovsLinkDetailsListener

Kind: interface

```kotlin
fun interface GrovsLinkDetailsListener {
    fun onLinkDetails(linkDetails: Map<String, Any>?, error: GrovsException?)
}
```

Callback for [`linkDetails`](#linkdetails). Same threading as `GrovsLinkGenerationListener`.

### GrovsInAppListener

Kind: interface · Since 3.1

```kotlin
interface GrovsInAppListener {
    fun shouldShowInAppMessage(campaignId: String): Boolean = true
    fun onInAppMessageShown(campaignId: String) {}
    fun onInAppMessageClicked(campaignId: String, buttonId: String?, payload: Map<String, Any?>?) {}
    fun onInAppMessageDismissed(campaignId: String, reason: String) {}
    fun onInAppMessageAnswered(campaignId: String, value: Any, comment: String?) {}
    fun onInAppMessageFailed(campaignId: String, message: String) {}
}
```

Passed to [`setInAppListener`](#setinapplistener). Every method has a default and runs on the **main thread**.

| Method                    | Called when                                                                                                                                                      |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `shouldShowInAppMessage`  | A message is about to show. Return `false` to stop it. It isn't counted as seen, and nothing else is shown for that event.                                       |
| `onInAppMessageShown`     | A message is on screen and its view was counted.                                                                                                                 |
| `onInAppMessageClicked`   | The user taps. `buttonId` is `null` for a tap on the message itself. `payload` is set only for a key-value action.                                               |
| `onInAppMessageDismissed` | A message closes without a click. See the reasons below.                                                                                                         |
| `onInAppMessageAnswered`  | An answered message has closed, in place of the dismissal. `value` is an `Int` for stars, the option's ID for a choice. `comment` is `null` unless one was sent. |
| `onInAppMessageFailed`    | A message couldn't be drawn, for example with no visible activity. It isn't counted and is tried again at its next trigger.                                      |

| Dismiss `reason` | Meaning                                                                                                      |
| ---------------- | ------------------------------------------------------------------------------------------------------------ |
| `close_button`   | The close button, the back gesture, or the alert's Close.                                                    |
| `backdrop`       | The user tapped outside the message.                                                                         |
| `swipe`          | The user swiped a banner away.                                                                               |
| `app`            | The SDK or your app closed it, for example with `discardInAppMessages(dismissCurrent = true)`.               |
| `orientation`    | The device turned to an orientation the campaign doesn't allow. Not counted as a dismissal in the dashboard. |

### GrovsInAppListenerAdapter

Kind: class · Since 3.1

```kotlin
open class GrovsInAppListenerAdapter : GrovsInAppListener
```

For Java. Kotlin interface defaults aren't Java defaults on the SDK's JVM target, so extend this and override only what you need.

### GrovsException

Kind: class

```kotlin
class GrovsException(message: String?) : Exception(message) {
    var errorCode: GrovsErrorCode?
}
```

Thrown by the coroutine forms of `generateLink` and `linkDetails`, and passed to the callback forms' listeners.

### GrovsErrorCode

Kind: enum

```kotlin
enum class GrovsErrorCode {
    LINK_GENERATION_ERROR,
    SDK_NOT_INITIALIZED,
    NOTIFICATIONS_ERROR,
    LINK_DETAILS_ERROR,
    EVENT_DISPATCH_ERROR
}
```

The category in [`GrovsException.errorCode`](#grovsexception).

### TrackingParams

Kind: class

```kotlin
class TrackingParams(
    val utmCampaign: String? = null,
    val utmSource: String? = null,
    val utmMedium: String? = null
)
```

UTM parameters for [`generateLink`](#generatelink).

### CustomRedirects

Kind: class

```kotlin
class CustomRedirects(
    val ios: CustomLinkRedirect? = null,
    val android: CustomLinkRedirect? = null,
    val desktop: CustomLinkRedirect? = null
)
```

Per-platform redirect overrides for [`generateLink`](#generatelink).

### CustomLinkRedirect

Kind: class

```kotlin
class CustomLinkRedirect(
    val link: String,
    val openAppIfInstalled: Boolean = true
)
```

One platform redirect. When `openAppIfInstalled` is `true`, the app opens if installed. Otherwise `link` is always used.

### PaymentEventType

Kind: enum

```kotlin
enum class PaymentEventType {
    BUY,
    CANCEL,
    REFUND
}
```

Used with [`logCustomPurchase`](#logcustompurchase).

### InstantCompat

Kind: class

```kotlin
data class InstantCompat(val epochMillis: Long)
```

A point in time that works on API 21, for `startDate` in [`logCustomPurchase`](#logcustompurchase).

| Factory                                | Creates                  |
| -------------------------------------- | ------------------------ |
| `InstantCompat.now()`                  | The current time.        |
| `InstantCompat.ofEpochMilli(millis)`   | From epoch milliseconds. |
| `InstantCompat.ofEpochSecond(seconds)` | From epoch seconds.      |
| `InstantCompat.parse(iso8601)`         | From an ISO 8601 string. |

### LogLevel

Kind: enum

```kotlin
enum class LogLevel {
    INFO,
    ERROR
}
```

Passed to [`setDebug`](#setdebug).

| Value   | Logs                                          |
| ------- | --------------------------------------------- |
| `INFO`  | Everything, including informational messages. |
| `ERROR` | Errors only (default).                        |

---

## Deprecated

The messages inbox was removed in 3.1. These members remain so existing code compiles, and show nothing. Use [in-app messages](#in-app-messages).

### displayMessagesFragment

Kind: method · Deprecated in 3.1

```kotlin
fun displayMessagesFragment(onDismissed: (() -> Unit)?)
```

Shows nothing. Calls `onDismissed` once, on the main thread.

### numberOfUnreadMessages

Kind: method · Deprecated in 3.1

```kotlin
suspend fun numberOfUnreadMessages(): Int?
fun numberOfUnreadMessages(lifecycleOwner: LifecycleOwner? = null, onResult: ((Int?) -> Unit)?)
```

Always yields `0`. The callback runs once on the main thread, and is skipped if `lifecycleOwner` is destroyed by then.

### setOnAutomaticNotificationsListener

Kind: method · Deprecated in 3.1

```kotlin
fun setOnAutomaticNotificationsListener(listener: GrovsNotificationsListener)
```

Does nothing. The listener is never called.

### GrovsNotificationsListener

Kind: interface · Deprecated in 3.1

```kotlin
fun interface GrovsNotificationsListener {
    fun onAutomaticNotificationClosed(isLast: Boolean)
}
```

Never called.

### handleGrovsNotification

Kind: method · Deprecated in 3.1

```kotlin
fun FirebaseMessagingService.handleGrovsNotification(message: RemoteMessage): Boolean
```

Same as [`GrovsMessaging.handleMessage(this, message)`](#grovsmessaging). Use that instead.
