Android

Android BOM

What Is Android BOM? A Beginner’s Guide to Simplifying Dependencies in 2025

Managing dependencies in Android development can feel like juggling flaming torches—one wrong move, and your build breaks. If you’re tired of mismatched library versions, build errors, and long Gradle files, Android BOM might be the solution you didn’t know you needed. In this guide, we’ll break down what Android BOM is, why it matters in...

Membership Required

You must be a member to access this content.

View Membership Levels

Already a member? Log in here
What is libs.versions.toml

Mastering libs.versions.toml: Add Plugins, Dependencies & Manage Versions Like a Pro

In modern Android and Kotlin Multiplatform development, managing dependencies across multiple modules can quickly become messy. Manually updating versions in each build.gradle.kts file is not only error-prone—it’s a headache when scaling projects. That’s where libs.versions.toml steps in—the primary and recommended configuration file for Gradle Version Catalogs, a game-changing feature introduced in Gradle 7.0 and stabilized...

Membership Required

You must be a member to access this content.

View Membership Levels

Already a member? Log in here
Migrate from SharedPreferences to Jetpack DataStore

How to Migrate from SharedPreferences to Jetpack DataStore (Step-by-Step Guide)

If you’re still using SharedPreferences in your Android app, it’s time to level up. Google introduced Jetpack DataStore as the modern solution for storing key-value and typed objects in a more efficient, safe, and asynchronous way.

In this guide, we’ll walk you through how to migrate from SharedPreferences to Jetpack DataStore, step by step, with easy-to-follow code examples and clear explanations.

Let’s future-proof your app’s data storage..!

Why Migrate from SharedPreferences to Jetpack DataStore?

Before we jump into the code, here’s why the switch matters:

  • Asynchronous: DataStore is built on Kotlin Coroutines, meaning no more blocking the main thread.
  • Type safety: With Proto DataStore, you can define your own schema.
  • More robust: Handles data consistency and corruption better.
  • Google-backed: DataStore is the future; SharedPreferences is legacy.

So let’s get into it.

Step 1: Add DataStore Dependencies

First, update your build.gradle (app-level) file:

Kotlin
dependencies {
    implementation "androidx.datastore:datastore-preferences:1.0.0"
}

Sync your project to download the necessary libraries.

Step 2: Create Your DataStore Instance

Unlike SharedPreferences, you don’t instantiate DataStore directly. Instead, use an extension on Context.

Kotlin
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "user_prefs")

Place this in a Kotlin file (e.g., DataStoreModule.kt) at the top-level (outside any class).

Step 3: Reading Data from DataStore

Let’s say you used to read the user’s theme like this:

Kotlin
val isDarkMode = sharedPreferences.getBoolean("dark_mode", false)

Here’s how to do it with DataStore:

Kotlin
val DARK_MODE_KEY = booleanPreferencesKey("dark_mode")

val isDarkModeFlow: Flow<Boolean> = context.dataStore.data
    .map { preferences ->
        preferences[DARK_MODE_KEY] ?: false
    }

Btw, what’s happening here?

  • DARK_MODE_KEY is a typed key (you can have string, int, float, etc.).
  • dataStore.data returns a Flow of Preferences.
  • map transforms it to the value you care about.

To observe the value:

Kotlin
lifecycleScope.launch {
    isDarkModeFlow.collect { isDark ->
        // Update UI or store in variable
    }
}

Step 4: Writing Data to DataStore

Here’s how you’d save data using SharedPreferences:

Kotlin
sharedPreferences.edit().putBoolean("dark_mode", true).apply()

With DataStore:

Kotlin
suspend fun saveDarkModeSetting(context: Context, isDarkMode: Boolean) {
    context.dataStore.edit { preferences ->
        preferences[DARK_MODE_KEY] = isDarkMode
    }
}

This function must be called from a coroutine or lifecycleScope.launch {}.

Step 5: Migrate Existing Data from SharedPreferences

