GetPassive logoGetPassive
2026-06-14 · GetPassive Team · 10 min read

How to Add Passive Income to Your Android App

If you want to add passive income to your Android app without filling it with ads, the work is smaller than most developers expect: a Gradle dependency, a couple of manifest entries, an in-app disclosure, and a single SDK call. This guide walks through the whole thing in Kotlin, with the exact code and the consent UX you should ship.

The premise: you already have a working Android app with active users. You want a quiet, opt-in revenue layer that earns when devices are online and idle, without changing the user-facing product. We will integrate the GetPassive Android SDK as the example because the API is small and the consent pattern is reusable, but the same shape applies to other SDKs in the category.

Step 0: Decide if this fits your app

Not every Android app is a good fit. The ones that earn well share three traits:

  • Long installed uptime. Launchers, file managers, media players, IPTV apps, Android TV apps, and utility tools that stay installed and online beat short-session apps with the same audience size.
  • Wi-Fi-heavy users. Users on Wi-Fi can opt in safely without burning their mobile data. Apps used mostly on mobile data only earn when users explicitly extend consent to metered connections.
  • An audience that trusts you. Consent is the whole game. If your audience is loyal and you have built trust through years of clean releases, you will see better opt-in rates.

Apps that struggle: short-session tools (calculators with a 20-second median session), apps where users explicitly chose a privacy-focused product, and apps in regions where bandwidth demand is low. For more on app fit, see why utility apps are the hardest to monetize.

Step 1: Add the Gradle dependency

The Android SDK ships as an .aar dependency. Add it to your module-level build.gradle.kts:

dependencies {
    implementation("io.getpassive:sdk-android:1.4.0")
}

Or if you are still on Groovy:

dependencies {
    implementation 'io.getpassive:sdk-android:1.4.0'
}

Sync Gradle. The SDK adds roughly 180 KB to your APK and has no transitive Google Play Services dependency, so it works on Android builds without GMS (Huawei devices, AOSP forks, set-top boxes).

Step 2: Manifest entries

The SDK needs two permissions: INTERNET (you almost certainly have it already) and ACCESS_NETWORK_STATE (so it can respect metered connections). Add these inside the <manifest> root in AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Do not add FOREGROUND_SERVICE unless you actually want the SDK to run while your app is killed. For most consumer apps a normal background dispatcher is the right behaviour: the SDK runs while the app process is alive (which on Android can be quite long for apps with notifications, services, or active components) and stops cleanly when the system reclaims memory.

Step 3: Initialise the SDK in Application.onCreate

Initialise the SDK once, at app start, with your developer key from the dashboard. Pass the user's current consent state — do not enable by default.

class App : Application() {
    override fun onCreate() {
        super.onCreate()
        GetPassive.initialize(
            context = this,
            developerKey = BuildConfig.GETPASSIVE_KEY,
            consent = ConsentState.fromUserPreference(
                getSharedPreferences("gp", MODE_PRIVATE)
                    .getBoolean("opted_in", false)
            ),
            options = GpOptions(
                wifiOnly = true,        // safe default
                respectBatterySaver = true,
                respectDataSaver = true
            )
        )
    }
}

Register the Application class in the manifest if you have not already:

<application
    android:name=".App"
    ...>

That is the entire SDK surface. There is no "start" call, no service to bind, no notification to manage. The SDK reads consent at init and respects future updates pushed via GetPassive.updateConsent(...).

Step 4: Build the in-app disclosure

The in-app disclosure is the single most important piece of this integration. Get it right and your opt-in rate (and retention) will be fine. Get it wrong and you will earn nothing because nobody opts in — or worse, you damage user trust with a dark-pattern flow.

Use plain English. Default off. Active acceptance. Visible off switch in settings.

