Perkox Android SDK: Complete Offerwall Integration Guide for Kotlin Developers (2026)
Kotlin Java Updated Aug 2026
perkox android sdk integration doesn’t have to be complicated. If you’re building an Android app and want to monetize with an offerwall, the Perkox Android SDK gives you a production-ready, drop-in solution that handles offer display, user tracking, and reward callbacks in a few lines of code. This guide walks through everything from installation through server-side reward validation — the complete android offerwall integration workflow for 2026.
Whether you’re building a rewards app, a gaming platform with virtual currency, or any app where users earn value by completing tasks, the offerwall android sdk from Perkox is designed to be integrated in under 15 minutes for the basic flow, with a robust server-side validation path for production-grade security.
1. What the Perkox Android SDK Does
The Perkox Android SDK is a lightweight monetization library that embeds an offerwall directly into your Android application. An offerwall is essentially a curated catalog of rewarded offers — surveys, app installs, video ads, sign-ups, and other tasks — that users can complete in exchange for in-app rewards or virtual currency. Every time a user completes an offer, the advertiser pays Perkox, and you as the publisher receive a share of that revenue.
Instead of building your own offer catalog, negotiating with advertisers, implementing tracking pixels, and building fraud detection systems, the SDK handles all of that behind a clean API surface:
PerkoxOfferwall.create()— Initializes the SDK with your credentials and returns anOfferwallinstance.offerwall.launch(activity)— Displays the offerwall UI as an overlay on top of your activity.offerwall.onReward— Callback fired when a reward event occurs, delivering a map of reward data to your app.offerwall.onClose— Callback fired when the user dismisses the offerwall, so you can resume your app’s flow.
The SDK package is com.perkoxofferwall.sdk.PerkoxOfferwall, and it’s distributed as an AAR (Android Archive) file that you drop into your project. No complex dependency chains, no multi-module Gradle setup — just the AAR and a few lines of Gradle configuration.
For a broader understanding of how offerwalls work and why they’re one of the highest-CPM monetization strategies for mobile apps, check out our deep dive: What is an Offerwall? A Complete Guide for App Developers.
2. Prerequisites
Before you begin the android offerwall integration, make sure your development environment and project meet these requirements:
| Requirement | Minimum Version | Notes |
|---|---|---|
| Android minSdk | 21 (Android 5.0 Lollipop) | Covers 99%+ of active Android devices |
| targetSdk | 33 (Android 13) or higher | Required for Google Play compliance |
| Java | 17 | Use JDK 17 for Gradle compilation |
| Kotlin | 1.9+ | SDK is Kotlin-first; Java interop fully supported |
| AndroidX | Required | Migrate from Support Library if needed |
| Perkox Account | Active publisher account | Get appId and sdkKey from dashboard |
| Gradle | 7.0+ | AGP 7.0+ recommended |
Check Your Kotlin and Java Versions
Verify your project’s Kotlin plugin version in your root-level build.gradle or build.gradle.kts:
// build.gradle.kts (project-level)
plugins {
id("com.android.application") version "8.2.0" apply false
id("org.jetbrains.kotlin.android") version "1.9.22" apply false
}
Ensure you’re compiling with Java 17 by setting the JAVA_HOME environment variable or configuring it in Android Studio under Settings → Build, Execution, Deployment → Build Tools → Gradle → Gradle JDK.
3. Installation
The Perkox Android SDK is distributed as an AAR file. Installation is straightforward: download the AAR, place it in your project’s libs/ directory, and configure Gradle to include it as a dependency.
Step 1: Download the AAR
Download the latest Perkox Android SDK AAR file from the official Perkox documentation or directly from your publisher dashboard. The file will be named something like perkox-offerwall-sdk-1.x.x.aar.
Step 2: Place the AAR in Your Project
Move the downloaded AAR file into your app module’s libs/ directory:
your-project/
├── app/
│ ├── libs/
│ │ └── perkox-offerwall-sdk-1.x.x.aar ← place it here
│ ├── src/
│ │ └── main/
│ │ ├── java/
│ │ └── res/
│ └── build.gradle (or build.gradle.kts)
├── build.gradle (project-level)
└── settings.gradle
Step 3: Configure Gradle
Add the AAR as a flat-file repository and dependency in your app-level build.gradle. Below are examples for both Groovy DSL and Kotlin DSL.
Groovy DSL (build.gradle)
// app/build.gradle
android {
compileSdk 33
defaultConfig {
applicationId "com.yourcompany.yourapp"
minSdk 21
targetSdk 33
versionCode 1
versionName "1.0"
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = '17'
}
}
repositories {
flatDir {
dirs 'libs'
}
}
dependencies {
implementation(name:'perkox-offerwall-sdk-1.x.x', ext:'aar')
// Required dependencies for the SDK
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.webkit:webkit:1.8.0'
implementation 'com.google.android.material:material:1.11.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3'
}
Kotlin DSL (build.gradle.kts)
// app/build.gradle.kts
android {
compileSdk = 33
defaultConfig {
applicationId = "com.yourcompany.yourapp"
minSdk = 21
targetSdk = 33
versionCode = 1
versionName = "1.0"
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
}
}
repositories {
flatDir {
dirs("libs")
}
}
dependencies {
implementation(files("libs/perkox-offerwall-sdk-1.x.x.aar"))
// Required dependencies for the SDK
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("androidx.webkit:webkit:1.8.0")
implementation("com.google.android.material:material:1.11.0")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
}
Step 4: Add Internet Permission
The SDK needs network access to fetch offers and communicate with Perkox servers. Add the permission to your AndroidManifest.xml:
<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:label="MyApp"
android:usesCleartextTraffic="false">
<!-- Your activities -->
</application>
</manifest>
./gradlew sync from the command line. The com.perkoxofferwall.sdk.PerkoxOfferwall package should now be resolvable in your code.
4. Quick Start — Kotlin Implementation
Now for the exciting part. Here’s a complete, minimal Kotlin implementation that initializes the SDK, shows the offerwall, and handles reward and close events. This is the fastest way to get a working perkox android sdk integration.
import android.os.Bundle
import android.widget.Button
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.perkoxofferwall.sdk.PerkoxOfferwall
import com.perkoxofferwall.sdk.Offerwall
class MainActivity : AppCompatActivity() {
private lateinit var offerwall: Offerwall
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Step 1: Initialize the SDK with your credentials
// Get these values from your Perkox publisher dashboard
val appId = "YOUR_APP_ID"
val sdkKey = "YOUR_SDK_KEY"
val playerId = "user_12345" // Unique user identifier
offerwall = PerkoxOfferwall.create(
appId = appId,
sdkKey = sdkKey,
playerId = playerId
)
// Step 2: Set up event callbacks
offerwall.onReward = { rewardData ->
// This callback fires when a reward event occurs
val amount = rewardData["amount"]
val status = rewardData["status"]
val txid = rewardData["txid"]
val rewardedPlayerId = rewardData["player_id"]
runOnUiThread {
Toast.makeText(
this,
"Reward earned: $amount (Status: $status)",
Toast.LENGTH_LONG
).show()
}
}
offerwall.onClose = {
// This callback fires when the user closes the offerwall
runOnUiThread {
Toast.makeText(
this,
"Offerwall closed",
Toast.LENGTH_SHORT
).show()
}
}
// Step 3: Launch the offerwall when the user taps a button
val earnButton = Button(this).apply {
text = "Earn Rewards"
setOnClickListener {
offerwall.launch(this@MainActivity)
}
}
setContentView(earnButton)
}
}
That’s the complete minimal flow. Let’s break down what’s happening:
PerkoxOfferwall.create(appId, sdkKey, playerId)— This initializes the SDK with your publisher credentials and the unique identifier for the current user. It returns anOfferwallinstance that you hold as a reference.offerwall.onReward = { ... }— Assigns a lambda that fires whenever a reward event is triggered. The callback receives aMap<String, Any?>containingamount,status,txid, andplayer_id.offerwall.onClose = { ... }— Assigns a lambda that fires when the user dismisses the offerwall overlay.offerwall.launch(activity)— Displays the offerwall UI on top of the provided activity. This is a full-screen overlay that users interact with to browse and complete offers.
onReward callback is for UX purposes only — showing a toast, updating a balance display, playing a sound. Do not credit users based on client-side callbacks. See Section 7 for why server-side validation is mandatory.
5. Java Implementation
The SDK is fully interoperable with Java. If your project is Java-based or you’re integrating into a legacy codebase, here’s the equivalent implementation in Java:
import android.os.Bundle;
import android.widget.Button;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.perkoxofferwall.sdk.PerkoxOfferwall;
import com.perkoxofferwall.sdk.Offerwall;
import java.util.Map;
public class MainActivity extends AppCompatActivity {
private Offerwall offerwall;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Step 1: Initialize the SDK
String appId = "YOUR_APP_ID";
String sdkKey = "YOUR_SDK_KEY";
String playerId = "user_12345";
offerwall = PerkoxOfferwall.create(appId, sdkKey, playerId);
// Step 2: Set up the onReward callback
offerwall.setOnReward((rewardData) -> {
Object amount = rewardData.get("amount");
Object status = rewardData.get("status");
Object txid = rewardData.get("txid");
Object rewardedPlayerId = rewardData.get("player_id");
runOnUiThread(() -> {
Toast.makeText(
this,
"Reward earned: " + amount + " (Status: " + status + ")",
Toast.LENGTH_LONG
).show();
});
return null;
});
// Step 3: Set up the onClose callback
offerwall.setOnClose(() -> {
runOnUiThread(() -> {
Toast.makeText(
this,
"Offerwall closed",
Toast.LENGTH_SHORT
).show();
});
return null;
});
// Step 4: Launch the offerwall
Button earnButton = new Button(this);
earnButton.setText("Earn Rewards");
earnButton.setOnClickListener(v -> {
offerwall.launch(MainActivity.this);
});
setContentView(earnButton);
}
}
The Java API mirrors the Kotlin API exactly. The only difference is that in Java, you use setOnReward() and setOnClose() setter methods instead of property assignment, and the callbacks return null (Unit) to satisfy Kotlin’s functional type signature.
6. Event Handling — onReward and onClose Callbacks
Event handling is where you connect the offerwall to your app’s user experience. The SDK exposes two primary callbacks that you should implement for a polished integration.
onReward Callback
The onReward callback fires when a reward event is triggered — typically when a user completes an offer and the Perkox server confirms the conversion. The callback receives a Map<String, Any?> with the following keys:
| Key | Type | Description |
|---|---|---|
amount |
Double / Number | The reward amount in your configured currency |
status |
String | The reward status (e.g., “completed”, “pending”) |
txid |
String | Unique transaction ID for this reward event |
player_id |
String | The player ID associated with this reward |
Here’s a more detailed implementation that handles all fields and includes null safety:
offerwall.onReward = { rewardData ->
val amount = rewardData["amount"] as? Number ?: 0
val status = rewardData["status"] as? String ?: "unknown"
val txid = rewardData["txid"] as? String ?: ""
val rewardedPlayerId = rewardData["player_id"] as? String ?: ""
runOnUiThread {
// Update the user's balance display
updateBalanceDisplay(amount.toDouble())
// Show a celebratory notification
showRewardNotification(amount.toDouble(), txid)
}
}
onClose Callback
The onClose callback fires when the user dismisses the offerwall overlay, either by pressing the back button or tapping the close button. Use this to resume your app’s normal flow — for example, refreshing the user’s balance or returning to a previous screen.
offerwall.onClose = {
runOnUiThread {
// Refresh the user's balance from your server
refreshUserBalance()
// Navigate back to the main screen
showMainScreen()
}
}
runOnUiThread { ... } inside callbacks. The SDK may invoke callbacks from background threads, and Android requires all UI manipulations to happen on the main thread.
7. Server-Side Reward Validation
This is the most critical section of this entire guide. If you only read one section, read this one.
onReward callbacks are not secure and must never be used as the source of truth for crediting users. A determined attacker can spoof callbacks, replay them, or intercept and modify the data before it reaches your app. Always use server-side postback validation for actual reward crediting.
Why Client-Side Callbacks Are Not Enough
Here’s the fundamental problem: when onReward fires in your app, the data it delivers has traveled through the user’s device. This means:
- Spoofing: An attacker can hook the SDK method and inject fake reward data with arbitrary amounts.
- Replay attacks: A legitimate callback can be captured and replayed multiple times to multiply the reward.
- Tampering: The
amountfield in the callback map can be modified before your app processes it. - Network manipulation: Man-in-the-middle attacks can alter data in transit.
None of these attacks are possible with server-side postbacks, because the postback goes directly from Perkox’s servers to your backend — the user’s device is never in the path.
Postback URL Setup
A postback is an HTTP request that Perkox sends to your server whenever a reward event occurs. You configure the postback URL in your Perkox publisher dashboard, and Perkox calls it with the reward data as URL parameters.
Here’s the postback URL format:
https://yourdomain.com/postback?offer_id={offer_id}&payout={payout}&status={status}&player_id={player_id}&reward_amount={reward_amount}
Postback Parameters
Perkox populates the following parameters in the postback URL:
| Parameter | Description | Example |
|---|---|---|
{offer_id} |
Unique identifier of the completed offer | offer_98472 |
{payout} |
The payout amount (what you earn as publisher) | 1.50 |
{status} |
Reward status: completed, pending, reversed | completed |
{event} |
The type of event that triggered the postback | conversion |
{player_id} |
The player ID you passed during SDK initialization | user_12345 |
{reward_amount} |
The reward amount credited to the user | 120.0 |
{click_id} |
Unique click/tracking ID for attribution | clk_a8f3k2 |
{country} |
ISO country code of the user | US |
{device_type} |
The user’s device type | android |
Example Server-Side Postback Handler (Node.js)
const express = require('express');
const app = express();
app.get('/postback', (req, res) => {
const {
offer_id,
payout,
status,
event,
player_id,
reward_amount,
click_id,
country,
device_type
} = req.query;
// 1. Validate the request (check IP, signature, or secret token)
if (!isValidPostback(req)) {
return res.status(403).send('Forbidden');
}
// 2. Only process completed rewards
if (status !== 'completed') {
return res.status(200).send('OK');
}
// 3. Check for duplicate transactions (idempotency)
const existing = await db.findTransaction(click_id);
if (existing) {
return res.status(200).send('Already processed');
}
// 4. Credit the user's account
await db.creditUser(player_id, parseFloat(reward_amount), {
offer_id,
click_id,
payout: parseFloat(payout),
country,
device_type
});
// 5. Respond with 200 OK so Perkox knows the postback was received
res.status(200).send('OK');
});
app.listen(3000);
Postback Security Best Practices
- Validate the source IP: Only accept postbacks from Perkox’s known IP ranges (listed in your dashboard).
- Use a secret token: Add a secret parameter to your postback URL that only your server and Perkox know.
- Implement idempotency: Store
click_idand check for duplicates before crediting. Network retries can cause the same postback to arrive multiple times. - Always return HTTP 200: If your server returns a non-200 status, Perkox will retry the postback. Always return 200 once you’ve received and queued the data, even if processing is async.
- Use HTTPS: Never use HTTP for your postback endpoint.
For a comprehensive deep dive into postback configuration, security, and debugging, read our Complete Offerwall Postback Guide. For broader SDK security practices, see Offerwall SDK Security Best Practices.
8. Configuration
The SDK is configured at initialization time through PerkoxOfferwall.create(). Here’s a detailed breakdown of each configuration parameter:
appId
Your application identifier, obtained from the Perkox publisher dashboard. This uniquely identifies your app within the Perkox ecosystem. Each app you register gets its own appId. Do not hardcode another app’s appId — this will route your revenue to the wrong account.
val appId = "px_app_a1b2c3d4e5" // From dashboard → App Settings
sdkKey
Your SDK key is a secret credential that authenticates the SDK when communicating with Perkox servers. Treat this like an API key — do not commit it to public repositories or share it publicly. While the SDK key alone isn’t sufficient to credit users (that requires server-side validation), exposing it can lead to abuse.
val sdkKey = "px_sdk_key_f8g9h0i1j2k3l4" // From dashboard → SDK Settings
playerId
The playerId is the unique identifier for the current user in your system. This is critical — it’s how Perkox attributes completed offers to the correct user and how your server knows which user to credit when a postback arrives. The playerId you pass during SDK initialization will appear in the postback as the {player_id} parameter.
// Use your app's internal user ID, a UUID, or whatever
// unique identifier you use for the logged-in user
val playerId = "user_12345"
// Or retrieve from your auth system
val playerId = getCurrentUser().id
playerId must be set before calling offerwall.launch(). If the user logs out or switches accounts, you must re-create the offerwall instance with the new playerId.
Full Configuration Example
val offerwall = PerkoxOfferwall.create(
appId = "px_app_a1b2c3d4e5",
sdkKey = "px_sdk_key_f8g9h0i1j2k3l4",
playerId = "user_12345"
)
// Optionally configure callbacks before launching
offerwall.onReward = { data ->
handleRewardClientSide(data)
}
offerwall.onClose = {
handleOfferwallClose()
}
// Launch when ready
offerwall.launch(this)
9. Testing and Sandbox Mode
Before shipping your integration to production, you need to test the entire flow — from SDK initialization through offer completion to postback receipt and user crediting. Perkox provides a sandbox mode for exactly this purpose.
Enabling Sandbox Mode
In your Perkox publisher dashboard, you’ll find separate credentials for sandbox and production environments. Sandbox credentials display test offers that don’t generate real revenue, and postbacks are sent to your configured sandbox postback URL.
// Sandbox configuration — use sandbox credentials from dashboard
val offerwall = PerkoxOfferwall.create(
appId = "px_app_sandbox_test", // Sandbox appId
sdkKey = "px_sdk_key_sandbox_test", // Sandbox sdkKey
playerId = "test_user_001" // Test player ID
)
Testing Checklist
Run through this checklist before going live:
- SDK initializes without errors — No exceptions thrown after
PerkoxOfferwall.create() - Offerwall displays —
offerwall.launch(activity)shows the offerwall overlay with test offers - Test offer completion — Complete a test offer and verify the
onRewardcallback fires - Postback received — Check your server logs for the postback HTTP request
- User credited — Verify your server correctly processes the postback and credits the test user
- onClose works — Close the offerwall and verify the callback fires and your UI resumes correctly
- Idempotency check — Trigger a duplicate postback and verify your server doesn’t double-credit
- Error handling — Test with invalid credentials and verify graceful error handling
Switching to Production
Once you’ve verified the full flow in sandbox, switch to your production credentials:
// Production configuration
val offerwall = PerkoxOfferwall.create(
appId = "px_app_a1b2c3d4e5", // Production appId
sdkKey = "px_sdk_key_f8g9h0i1j2k3l4", // Production sdkKey
playerId = getCurrentUser().id // Real user ID
)
10. Common Issues and Troubleshooting
Here are the most common issues developers encounter during android offerwall integration and how to resolve them:
1. “Unresolved reference: PerkoxOfferwall”
Cause: The AAR file isn’t properly included in your Gradle dependencies, or the Gradle project hasn’t been synced.
Solution: Verify the AAR file exists in app/libs/, check your flatDir repository configuration, and run a Gradle sync. Clean and rebuild: ./gradlew clean build.
2. “Failed to resolve: perkox-offerwall-sdk”
Cause: The AAR filename in your Gradle dependency doesn’t match the actual file in libs/.
Solution: Double-check the exact filename. For Groovy DSL, the name parameter should exclude the .aar extension. For Kotlin DSL, use files("libs/exact-filename.aar").
3. Offerwall doesn’t appear when calling launch()
Cause: The activity passed to launch() may be finishing, or the SDK may not have been properly initialized.
Solution: Ensure you’re passing a valid, active activity. Check that PerkoxOfferwall.create() returned a non-null Offerwall instance. Verify your appId and sdkKey are correct and correspond to an active app in your dashboard.
4. onReward callback not firing
Cause: The callback may be firing on a background thread and crashing silently, or no offers have been completed yet.
Solution: Wrap callback code in runOnUiThread { ... }. In sandbox mode, complete a test offer to verify the callback fires. Check logcat for any SDK errors.
5. Postback not received on server
Cause: The postback URL is misconfigured in the dashboard, your server is not reachable from the internet, or the server is returning a non-200 status.
Solution: Verify the postback URL in your dashboard settings. Ensure your server is accessible via HTTPS. Test the URL manually with curl. Check that your server returns HTTP 200. Review Perkox dashboard logs for postback delivery status and error messages.
6. Java compilation error with Kotlin lambda callbacks
Cause: Java doesn’t support Kotlin property syntax for callbacks.
Solution: Use the Java setter methods: offerwall.setOnReward(...) and offerwall.setOnClose(...) instead of offerwall.onReward = .... See the Java implementation section above.
7. “Java 17 required” build error
Cause: Your Gradle JDK is set to a version older than 17.
Solution: In Android Studio, go to Settings → Build, Execution, Deployment → Build Tools → Gradle → Gradle JDK and select JDK 17. Alternatively, set JAVA_HOME to your JDK 17 installation path.
11. FAQ
What is the Perkox Android SDK and what does it do?
The Perkox Android SDK is a lightweight library that lets you embed an offerwall — a catalog of rewarded offers, surveys, and tasks — directly inside your Android app. Users complete offers and earn in-app rewards, while you earn revenue per completed action. The SDK handles offer display, tracking, and reward callbacks so you don’t have to build monetization infrastructure from scratch.
What are the minimum requirements for the Perkox Android SDK?
The SDK requires minSdk 21 (Android 5.0 Lollipop), targetSdk 33 or higher, Java 17, Kotlin 1.9 or later, and AndroidX libraries. You also need a Perkox publisher account with an appId and sdkKey from the dashboard.
Can I rely on client-side onReward callbacks for crediting users?
No. Client-side callbacks are useful for UX updates like showing a toast or refreshing a balance, but they are not secure. A user could spoof or replay callbacks to credit themselves without completing an offer. Always validate rewards server-side using Perkox postback URLs with signature verification, and treat client-side callbacks as informational only. Read our Complete Offerwall Postback Guide for implementation details.
Does the Perkox Android SDK support both Kotlin and Java projects?
Yes. The SDK is written in Kotlin but is fully interoperable with Java. Both Kotlin and Java implementation examples are provided in the official documentation. The API surface (PerkoxOfferwall.create, offerwall.launch, offerwall.onReward, offerwall.onClose) works identically in both languages.
How do I test the offerwall before going live?
Configure your SDK with sandbox credentials from the Perkox dashboard. In sandbox mode, test offers are displayed, postbacks are sent to your configured URL, and no real charges occur. Once you verify the full flow — offer completion, postback receipt, and reward credit — switch to production credentials and publish your app. See the Testing and Sandbox Mode section above for a complete testing checklist.
12. Get Started with Perkox
You now have everything you need to integrate the Perkox Android SDK into your app — from installation and Quick Start through event handling, server-side validation, sandbox testing, and troubleshooting. The core flow is straightforward: initialize with PerkoxOfferwall.create(), launch with offerwall.launch(activity), handle UX with onReward and onClose, and validate rewards server-side via postback.
If you’re also building for other platforms, check out our companion guides:
- Perkox iOS SDK: Complete Offerwall Integration Guide — The same monetization flow for iPhone and iPad apps.
- Perkox Flutter SDK: Complete Offerwall Integration Guide — Cross-platform offerwall integration for Flutter apps.
Ready to start earning? Create your free Perkox publisher account today:
Start Monetizing Your Android App with Perkox
Join thousands of developers earning revenue with offerwall monetization. Free to sign up, no minimum traffic requirements.
This guide covers the Perkox Android SDK for offerwall monetization. For the latest API changes and version history, always refer to the official Perkox Android SDK documentation. © 2026 Perkox. All rights reserved.