Let’s say you have existing users and don’t want to lose their preferences.

Jetpack provides a migration tool built in:

Kotlin
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(
    name = "user_prefs",
    produceMigrations = { context ->
        listOf(SharedPreferencesMigration(context, "user_prefs"))
    }
)

This tells DataStore to automatically read and move values from SharedPreferences the first time it’s accessed.

Important:
  • The name in preferencesDataStore must match the SharedPreferences file name.
  • After migration, DataStore handles everything.

Step 6: Remove SharedPreferences Usage

Once you’re confident DataStore is working, clean up your codebase:

  • Delete old SharedPreferences references
  • Remove the old preference XML file if applicable

This makes your app lighter and future-proof.

Bonus: Best Practices for DataStore

  • Use a singleton or Context extension to access DataStore.
  • Keep key declarations in one place (object or constants file).
  • Prefer Flow + collect with lifecycle awareness to avoid leaks.
  • Validate and sanitize user input before writing to DataStore.

Conclusion

Migrating from SharedPreferences to Jetpack DataStore is a smart move. It modernizes your data layer, embraces async programming, and makes your app more robust.

With the step-by-step guide above, you should now feel confident making the switch. It’s not just about keeping up with Android trends — it’s about building better apps.

So go ahead, migrate from SharedPreferences to Jetpack DataStore, and give your app the stability and performance it deserv

Android Doze Mode

The Truth About Android Doze Mode: Does It Really Save Battery?

If you’ve ever wondered why your Android phone suddenly becomes stingy with background tasks when left idle, the answer likely lies in Doze Mode. Introduced in Android 6.0 (Marshmallow), this feature promised to significantly improve battery life. But does it actually deliver? 

Let’s break it down.

What Is Doze Mode?

Doze Mode is a battery-saving feature that kicks in when your device is idle for an extended period. Think of it as your phone going into “power nap” mode. During Doze, the system restricts background activities such as syncing, GPS, and network access to conserve energy.

Android doesn’t completely shut off these services but defers them to periodic maintenance windows. So your device can still check for important updates — just not every second.

When Does Doze Mode Activate?

Doze Mode isn’t triggered the moment you stop using your phone. Android checks several conditions:

  • The device is unplugged.
  • The screen is off.
  • The phone hasn’t moved for a while.
  • No active wake locks are held by apps.

Once all conditions are met, the phone enters Idle mode, and Doze begins throttling background processes.

Does Doze Mode Really Save Battery?

In one word: Yes — but with context.

Real-World Impact

If you’re someone who leaves their phone idle for long periods (e.g., overnight or during work hours), Doze Mode can significantly extend battery life. Users have reported up to 30% more standby time.

However, if your phone is constantly in use, or you’re moving around with it in your pocket, Doze may not activate often enough to make a noticeable difference.

How Developers Handle Doze Mode

If you’re a developer, ignoring Doze Mode can lead to broken background functionality. Here’s a simple example of how to test if your app works with Doze:

Requesting Exemption from Doze Mode

Java
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
    String packageName = context.getPackageName();
    if (!pm.isIgnoringBatteryOptimizations(packageName)) {
        Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
        intent.setData(Uri.parse("package:" + packageName));
        context.startActivity(intent);
    }
}
  • This code checks if your app is excluded from Doze Mode.
  • If it isn’t, it launches a system dialog requesting the user to whitelist your app.
  • Be cautious: this should only be used for essential apps like alarms or health monitors.

Please note, you must have this permission in your AndroidManifest.xml:

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

How to Check If Doze Mode Is Hurting App Performance

Some apps rely heavily on real-time background updates (think messaging or location tracking). If users report delays or missed notifications, Doze could be the culprit.

Quick Fix for Users

  1. Go to Settings > Battery > Battery Optimization.
  2. Select “All apps.”
  3. Tap your app and choose “Don’t optimize.”

