DEV Community

NexusDriftStudio
NexusDriftStudio

Posted on

Privacy-First Android Dev: How to Build an App With Zero Analytics, Zero Firebase, Zero Cloud

Privacy-First Android Dev: How to Build an App With Zero Analytics, Zero Firebase, Zero Cloud

StepShield Pro is 100% free. Forever. No paid tier. No ads. No in-app purchases. No upsells. No data collection. No tracking. No account required. No subscription. The full feature set is in the free app, and always will be. This is a complete product, not a freemium teaser. (I built it. I am documenting the privacy architecture here so other Android devs can copy the pattern.)

I ship a digital wellbeing Android app with zero analytics, zero Firebase, and zero cloud. The whole app is 7.8 MB. The entire privacy policy fits in 200 words. The Play Store data safety form says "no data collected." I pass their verification.

This is the architecture. If you ship an Android app, you can copy it.

What "privacy-first" actually means

Most Android apps ship with a "data safety" section that lists every byte of data the app touches. The minimum you see in a typical indie app:

  • Device ID (Android Advertising ID, Google Play ID)
  • Crash reports (Firebase Crashlytics, Sentry, Bugsnag)
  • Install referrer (Google Play install referrer)
  • In-app events (Firebase Analytics, Amplitude, Mixpanel)
  • In-app purchases receipt validation (server-side)
  • User account (email, OAuth profile)
  • Push notification tokens (FCM)

That's six data points the user has to trust you with before they even see your onboarding screen. Each one is a liability: GDPR, CCPA, COPPA, the app store's data safety form, and the security of whatever server you push it to.

Privacy-first means: the data never leaves the device. No analytics endpoint, no crash reporter, no push server. There is no server. There is no data to be non-compliant about.

The complete dependency list (yes, this is the whole app)

Here's every line in the app's build.gradle.kts:

dependencies {
    implementation("androidx.core:core-ktx:1.13.1")
    implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.7")
    implementation("androidx.lifecycle:lifecycle-service:2.8.7")
    implementation("androidx.room:room-runtime:2.6.1")
    implementation("androidx.room:room-ktx:2.6.1")
    implementation("androidx.security:security-crypto:1.1.0-alpha06")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.9.0")
    implementation("androidx.work:work-runtime-ktx:2.10.0")
    implementation("androidx.compose.material3:material3:1.3.1")
    implementation("androidx.activity:activity-compose:1.9.3")
}
Enter fullscreen mode Exit fullscreen mode

No com.google.firebase:*. No com.google.android.gms:play-services-*. No com.amplitude:*. No io.sentry:*. No com.mixpanel:*. The biggest dependency is Jetpack Compose.

The app blocker with no tracking ships in 7.8 MB. The equivalent app with Firebase ships in 25-40 MB. That is a 70% size reduction for removing features.

How to replace each Firebase feature

Crash reporting without Firebase Crashlytics

I use Thread.setDefaultUncaughtExceptionHandler and write the stack trace to a local file. On the next app launch, I show a banner: "The app crashed last time. Tap to view the trace. Tap again to send." If the user wants to send, they get a system chooser. If they don't, the trace is deleted after 7 days. Optional, in-app, transparent.

class PrivacyFirstCrashHandler(private val context: Context) : Thread.UncaughtExceptionHandler {
    private val original = Thread.getDefaultUncaughtExceptionHandler()

    override fun uncaughtException(t: Thread, e: Throwable) {
        val trace = StringWriter().also { e.printStackTrace(PrintWriter(it)) }
        File(context.filesDir, "last_crash.txt").writeText("""
            Thread: ${'$'}{t.name}
            Time: ${'$'}{Instant.now()}
            Build: ${'$'}{BuildConfig.VERSION_NAME} (${'$'}{BuildConfig.VERSION_CODE})
            Device: ${'$'}{Build.MANUFACTURER} ${'$'}{Build.MODEL}, Android ${'$'}{Build.VERSION.RELEASE}
            Stack trace: ${'$'}trace
        """.trimIndent())
        original?.uncaughtException(t, e)
    }
}
Enter fullscreen mode Exit fullscreen mode

50 lines. Beats configuring Firebase. Beats waiting for a dashboard.

Push notifications without FCM

I use Android's built-in NotificationManager with local-scheduled alarms. No FCM, no remote server. The user gets a daily reminder at 9 PM ("You walked 4,200 steps. Your apps are unlocked until 11 PM.") because the app schedules a local AlarmManager for the next day at 9 PM, in a loop. No remote trigger, no push token, no Google Play Services.

Cloud sync without a cloud

There is no cloud sync. The user installs the app on a new phone, they start from zero. That is a feature, not a bug - a stalker ex cannot log into their account and see step counts from the past year. No account exists to be compromised.

Analytics without a dashboard

I have one log line: Log.d("StepShield", "step_count=" + count). It goes to adb logcat if the user opts in to USB debugging. Otherwise it goes nowhere. No Amplitude, no Mixpanel, no Firebase Analytics, no Plausible, no self-hosted anything. I do not have a dashboard because I do not have data to put in one.

Account without OAuth

