Apply Android Agent
Prerequisites
Before installing the Android agent, check the following requirements.
- Android Min SDK 21 or higher
- Supported environments: Android 5.0 (API Level 21)+, Java 17+, Android Gradle Plugin 7.0 ~ 9.x, Gradle 7.0 ~ 8.x (Gradle 8.x is required when using AGP 9.x)
WhatapAgent Android SDK 2.3.0 is an SDK for monitoring the performance of Android applications. Applying the Gradle Plugin 2.2.2 together enables automatic collection without additional code.
Install Agent
To install the WhaTap mobile agent on Android, follow these steps.
- WhaTap mobile agent installation order: Gradle settings → SDK initialization → Builder options → Manifest settings → ProGuard settings → Supported collection items → Manual instrumentation → ScreenGroup settings
1. Gradle Settings
To install the agent, you need to modify your project's Gradle files. The configuration differs depending on whether the project uses Kotlin DSL or Groovy.
Kotlin DSL
plugins {
id("io.whatap.android") version "2.2.2" apply false
}
plugins {
id("com.android.application")
id("io.whatap.android")
}
dependencies {
implementation("io.whatap.android:whatap-android-agent:2.3.0")
}
Groovy
plugins {
id 'io.whatap.android' version '2.2.2' apply false
}
plugins {
id 'com.android.application'
id 'io.whatap.android'
}
dependencies {
implementation 'io.whatap.android:whatap-android-agent:2.3.0'
}
2. Local AAR File (closed network / internal network)
Place the distributed AAR file under app/libs/, and place the plugin JAR file, if needed, under libs/ or your internal Maven repository. If you don't use the Plugin JAR, call the manual instrumentation API to instrument the points you need.
Kotlin DSL (build.gradle.kts)
dependencies {
implementation(files("libs/whatap-android-agent-2.3.0.aar"))
}
Optional: Local Plugin JAR
buildscript {
dependencies {
classpath(files("libs/whatap-android-plugin-2.2.2.jar"))
}
}
Groovy
dependencies {
implementation files('libs/whatap-android-agent-2.3.0.aar')
}
3. SDK Initialization
To collect performance data from the Android application, you need to initialize the SDK. We recommend initializing it in the Application class.
Kotlin
import android.app.Application
import io.whatap.android.agent.WhatapAgent
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
WhatapAgent.Builder.newBuilder()
.setProjectKey("<YOUR_PROJECT_ACCESS_KEY>")
.setServerUrl("<YOUR_SERVER_URL>")
.setPCode(<YOUR_PCODE>)
.build(this)
}
}
Java
import android.app.Application;
import io.whatap.android.agent.WhatapAgent;
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
WhatapAgent.Builder.newBuilder()
.setProjectKey("<YOUR_PROJECT_ACCESS_KEY>")
.setServerUrl("<YOUR_SERVER_URL>")
.setPCode(<YOUR_PCODE>)
.build(this);
}
}
4. Builder Options
All Builder options are optional; if not specified, the default value is applied.
Transmission and buffer options
setFlushIntervalMs(long): 10,000 mssetMaxDiskBytes(int): 500 × 1024setMaxDiskFiles(int): 5setQueueSize(int): 1,000
Collection toggles
setCollectScreenLoading(boolean): truesetCollectNetwork(boolean): truesetCollectHeartbeat(boolean): true
HTTP connection options
setKeepAliveEnabled(boolean): truesetMaxConnections(int): 5setDisconnectAfterSend(boolean): false
ScreenGroup and user options
setScreenGroupDelaySeconds(int): 0 secondssetExcludeLifecycleEventsFromScreenGroup(boolean): truesetUserId(String),setSessionId(String),setSampling(double)
WhatapAgent.Builder.newBuilder()
.setFlushIntervalMs(60_000L)
.setMaxDiskBytes(2 * 1024 * 1024)
.setMaxDiskFiles(5)
.setQueueSize(1000)
.setKeepAliveEnabled(true)
.setMaxConnections(5)
.setDisconnectAfterSend(false)
.build(this)
Reducing traffic during low-usage periods: Heartbeat and resource samplers can be sent even while the app is in the background. If needed, you can turn off heartbeat collection or increase the flush interval to reduce the number of requests to the server.
WhatapAgent.Builder.newBuilder()
.setCollectHeartbeat(false)
.setFlushIntervalMs(60_000L)
.build(this)
5. Manifest Settings
You must configure the required permissions and the Application class in the AndroidManifest.xml file.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:name=".MyApplication"
...>
</application>
</manifest>
6. ProGuard Settings
# Activity/Fragment
-keep class * extends android.app.Activity
-keep class * extends androidx.fragment.app.Fragment
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
# WebView JavaScript Interface
-keepclassmembers class * {
@android.webkit.JavascriptInterface <methods>;
}
7. Supported Collection Items
- Activity/Fragment lifecycle and ScreenGroup
- Request/response information for supported network clients
- Resource usage, crashes, and ANR
- WebView page load and performance information
8. Manual Instrumentation
If you set setCollectNetwork(false), the network extension module is not initialized, so calls to wrap() and onRequest() will not work. Keep the default value of true for manual network instrumentation.
OkHttp3 / Retrofit
import io.whatap.android.agent.instrumentation.okhttp.OkHttp3Instrumentation
val client = OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.build()
val instrumentedClient = OkHttp3Instrumentation.wrap(client)
val retrofit = Retrofit.Builder()
.baseUrl("https://api.example.com/")
.client(instrumentedClient)
.build()
Volley
import io.whatap.android.agent.instrumentation.volley.VolleyInstrumentation
val queue = Volley.newRequestQueue(this)
val request = StringRequest(Request.Method.GET, url, listener, errorListener)
queue.add(request)
VolleyInstrumentation.onRequest(request)
HttpURLConnection
import io.whatap.android.agent.instrumentation.httpurlconnection.HttpUrlConnectionInstrumentation
val raw = URL(urlString).openConnection() as HttpURLConnection
val connection = HttpUrlConnectionInstrumentation.wrap(raw)
connection.requestMethod = "GET"
Apache HttpClient
Apache HttpClient is not automatically collected. To use DefaultHttpClient and HttpGet on Android 9 (API 28) or higher, you need to declare the use of org.apache.http.legacy or add an alternative dependency. If you cannot apply this prerequisite, use a supported network client instead.
import io.whatap.android.agent.instrumentation.httpclient.ApacheHttpClientInstrumentation
val client = DefaultHttpClient()
val instrumentedClient = ApacheHttpClientInstrumentation.wrap(client)
val request = HttpGet(url)
val response = instrumentedClient.execute(request)
StackSpan
import io.whatap.android.agent.instrumentation.stacktrace.CallStackTracer
val span = CallStackTracer.start("LoginService", "doLogin")
try {
doLogin()
span.end()
} catch (error: Exception) {
span.endWithError(error)
throw error
}
9. ScreenGroup Settings
Key change: The existing startGroup() / addTask() / endGroup() API has been replaced with startChain() / endChain(). For a flow that spans multiple Activities or Fragments, start it with startChain(), then call endChain() with the same taskId on the ending screen. If you omit taskId, it is generated automatically and can be retrieved with getCurrentChainTaskId().
Kotlin
import android.content.Intent
import io.whatap.android.agent.instrumentation.screengroup.ChainView
private const val EXTRA_CHAIN_TASK_ID = "whatap_chain_task_id"
class LoginActivity : AppCompatActivity() {
private fun continueToConfirmation() {
ChainView.getInstance().startChain("LoginFlow", null)
val taskId = ChainView.getInstance().getCurrentChainTaskId() ?: return
startActivity(Intent(this, ConfirmationActivity::class.java)
.putExtra(EXTRA_CHAIN_TASK_ID, taskId))
}
}
class ConfirmationActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
intent.getStringExtra(EXTRA_CHAIN_TASK_ID)?.let { taskId ->
ChainView.getInstance().endChain(taskId)
}
}
}
Chain state and auto-end wait time: You can check whether a chain is in progress with isChainActive(). For flows with a short gap between screens, increase the end-wait time to keep them in a single group.
val isChainActive = ChainView.getInstance().isChainActive()
WhatapAgent.Builder.newBuilder()
.setScreenGroupDelaySeconds(3)
.build(this)
Troubleshooting & Support
Troubleshooting
Desugaring-related error
If the error Dependency 'io.whatap.android:whatap-android-agent:2.3.0' requires core library desugaring to be enabled for :app. occurs, add the following configuration.
android {
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
isCoreLibraryDesugaringEnabled = true
}
}
dependencies {
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.0")
}
Plugin not found error
If a plugin not found error occurs, add the following configuration:
pluginManagement {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
Java version error
In case of Java version–related errors, check the following settings.
android {
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
}
Namespace warning
The Namespace 'io.whatap.android.agent' is used in multiple modules warning can be ignored. It indicates the library is used in multiple modules and does not affect app execution.
Build errors
- Verify that the Gradle version and Android Gradle Plugin version meet the requirements.
- Check network connectivity and configure a proxy if necessary.
- Try a Project Clean & Rebuild.
No data collected
- Check if the project access key is set correctly.
- Verify the internet permission is added in AndroidManifest.xml.
- Ensure SDK initialization in the Application class.
- Check for proxy/firewall settings blocking data transfer.
Support
When requesting technical support, providing the following information can lead to a faster resolution.
- Project access key
- Android SDK version
- Gradle version and Android Gradle Plugin version
- Full error log
- build.gradle file contents
- Steps to reproduce the issue