This removes Doze restrictions for that app, but use sparingly to avoid draining your battery.

How Android Developers Can Handle It

If you’re an app developer, you’ll want to make sure your app behaves properly while Doze Mode is active. Android offers special APIs so your alarms and background jobs don’t get lost in the shuffle.

Example: Scheduling Alarms in Doze Mode

By default, normal alarms are postponed. If your app needs to set a time-sensitive alarm (think: medication reminders or calendar events), you must use setAndAllowWhileIdle():

Java
AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
PendingIntent alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

alarmMgr.setAndAllowWhileIdle(
    AlarmManager.RTC_WAKEUP,
    triggerAtMillis, // desired trigger time in milliseconds
    alarmIntent
);

How This Works

  • setAndAllowWhileIdle() lets your alarm fire even if Doze Mode is triggered—but only for critical events.
  • Use this carefully, as Android limits how often you can schedule these alarms during Doze to prevent battery drain.

Best Practices for Developers

  1. Use WorkManager: It’s built to handle Doze correctly.
  2. Schedule jobs wisely: Use JobScheduler or AlarmManager with setAndAllowWhileIdle().
  3. Test aggressively: Use adb shell dumpsys deviceidle to simulate Doze in development.

Final Verdict: Is Doze Mode Worth It?

Absolutely. For most users, Doze Mode runs silently in the background, extending battery life without sacrificing usability. It’s one of those features that just works — when you let it.

However, for power users and developers, understanding how Doze interacts with apps is essential. Used properly, Doze Mode strikes a smart balance between saving power and staying connected.

So yes, Doze Mode really does save battery. It’s not a gimmick — just smart engineering.

TL;DR (Too Long; Didn’t Read)

  • Doze Mode saves battery by pausing background tasks when your phone is idle.
  • It’s most effective when the device is stationary and unused.
  • Developers must adapt their apps to work within Doze constraints.
  • It works quietly, efficiently, and yes — it makes a real difference.

Frequently Asked Questions

Will I Miss Important Calls or Messages Because of Doze Mode?

No, Doze Mode is designed to allow high-priority push notifications and alarm clock events even while active, so you don’t miss critical alerts.

Can I Turn Off Doze Mode?

By default, Doze Mode is automatic and always-on from Android 6.0 onward. You can exclude specific apps via Android settings if you need certain apps to bypass it, but this can hurt your battery life.

Does Doze Mode Replace Battery Saver?

No, it’s a different feature. Battery Saver is a manual or automatic mode you can toggle, restricting performance and features for more aggressive savings. Doze Mode works behind the scenes automatically, focusing on background tasks while idle

Why Device State Matters for Resource Limits

How Android Smartly Manages App Resources Based on Device State

When it comes to balancing app performance, user experience, and battery life, Android uses a sophisticated system of resource management that adapts dynamically based on the device’s current state. Understanding how these resource limits work is crucial for developers aiming to build efficient, battery-friendly, and responsive apps. 

In this blog, we’ll dive deep into how Android enforces or exempts resource limits depending on whether the device is charging, the screen is on, or the device is in a low-power mode like Doze.

Why Device State Matters for Resource Limits

Modern smartphones juggle dozens of apps and background processes at once. Without some form of resource control, one rogue app could drain your battery, clog the network, or degrade user experience for everything else running on your phone. To combat this, Android classifies device state into several modes — charging, screen on, and screen off with Doze active — and applies or lifts resource limits accordingly.

Resource Controls by Device State: The Big Picture

Let’s break down how resource limits change based on the device state, focusing on four key areas every developer and advanced user should know: Jobs, Alarms, Network Access, and Firebase Cloud Messaging (FCM).

1. Device Charging

Charging is the most permissive state.

  • Jobs: When your device is plugged in, most job execution limits are lifted, with the exception of apps in the restricted standby bucket (these are apps the user or system has placed under heavy restriction for background activity).
  • Alarms: There are essentially no limits to alarm scheduling, unless you have manually restricted an app’s battery usage.
  • Network Access: Apps can access the network freely. No special throttling or restrictions are applied.
  • FCM: Firebase Cloud Messaging enjoys unrestricted delivery of both high and normal priority messages while charging.