@Composable
fun ConsentSheet(onResult: (Boolean) -> Unit) {
    Column(Modifier.padding(24.dp)) {
        Text(
            "Help support development",
            style = MaterialTheme.typography.titleLarge
        )
        Spacer(Modifier.height(12.dp))
        Text(
            "If you turn this on, a small share of your spare " +
            "Wi-Fi bandwidth is used to help business customers " +
            "with web data tasks like price monitoring and brand " +
            "protection. We earn a share, you keep the app ad-free. " +
            "You can switch this off at any time in Settings."
        )
        Spacer(Modifier.height(16.dp))
        Row {
            TextButton(onClick = { onResult(false) }) {
                Text("Not now")
            }
            Spacer(Modifier.weight(1f))
            Button(onClick = { onResult(true) }) {
                Text("Turn on")
            }
        }
        Spacer(Modifier.height(8.dp))
        TextButton(onClick = { /* open disclosure URL */ }) {
            Text("Learn more")
        }
    }
}

When the user accepts, persist the choice and push the consent update:

private fun onConsentResult(accepted: Boolean) {
    getSharedPreferences("gp", MODE_PRIVATE).edit()
        .putBoolean("opted_in", accepted)
        .apply()
    GetPassive.updateConsent(
        ConsentState.fromUserPreference(accepted)
    )
}

Add a matching toggle to your settings screen. That is the entire UX. Do not nag, do not re-prompt every week, do not show a "you are missing out" banner if the user said no.

Step 5: Test before you ship

Before pushing to production, walk through this checklist on a real device:

  1. Cold-start the app on Wi-Fi with consent off. Confirm no traffic is generated by the SDK (check via a network monitor or charles-style proxy).
  2. Accept consent. Confirm the SDK starts and the dashboard registers the device within 60 seconds.
  3. Switch to mobile data. Confirm the SDK stops while wifiOnly = true.
  4. Enable Battery Saver in Android settings. Confirm the SDK throttles itself.
  5. Revoke consent from your settings screen. Confirm the SDK stops within a few seconds.
  6. Cold-start with consent on. Confirm the SDK resumes silently — no re-prompt.

If all six work, you are ready to ship.

Step 6: Earnings tracking and payouts

Earnings appear on the GetPassive developer console, broken down per app, per device, and per country tier. Higher-demand regions (US, UK, EU) produce stronger per-device earnings; quieter regions earn less. Payouts run monthly via Stripe Connect or USDC, with a $10 minimum balance. See how GetPassive developer earnings work for the full payout model, and Stripe Connect for international developers if you need to wire up payouts outside the US.

What this does to your release

Most developers ship this integration in an afternoon. The added APK weight is small. There is no UI surface to maintain except the consent sheet and the settings toggle. There is no ongoing work after release except watching the dashboard and adjusting your in-app disclosure copy if your opt-in rate is below what your audience can deliver.

If you want to test the integration on your own app, sign up. We review the app category and consent flow before issuing developer keys.

FAQ

Will this slow my Android app down?

A well-built bandwidth SDK runs on a background dispatcher, throttles itself when the app is in the foreground, and never touches the main thread. In practice users on mid-range devices do not notice a difference in app responsiveness.

Does the SDK need foreground service permissions?

It depends on how you want it to behave. For most consumer apps, a normal background dispatcher is fine and respects Doze. If you want it to run while the app is killed, you will need a foreground service with a persistent notification, which most apps do not need.

What happens on Wi-Fi vs mobile data?

The SDK should respect metered connections by default. Users on mobile data plans should never see their cap drained without explicit opt-in to use mobile data. Wi-Fi only is the safe default.

Do I need Google Play approval for this?

You need to disclose any background networking and the use of users' bandwidth in your privacy policy and the Play Store listing. Use a clear, default-off consent flow and link to a disclosure page. Play has approved this category of SDK when the consent is explicit and the user can revoke.

What does the in-app disclosure need to say?

Plain-language description of what is routed (small amount of spare bandwidth), who pays (business customers running legitimate web data use cases), how the user can turn it off (settings toggle), and a link to the full disclosure. Default off, active acceptance, no dark patterns.

Want to test this with your app?

Sign up free, add your app, and our team will review it within one business day before issuing your SDK key.

Sign up free

Read more

All posts