There is no account. The app has no login screen. There is no "Sign in with Google" button. There is nothing to log in to.

What the Play Store data safety form looks like (claim it exactly like this)

Data shared with third parties: None
Data collected: None
Data security: All data is encrypted in transit (TLS 1.3 to Google Play Store) and at rest (Android's full-disk encryption)
Data deletion: Users can delete all their data with one tap in Settings > Privacy > Wipe Everything
Data export: Users can export all their data as JSON in Settings > Privacy > Export

The Play Store's verification system actually checks this. They send synthetic requests and verify that no analytics endpoints are called. I passed the check.

GDPR, CCPA, and COPPA compliance by default

There is no data to be GDPR-non-compliant about. There is no data to delete on request. The data deletion form is one tap. Privacy by default means compliance by default. If you are a solo dev shipping an app, this is the only sustainable path. Lawyer fees alone can break a startup, and a privacy-first architecture removes the need for most of them.

What you give up (be honest with yourself)

Honestly, you give up three things:

  1. Cross-device sync. A user who installs your app on a Pixel 8 and a Samsung Tab does not see the same data. That is fine. Sync via Health Connect if you need it - it is opt-in, end-to-end, and does not involve your server.

  2. Conversion attribution. You do not know which marketing channel brought any given install. The Play Store install referrer is ignored. You cannot A/B test landing pages. You cannot tell yourself "50% of installs come from this Subreddit" (and you should not be on Reddit anyway, by choice). This hurts growth initially, but it forces you to write better content, which compounds.

  3. Real-time user feedback. You cannot push a "we just shipped v1.2, here's what's new" notification. The user finds out by opening the Play Store, or by their app updating silently. You lose some retention to this. The trade-off is worth it.

What you gain (be honest with users about it)

  • User trust. People who care about privacy install the app, leave a 5-star review, and tell their friends. The privacy-first angle in the Play Store description converts at a higher rate than I expected.
  • Faster development. You do not wait for Firebase Crashlytics to ingest a crash report to see what crashed. You do not have to check Amplitude for the funnel drop-off. You just ship and read user reviews.
  • Smaller app size. 7.8 MB vs 25-40 MB with Firebase. That is a 70% size reduction.
  • No server costs. I pay $0 per month. The app is 100% client-side. I have no server, no database, no CDN.
  • Better sleep. No 3 AM pages because your analytics dashboard is on fire. No breach notifications because there is no data to breach. No GDPR fines because there is no data subject to GDPR.
  • No ads, no paid tier. The app is free forever, with no monetization at all. The user gets a complete product, not a freemium teaser.

How to migrate an existing app to privacy-first

I will not pretend it is one afternoon of work. Here is the realistic sequence:

  1. Audit. Open your build.gradle.kts. For each Firebase / Google Play Services / analytics dependency, write down what it does and what would replace it. (Most replacements are 50-200 lines of code.)
  2. Replace crash reporting first. This is the lowest-risk swap. Users expect crash reporting to be optional, and the in-app banner pattern is well-understood.
  3. Replace analytics second. Stop the dashboard. Switch to Log.d calls + a one-time user survey ("how did you hear about us?"). You will lose some signal. You will gain a lot of trust.
  4. Replace auth last. This is the highest-risk swap, because your existing users have accounts. Plan a 6-month deprecation window, or keep auth but stop using the data.
  5. Update the Play Store data safety form. List "no data collected." Verify with a fresh install.

Privacy is not a feature you bolt on. It is an architecture you choose. And the architecture is simpler than the alternative.

FAQ

Can a privacy-first app have analytics at all?

Yes, but they have to be in-app, opt-in, and transparent. Local logcat logging, anonymous in-app surveys, or a self-hosted solution like Plausible. Just nothing that touches a remote server without explicit consent.

What about crash reporting?

Local file + in-app banner, as shown above. 50 lines. Beats Firebase Crashlytics for trust, and the data never leaves the device.

Is privacy-first only for small apps?

No. Signal, Tutanota, ProtonMail - all privacy-first. The architecture scales. You just need to be more disciplined about what you collect, and clearer with users about what you do with it.

How do you measure product success without analytics?

You read user reviews. You respond to support emails. You ship features people ask for. The signal is slower than a dashboard, but it is also less biased. The Play Store review section is the most honest product analytics tool you have.

What about A/B testing?

You can do server-side A/B testing without a server using local flags. Or you just ship the version you think is better and roll back if users complain. The latter is what most successful indie devs do.

How do you make money if there are no ads and no paid tier?

You do not, necessarily. I made a deliberate choice: no ads, no paid tier, no data collection, no tracking. The app is a portfolio piece and a small contribution to the privacy-first app ecosystem. If you want to monetize, the privacy-preserving options are: a one-time purchase (with no in-app subscription), tip jar, sponsorship from a privacy-aligned brand, or premium features that are clearly opt-in (e.g. cloud sync via your own server, Health Connect, etc.). I have not monetized StepShield Pro and I do not plan to.

Read the other article in this series

If you want the user-facing story - why I built a step-based app blocker, and how Walk-to-Unlock works - read Walk-to-Unlock: Step Counter App Blocker for Screen Time.

Top comments (0)