If your app needs to perform heavy background work, leveraging the charging state is best practice for both user satisfaction and energy efficiency.

2. Screen On

Active usage, but with smart checks in place.

  • Jobs: Execution of background jobs is allowed, but still subject to limits based on the app’s standby bucket. Apps the system deems “frequent” get more leeway than those rarely used.
  • Alarms: Alarm limits are enforced based on both process (foreground or background) and standby bucket.
  • Network Access: Access to network resources is permitted, but could be throttled depending on standby bucket or app process state.
  • FCM: No restrictions. Both high and normal priority FCM messages are delivered without delay.

Even with the screen on, background execution is managed to prevent resource hogging but without compromising the user’s foreground tasks.

3. Screen Off & Doze Mode

Aggressive conservation to preserve battery.

  • Jobs: Execution is heavily restricted. Jobs are only permitted to run during periodic “maintenance windows” triggered by Doze. The standby bucket further dictates how much background work an app can do — a rarely used app may only get a 10-minute quota every 24 hours.
  • Alarms: Most alarms, especially regular alarms, are deferred until these maintenance windows. “While-idle” alarms are strictly limited (e.g., 7 per hour). This ensures that the device is not frequently awakened from deep sleep, maximizing battery savings.
  • Network Access: Network requests are typically deferred, especially for background apps. Only the most essential tasks will get through during Doze.
  • FCM: High priority messages are delivered immediately, bypassing Doze. Normal priority messages are deferred until the next maintenance window, so non-urgent notifications may experience some delay.

Doze mode is designed to maximize standby time without missing critical notifications or updates. Writing efficient background code means understanding and respecting these constraints.

Device State vs. Resource Limits

Device StateJobs ExecutionAlarmsNetwork AccessFirebase Cloud Messaging
ChargingNo limits (except restricted standby bucket)No execution limits (unless manually restricted)No restrictionsNo restrictions (both priorities)
Screen OnBased on standby bucketBased on process & bucketBased on process or bucketNo restrictions
Screen Off & Doze ActiveEnforced by bucket; deferred to maintenance windowDeferred; while-idle alarms: 7/hrRestricted; usually deferredHigh priority: immediate, Normal: deferred

Developer Takeaways and Best Practices

  • Schedule background-intensive work during charging: Use job scheduling APIs to detect charging state and defer heavy tasks until then.
  • Respect Doze and App Standby Buckets: Design your background operations to be efficient and infrequent, using WorkManager or JobScheduler for compatibility.
  • Use High Priority FCM judiciously: Only essential and time-sensitive notifications should be sent with high priority to respect users’ battery life.
  • User control matters: Remember, users can manually restrict battery usage for specific apps, which overrides nearly all exemptions.

Conclusion

Android’s adaptive resource limits are a cornerstone of its battery and performance management strategy. By understanding how device state influences background jobs, alarms, network access, and cloud messaging, developers can craft apps that play nicely with the system, keeping users happy and devices running longer

Building Resilient Android Apps

Building Resilient Android Apps: Surviving Doze, App Standby, and Resource Restrictions

Android power management has evolved significantly over the years. As developers, we need to design apps that are not only functional but also battery-friendly. Google introduced Doze Mode, App Standby, and various resource restrictions to extend battery life. While these features improve user experience, they can cause unexpected issues if apps aren’t built with resilience in mind.

In this guide, we’ll break down Android power management features, why they matter, and how you can build resilient Android apps that survive and thrive under these restrictions.

Why You Should Care About Android Power Management

Modern Android devices aggressively manage background processes to save battery. If your app misbehaves — draining battery or waking up the device too often — it can be throttled, delayed, or even killed. Worse case, when you might see user complaints about missed notifications or slow updates.

