Android Agent
Overview
The NetFUNNEL Android agent is a dedicated client that communicates with the NetFUNNEL server from mobile applications. Users can apply a virtual waiting room by applying and implementing the various functions provided by the agent in their client application code.
Minimum Requirements
- Android API Level 22 (Lollipop 5.1) or higher
- Java 1.8 or higher
- Kotlin 2.0.0-RC1 or higher
External Dependencies
- Ktor (3.0.0 or higher)
- Kotlinx Serialization (any version)
Agent Operation Flow
Before Waiting
- Before waiting, configuration is initialized. This process involves fetching configuration from the NetFUNNEL server and initializing objects based on that information.
- Use the "initialization function" to initialize NetFUNNEL configuration.
While Waiting
- This is the process of displaying the virtual waiting room and applying traffic waiting on the screen (Activity or Fragment) where you want it.
- Use the "wait start function" to apply the virtual waiting room.
After Waiting
- This is the process of handling situations after waiting ends. Situations where an end-user's wait ends are:
- Entry success after waiting
- Entry failure due to server or network error during waiting
- End-user cancels waiting during wait
- Use the "callback function" and "wait stop function" to implement logic after waiting ends.
Agent Installation
This guide is written for the Android Studio environment.
The NetFUNNEL Android agent is provided in .aar (Android Archive) format. Add the .aar file to your Android project and register the dependency through Gradle configuration.
Agent Download
Download the NetFUNNEL Android agent from the agent tab in the NetFUNNEL Console.
Add .aar File
Copy the provided .aar file to the app/libs directory of your project.
Project root/
├── app/
| └── libs/
| └── netfunnel-android-agent-release-{{latest}}.aar
| └── netfunnel-android-agent-debug-{{latest}}.aar
└── gradle/
Gradle Configuration
Add Agent Dependency
Add the dependency to the build.gradle file as follows so that the .aar file is recognized.
Kotlin DSL (build.gradle.kts)
dependencies {
implementation(files("libs/netfunnel-android-agent-release-{{latest}}.aar"))
...
}
Groovy DSL (build.gradle)
dependencies {
implementation files("libs/netfunnel-android-agent-release-{{latest}}.aar")
...
}
The NetFUNNEL Android agent provides two files depending on the build environment. Use debug for debugging and release for app distribution.
Add External Libraries
The NetFUNNEL Android agent does not include external libraries. Add the following libraries to your project.
- Ktor: Network communication library (3.0.0 or higher)
- Kotlinx Serialization: Serialization library (any version)
Kotlin DSL (build.gradle.kts)
dependencies {
val ktorVersion = "{{KTOR_VERSION}}"
val serializationVersion = "{{SERIALIZATION_VERSION}}"
// Ktor dependencies
implementation("io.ktor:ktor-client-core:$ktorVersion")
implementation("io.ktor:ktor-client-okhttp:$ktorVersion")
implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion")
implementation("io.ktor:ktor-serialization-gson:$ktorVersion")
// Serialization dependency
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$serializationVersion")
...
}
Groovy DSL (build.gradle)
ext {
ktorVersion = "{{KTOR_VERSION}}"
serializationVersion = "{{SERIALIZATION_VERSION}}"
}
dependencies {
// Ktor dependencies
implementation "io.ktor:ktor-client-core:$ktorVersion"
implementation "io.ktor:ktor-client-okhttp:$ktorVersion"
implementation "io.ktor:ktor-client-content-negotiation:$ktorVersion"
implementation "io.ktor:ktor-serialization-gson:$ktorVersion"
// Serialization dependency
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:$serializationVersion"
...
}
Manifest Configuration
Internet permission must be added to communicate with the NetFUNNEL server. Allow internet access in the AndroidManifest.xml file.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<!-- Internet permission -->
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
Agent Initialization
The NetFUNNEL Android agent must be initialized when the app starts.
Perform initialization in the Application class's onCreate() so that it runs only once at app startup.
Kotlin
Netfunnel.initialize(
clientId = "{{CLIENT_ID}}",
serverUrl = "{{SERVER_URL}}",
errorUrl = "{{ERROR_URL}}",
networkTimeout = 3000,
retryCount = 0,
printLog = false,
errorBypass = false,
useNetfunnelTemplate = true,
userId = "{{USER_ID}}",
useNetworkRecoveyMode = true,
healthCheckUrl = "{{HEALTH_CHECK_URL}}",
statusBarStyle = null
)
Java
Netfunnel.INSTANCE.initialize(
"{{CLIENT_ID}}",
"{{SERVER_URL}}",
"{{ERROR_URL}}",
3000,
0,
false,
false,
true,
"{{USER_ID}}",
true,
"{{HEALTH_CHECK_URL}}",
null
);
| Parameter | Type | Description | Required | Condition |
|---|---|---|---|---|
| clientId | String | User unique identifier | O | Cannot be empty string |
| serverUrl | String | NetFUNNEL server address | X | None (use default address) |
| errorUrl | String | HTML address of NetFUNNEL error page | X | None (use default address) |
| networkTimeout | Long | Maximum time to wait for network response | X | Default (ms): 3,000 Max (ms): 10,000 Min (ms): 100 |
| retryCount | Int | Number of retries on network request failure | X | Default (times): 0 Max (times): 10 Min (times): 0 |
| printLog | Boolean | Whether to print logs for debugging | X | Default: false |
| errorBypass | Boolean | Whether to bypass on error | X | Default: false |
| useNetfunnelTemplate | Boolean | Whether to use NetFUNNEL waiting room customized in Console | X | Default: true |
| userId | String | End-user unique identifier for blacklist/whitelist check | X | Default: null |
| useNetworkRecoveryMode | Boolean | Whether to use waiting room retention and reconnection on network disconnect | X | Default: false |
| healthCheckUrl | String | Health check URL to distinguish network delay from NetFUNNEL server failure | X | Default: null |
| statusBarStyle | String | Status bar transparency option for NetFUNNEL waiting room (WebView) | X | Default: null |
Agent Application
You can apply the waiting room to specific screens using the functions provided by the NetFUNNEL Android agent.
Project Key and Segment Key used in the start and stop functions can be found in the Console's project tab.
Callback Functions
To use the NetFUNNEL Android agent, you must inject callback functions into the start and stop functions.
The waiting room can end in various situations (wait success, cancel, block, error, network error, etc.), and handling for each situation can be implemented through callback functions.
| abstract class | abstract function | Required |
|---|---|---|
| NetfunnelCallback | onSuccess | Required |
| NetfunnelCallback | onError | Required |
| NetfunnelCallback | onNetworkError | Required |
| NetfunnelCallback | onBlock | Optional |
| NetfunnelCallback | onClose | Optional |
| NetfunnelCallback | onContinue | Optional |
| NetfunnelCompleteCallback | onComplete | Optional |
Start Callback - NetfunnelCallback
| Callback | Status Code | Scenario |
|---|---|---|
| onSuccess | 200 | Passed queue normally; service access allowed |
| onSuccess | 300 | Subscription or license expired Console project/segment deactivated Agent errorBypass=true and error occurred |
| onSuccess | 303 | Request with IP or ID registered on Console whitelist (admin bypass) |
| onError | 500 | Start function called without agent initialization Non-existent project/segment key in start function Segment deleted in Console Response partially missing due to server error |
| onNetworkError | 1001 | Network connection blocked (Wi-Fi, cellular data blocked) |
| onNetworkError | 1002 | Network timeout Invalid HTML URL received due to server error No response due to server down (502, etc.) |
| onBlock | 301 | Console segment block (voluntary entry block) |
| onBlock | 302 | Request with IP or ID on Console blacklist (admin block) Console BotManager Basic enabled (malicious entry block) |
| onClose | 495 | Post-wating room close button or back button pressed |
| onClose | 496 | Pre-waiting room close button or back button pressed |
| onClose | 497 | Macro block room close button or back button pressed |
| onClose | 498 | Block Room close button or back button pressed |
| onClose | 499 | Waiting Room cancel button or back button pressed |
| onContinue | 201 | Agent useNetfunnelTemplate=false and default wait |
Kotlin
import com.nf4.NetfunnelCallback
class StartCallback {
companion object {
private const val TAG = "NetFUNNEL"
}
private val callback = object : NetfunnelCallback() {
override fun onSuccess(statusCode: Int, message: String) {
Log.d(TAG, "onSuccess $statusCode $message")
/**
* Logic to run when queue is passed
* ex - service screen entry
*/
}
override fun onError(statusCode: Int, message: String) {
Log.d(TAG, "onError $statusCode $message")
/**
* Logic to run on error
* ex - show error message to user or bypass
*/
}
override fun onNetworkError(statusCode: Int, message: String) {
Log.d(TAG, "onNetworkError $statusCode $message")
/**
* Logic to run on network error
* ex - guide to reconnect or navigate to retry screen
*/
}
override fun onBlock(statusCode: Int, message: String) {
Log.d(TAG, "onBlock $statusCode $message")
/**
* Logic when user entry is blocked
* ex - show access denied message
*/
}
override fun onClose(statusCode: Int, message: String) {
Log.d(TAG, "onClose $statusCode $message")
/**
* Logic when user cancels wait or presses back (WebView closes and returns to previous screen)
* ex - show exit Toast
*/
}
override fun onContinue(statusCode: Int, message: String, aheadWait: Int, behindWait: Int, waitTime: String, progressRate: Int) {
Log.d(TAG, "onContinue $statusCode $message")
/**
* UI update logic while waiting (only when using custom waiting room)
* ex - update custom waiting screen with real-time wait info
*/
}
}
fun getCallback(): NetfunnelCallback = callback
}
Java
import com.nf4.NetfunnelCallback;
public class StartCallback{
private static final String TAG = "NetFUNNEL";
private final NetfunnelCallback callback = new NetfunnelCallback() {
@Override
public void onSuccess(int statusCode, @NonNull String message) {
Log.d(TAG, "onSuccess " + statusCode + " " + message);
/**
* Logic to run when queue is passed
* ex - service screen entry
*/
}
@Override
public void onError(int statusCode, @NonNull String message) {
Log.d(TAG, "onError " + statusCode + " " + message);
/**
* Logic to run on error
* ex - show error message to user or bypass
*/
}
@Override
public void onNetworkError(int statusCode, @NonNull String message) {
Log.d(TAG, "onNetworkError " + statusCode + " " + message);
/**
* Logic to run on network error
* ex - guide to reconnect or navigate to retry screen
*/
}
@Override
public void onBlock(int statusCode, @NonNull String message) {
Log.d(TAG, "onBlock " + statusCode + " " + message);
/**
* Logic when user entry is blocked
* ex - show access denied message
*/
}
@Override
public void onClose(int statusCode, @NonNull String message) {
Log.d(TAG, "onClose " + statusCode + " " + message);
/**
* Logic when user cancels wait (WebView closes and returns to previous screen)
* ex - show exit Toast
*/
}
@Override
public void onContinue(int statusCode, @NonNull String message, int aheadWait, int behindWait, @NonNull String waitTime, int progressRate) {
Log.d(TAG, "onContinue " + statusCode + " " + message);
/**
* UI update logic while waiting (only when using custom waiting room)
* ex - update custom waiting screen with real-time wait info
*/
}
};
public NetfunnelCallback getCallback() {
return callback;
}
}
Stop Callback - NetfunnelCompleteCallback
| Callback | Status Code | Scenario |
|---|---|---|
| onComplete | 200 | Entry key successfully returned to server after wait |
| onComplete | 500 | Entry key return to server failed after wait |
Kotlin
import com.nf4.NetfunnelCompleteCallback
class StopCallback {
companion object {
private const val TAG = "NetFUNNEL"
}
private val callback = object : NetfunnelCompleteCallback() {
override fun onComplete(statusCode: Int, message: String) {
Log.d(TAG, "onComplete $statusCode $message")
/**
* Logic for entry key return result
* ex - navigate to next page on successful key return
*/
}
}
fun getCallback(): NetfunnelCompleteCallback = callback
}
Java
import com.nf4.NetfunnelCompleteCallback;
public class StopCallback {
private static final String TAG = "NetFUNNEL";
private final NetfunnelCompleteCallback callback = new NetfunnelCompleteCallback() {
@Override
public void onComplete(int statusCode, @NonNull String message) {
Log.d(TAG, "onComplete " + statusCode + " " + message);
/**
* Logic for entry key return result
* ex - navigate to next page on successful key return
*/
}
};
public NetfunnelCompleteCallback getCallback() {
return callback;
}
}
Basic Control
Start Function
To apply the waiting room on a specific screen (Activity or Fragment), use the "wait start function" to show the virtual waiting room. Basic Control is useful for applying wait when an end-user enters a specific screen to manage server load and end-user experience.
Kotlin
Netfunnel.nfStart("{{PROJECT_KEY}}", "{{SEGMENT_KEY}}", callback, activity)
Java
Netfunnel.INSTANCE.nfStart("{{PROJECT_KEY}}", "{{SEGMENT_KEY}}", callback, activity);
| Parameter | Type | Description | Required |
|---|---|---|---|
| projectKey | String | Console Basic Control project key | O |
| segmentKey | String | Console Basic Control segment key | O |
| callback | NetfunnelCallback | User-defined callback for waiting room events | O |
| activity | Activity | Screen where waiting room is applied | O |
Stop Function
When Basic Control wait completes successfully, you must implement the following:
- Code to enter the service after wait (code to enter the target page)
- Code that calls the "wait stop function" after business logic to return the service entry key to the NetFUNNEL server
Kotlin
Netfunnel.nfStop("{{PROJECT_KEY}}", "{{SEGMENT_KEY}}", completeCallback)
Java
Netfunnel.INSTANCE.nfStop("{{PROJECT_KEY}}", "{{SEGMENT_KEY}}", completeCallback);
| Parameter | Type | Description | Required |
|---|---|---|---|
| projectKey | String | Project key used in wait start function | O |
| segmentKey | String | Segment key used in wait start function | O |
| completeCallback | NetfunnelCompleteCallback | User-defined callback for key return after wait | O |
Section Control
Start Function
Section Control applies a waiting state between entry and exit of a specific page. With Section Control, users can maintain a smooth flow in a specific section of the page.
- After entering an event page, purchasing a product, and clicking the payment complete button
- From end-user login until logout
To start Section Control, use the "section start function" to define the start of the control section. This keeps the waiting state in that section's flow.
Kotlin
Netfunnel.nfStartSection("{{PROJECT_KEY}}", "{{SEGMENT_KEY}}", callback, activity)
Java
Netfunnel.INSTANCE.nfStartSection("{{PROJECT_KEY}}", "{{SEGMENT_KEY}}", callback, activity);
| Parameter | Type | Description | Required |
|---|---|---|---|
| projectKey | String | Console Section Control project key | O |
| segmentKey | String | Console Section Control segment key | O |
| callback | NetfunnelCallback | User-defined callback for waiting room events | O |
| activity | Activity | Screen where waiting room is applied | O |
Stop Function
When Section Control wait completes successfully, you can implement:
- Code to enter the service after wait (code to enter the target page)
To end Section Control, use the "section stop function" to define the end of the section. This ends the end-user's section control and allows the next end-user to enter.
Kotlin
Netfunnel.nfStopSection("{{PROJECT_KEY}}", "{{SEGMENT_KEY}}", completeCallback)
Java
Netfunnel.INSTANCE.nfStopSection("{{PROJECT_KEY}}", "{{SEGMENT_KEY}}", completeCallback);
| Parameter | Type | Description | Required |
|---|---|---|---|
| projectKey | String | Project key used in wait start function | O |
| segmentKey | String | Segment key used in wait start function | O |
| completeCallback | NetfunnelCompleteCallback | User-defined callback for key return after wait | O |