By understanding how Doze Mode, App Standby, and background restrictions work, you can ensure your app remains responsive while respecting battery life.

Doze Mode

Doze Mode activates when a device is idle for a while — screen off, unplugged, and stationary. Android periodically defers background CPU and network activity to preserve battery.

Key Points:

  • Your app’s background tasks get paused.
  • Network access is restricted.
  • Alarms (except AlarmManager.setExactAndAllowWhileIdle()) are deferred.

How to Handle Doze Mode Correctly:

Java
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
if (pm.isIgnoringBatteryOptimizations(getPackageName())) {
    // Your app is exempted from Doze (rarely recommended)
} else {
    // Use WorkManager or Firebase JobDispatcher for background tasks
}

Instead of fighting Doze, work with it. Use WorkManager for deferrable background tasks. It automatically handles Doze and other restrictions.

App Standby: What Developers Must Know

App Standby identifies apps that aren’t used frequently and restricts their background activity.

Behavior:

  • Background network access is blocked.
  • Jobs and alarms are deferred.
  • High-priority notifications still work.

Detecting App Standby Bucket:

Java
UsageStatsManager usageStatsManager = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE);
int appStandbyBucket = usageStatsManager.getAppStandbyBucket();

switch (appStandbyBucket) {
    case UsageStatsManager.STANDBY_BUCKET_ACTIVE:
        // App is active
        break;
    case UsageStatsManager.STANDBY_BUCKET_RARE:
        // App is rarely used
        break;
}

Encourage user engagement with meaningful notifications to avoid landing in the “rare” bucket.

Background Execution Limits

Starting from Android 8.0 (Oreo), background execution limits make Android power management stricter:

  • Background services can’t run freely.
  • Implicit broadcasts are restricted.

Solution: WorkManager to the Rescue

Java
WorkManager workManager = WorkManager.getInstance(context);
OneTimeWorkRequest workRequest = new OneTimeWorkRequest.Builder(MyWorker.class).build();
workManager.enqueue(workRequest);

Replace IntentService with JobIntentService or WorkManager to ensure reliability.

Optimizing Notifications Under Power Management

Notifications are crucial for engagement, but Android power management policies may delay them if improperly handled.

Best Practices:

  • Use Firebase Cloud Messaging (FCM) with high-priority messages sparingly.
  • Avoid unnecessary wake-ups; reserve high-priority FCM for time-critical updates.
  • Use NotificationManager correctly to deliver timely, non-intrusive notifications.
Java
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
    .setSmallIcon(R.drawable.notification_icon)
    .setContentTitle("Update Available")
    .setContentText("New data ready to view!")
    .setPriority(NotificationCompat.PRIORITY_HIGH);

High-priority FCM bypasses Doze but excessive usage can get your app flagged.

Avoid Common Pitfalls

Don’t abuse foreground services. They drain battery and annoy users if misused.

Don’t request battery optimization exemptions unless absolutely necessary. Google Play has strict policies and most requests get denied.

Do leverage JobScheduler, WorkManager, and FCM effectively.

Do test under real conditions. Use adb shell dumpsys deviceidle to simulate Doze Mode and check your app’s behavior.

Conclusion

Building resilient Android apps means respecting Android power management rather than working around it. Focus on:

  • Using WorkManager for background tasks.
  • Optimizing notifications.
  • Monitoring app standby behavior.

By designing apps that adapt to Android’s power-saving mechanisms, you’ll deliver reliable experiences without draining users’ batteries. 

Android Standby Bucket

Mastering Android Standby Bucket: How It Impacts Your App’s Background Activity

If you’ve noticed your Android app getting delayed push notifications, or background tasks not running as expected, the culprit could be Android Standby Bucket. This isn’t some hidden developer setting — it’s a key part of Android’s power management system. And if you want your app to work smoothly in the background without draining battery, you need...

Membership Required

You must be a member to access this content.

View Membership Levels

Already a member? Log in here
Android Back Stack

Android Back Stack: A Complete Guide for Modern App Navigation

Let’s talk about something that trips up a lot of Android developers — especially when building apps with complex navigation: the Android Back Stack. You know that moment when you hit the back button and your app behaves like it has a mind of its own? Yeah, we’ve all been there. The Android Back Stack can be...

Membership Required

You must be a member to access this content.

View Membership Levels

Already a member? Log in here
Paparazzi Testing Library

Paparazzi Testing Library: The Secret Weapon for Flawless UI Snapshots in Android

You build a clean UI, test it on your emulator, and everything looks solid. But once QA or users get their hands on it, layout bugs pop up — text overflowing, views misaligned, odd paddings. It happens more often than we like to admit. That’s where the Paparazzi Testing Library proves its worth. It’s a powerful snapshot...

Membership Required

You must be a member to access this content.

View Membership Levels

Already a member? Log in here
android sdk tools

Android SDK Tools: The Brains Behind Your App Development

When building Android apps, it’s easy to focus only on the code, UI, and features. But behind every successful app lies a set of powerful, low-level tools that keep the whole process moving. These are the Android SDK Tools — the unsung heroes of the Android development ecosystem.

In this post, we’ll break down what they are, how they work, and why every Android developer should understand them — even in the age of Android Studio.

What Are Android SDK Tools?

Android SDK Tools are a collection of command-line utilities that help you build, test, and debug Android apps. They used to be packaged together as “SDK Tools,” but over time, they’ve been split into modular components like:

  • platform-tools — includes ADB, fastboot, and other core tools.
  • build-tools — includes utilities like aapt, zipalign, etc.

Even though Android Studio handles much of this behind the scenes, these tools are still critical — especially when things go wrong, or when you want to automate development tasks.

Essential SDK Tools Every Android Developer Should Know

Let’s take a closer look at the key tools that power Android development under the hood:

1. ADB (Android Debug Bridge)

ADB is a command-line tool that lets your computer communicate with an Android device or emulator.

Think of it as a remote control for your Android environment. You can install apps, copy files, debug logs, and even run shell commands directly on the device.

Common ADB Commands:

ASM
adb devices             # Lists connected devices
adb install myapp.apk   # Installs an APK
adb logcat              # Displays real-time device logs

This is one of the most valuable tools in your toolbox, especially for real-time debugging.

2. fastboot

When your device is in bootloader mode, fastboot lets you flash images to the device, unlock the bootloader, and perform other low-level operations.

It’s typically used for:

  • Flashing custom recoveries or ROMs
  • Unlocking or locking bootloaders
  • Recovering bricked devices

While not every developer uses fastboot regularly, it’s indispensable for anyone working near the hardware layer or with custom builds.

3. R8 and ProGuard

Originally, ProGuard was used to shrink and obfuscate Java code in Android apps. Today, R8 has replaced it as the default tool for most modern Android projects.

R8 performs:

  • Code shrinking
  • Dead code elimination
  • Resource optimization
  • Obfuscation (to make reverse engineering harder)

R8 is built into the Android Gradle plugin, so you don’t typically run it manually — but understanding what it does can help you configure it properly in proguard-rules.pro.

Why These Tools Still Matter in 2025

Even though Android Studio and Gradle handle most of the heavy lifting today, knowing how SDK tools work gives you:

  • More control over your builds and deployments
  • Better debugging capabilities, especially on real devices
  • The ability to automate testing, CI/CD, and device management
  • Deeper insights into how Android actually works

When something breaks outside the Studio UI, these tools are often your first (and best) line of defense.

Conclusion

The Android SDK Tools may not be glamorous, but they are the engine under the hood of Android development. Whether you’re pushing your first APK or debugging a complex issue, understanding ADB, fastboot, and R8 will make you a more capable — and confident — developer.

error: Content is protected !!