Amol Pawar

Unchecked Exceptions in Java

Unchecked Exceptions in Java: What They Are

Java is a powerful programming language that provides robust error handling mechanisms through exceptions. Exceptions in Java are classified into checked exceptions and unchecked exceptions. In this blog post, we’ll dive deep into unchecked exceptions in java, focusing on RuntimeException, and explore how they work, when to use them, and best practices.

What Are Unchecked Exceptions in Java?

Unchecked exceptions in Java are exceptions that occur during the execution of a program and do not need to be explicitly declared or handled. They are subclasses of RuntimeException, which itself extends Exception. Unlike checked exceptions, the compiler does not force you to handle unchecked exceptions, giving developers more flexibility.

Imagine you are driving a car:

  • If you run out of fuel before starting, you already know you’ll need to refill (like a checked exception, where Java warns you in advance).
  • If you suddenly get a flat tire while driving, it’s unexpected (like an unchecked exception, because Java doesn’t force you to check for it).

Unchecked exceptions usually happen due to coding mistakes like dividing by zero, accessing an invalid index, or dereferencing null.

Key Characteristics of Unchecked Exceptions:

  • They occur at runtime.
  • They are not required to be handled using try-catch or declared with throws
  • They indicate programming errors, such as logical flaws or improper API usage.
  • Examples include NullPointerException, ArrayIndexOutOfBoundsException, and IllegalArgumentException.

Common Causes of Unchecked Exceptions

Unchecked exceptions often arise from:

  1. Null references — Trying to access methods or fields of a null object leads to a NullPointerException.
  2. Invalid array access — Accessing an index beyond the array’s length results in ArrayIndexOutOfBoundsException.
  3. Illegal operations — Dividing by zero throws an ArithmeticException.
  4. Invalid casting — Trying to cast an object to an incompatible type leads to ClassCastException.
  5. Improper argument usage — Passing an invalid argument to a method can trigger IllegalArgumentException.

How to Handle Unchecked Exceptions in Java?

Although unchecked exceptions don’t require explicit handling, it is good practice to write defensive code to avoid them. Here are some best practices:

1. Use Null Checks

Before using an object, always ensure it is not null to avoid NullPointerException.

2. Validate Input Arguments

Check method parameters before processing them.

3. Use Try-Catch Blocks Sparingly

Try-catch blocks should not be overused for unchecked exceptions but can be useful in specific cases.

Difference Between Checked and Unchecked Exceptions

Understanding the distinction between checked and unchecked exceptions is crucial for writing efficient Java code.

FeatureChecked ExceptionsUnchecked Exceptions
InheritanceExtends Exception (except RuntimeException)Extends RuntimeException
Compile-time CheckingChecked by the compilerNot checked by the compiler
Handling RequirementMust be handled or declaredNo mandatory handling
Use CaseRepresent recoverable conditions (e.g., IOException)Indicate programming errors (e.g., NullPointerException)

Should You Catch Unchecked Exceptions in Java?

Generally, it’s best to avoid catching unchecked exceptions unless you’re implementing a global exception handler. Instead, focus on writing clean, error-free code by using input validation and proper null checks. However, in web applications or frameworks, handling unchecked exceptions globally can enhance user experience by providing clear error messages rather than allowing the application to crash.

Conclusion

Unchecked exceptions in Java, particularly those derived from RuntimeException, provide flexibility but also require responsible usage. They indicate programming mistakes that should be fixed rather than caught. By following best practices like validating inputs, using meaningful messages, and logging exceptions properly, developers can write robust and maintainable Java applications.

Mastering MVVM Architecture

Mastering MVVM Architecture in Android: A Complete Guide

Modern Android development demands scalable, maintainable, and testable architectures, and MVVM (Model-View-ViewModel) has emerged as the gold standard. It helps in structuring code in a way that ensures a clean separation of concerns, making it easier to manage UI, business logic, and data operations.

In this guide, we’ll take an in-depth look at MVVM, its benefits, how to implement it using Jetpack Compose, and advanced concepts like dependency injection, UI state handling, and testing. Let’s dive in!

What is MVVM?

MVVM (Model-View-ViewModel) is an architectural pattern that separates the presentation layer (UI) from the business logic and data handling. This separation enhances modularity, making the app easier to maintain and test.

MVVM Components

  1. Model: Represents the data layer (API, database, repositories) and business logic.
  2. View: The UI layer (Activity, Fragment, or Composable functions in Jetpack Compose).
  3. ViewModel: Acts as a bridge between View and Model, holding UI-related data and surviving configuration changes.

How MVVM Works

  1. The View observes data from the ViewModel.
  2. The ViewModel fetches data from the Model.
  3. The Model retrieves data from an API, database, or local cache.
  4. The ViewModel exposes the data, and the View updates accordingly.

Why Use MVVM?

  • Separation of Concerns — Keeps UI and business logic separate.
  • Better Testability — ViewModel can be unit tested without UI dependencies.
  • Lifecycle Awareness — ViewModel survives configuration changes.
  • Scalability — Works well with large-scale applications.
  • Compatibility with Jetpack Compose — Supports modern UI development in Android.

Implementing MVVM in Android with Jetpack Compose

Let’s implement a simple MVVM architecture using Jetpack Compose.

Step 1: Model (Repository Layer)

Kotlin
class UserRepository {
    fun getUsers(): List<String> {
        return listOf("Amol", "Akshay", "Swapnil")
    }
}

Step 2: ViewModel

Kotlin
class UserViewModel : ViewModel() {
    private val repository = UserRepository()
    private val _users = MutableStateFlow<List<String>>(emptyList())
    val users: StateFlow<List<String>> = _users

    init {
        fetchUsers()
    }

    private fun fetchUsers() {
        _users.value = repository.getUsers()
    }
}

Step 3: View (Jetpack Compose UI)

Kotlin
@Composable
fun UserScreen(viewModel: UserViewModel = viewModel()) {
    val users by viewModel.users.collectAsState()
    LazyColumn {
        items(users) { user ->
            Text(text = user, fontSize = 20.sp, modifier = Modifier.padding(16.dp))
        }
    }
}

This basic example sets up MVVM with a repository, ViewModel, and a UI that observes data changes.

Dependency Injection in MVVM (Using Hilt)

To make the architecture scalable, we use Hilt for dependency injection.

Step 1: Add Dependencies

Kotlin
dependencies {
    implementation "androidx.hilt:hilt-navigation-compose:1.1.0"
    implementation "com.google.dagger:hilt-android:2.44"
    kapt "com.google.dagger:hilt-compiler:2.44"
}

Step 2: Enable Hilt in the Application Class

Kotlin
@HiltAndroidApp
class MyApp : Application()

Step 3: Inject Repository into ViewModel

Kotlin
@HiltViewModel
class UserViewModel @Inject constructor(private val repository: UserRepository) : ViewModel() {
    private val _users = MutableStateFlow<List<String>>(emptyList())
    val users: StateFlow<List<String>> = _users

    init {
        fetchUsers()
    }

    private fun fetchUsers() {
        _users.value = repository.getUsers()
    }
}

Step 4: Inject ViewModel into Composable

Kotlin
@Composable
fun UserScreen(viewModel: UserViewModel = hiltViewModel()) {
    val users by viewModel.users.collectAsState()
    
    LazyColumn {
        items(users) { user ->
            Text(text = user, fontSize = 20.sp, modifier = Modifier.padding(16.dp))
        }
    }
}

LiveData vs StateFlow: Which One to Use?

Best Practice: Use StateFlow with Jetpack Compose because it integrates better with collectAsState().

Handling UI State in MVVM

To manage loading, success, and error states:

Kotlin
sealed class UIState<out T> {
    object Loading : UIState<Nothing>()
    data class Success<T>(val data: T) : UIState<T>()
    data class Error(val message: String) : UIState<Nothing>()
}

Modify ViewModel:

Kotlin
class UserViewModel : ViewModel() {
    private val _users = MutableStateFlow<UIState<List<String>>>(UIState.Loading)
    val users: StateFlow<UIState<List<String>>> = _users

    fun fetchUsers() {
        viewModelScope.launch {
            try {
                val data = repository.getUsers()
                _users.value = UIState.Success(data)
            } catch (e: Exception) {
                _users.value = UIState.Error("Failed to load users")
            }
        }
    }
}

In UI:

Kotlin
when (state) {
    is UIState.Loading -> CircularProgressIndicator()
    is UIState.Success -> LazyColumn { items(state.data) { user -> Text(user) } }
    is UIState.Error -> Text(state.message, color = Color.Red)
}

Unit Testing MVVM Components

Unit testing is important in MVVM to ensure reliability.

Test ViewModel

Add testing dependencies:

Kotlin
testImplementation "junit:junit:4.13.2"
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.4"
testImplementation "io.mockk:mockk:1.13.3"

Create a UserViewModelTest file:

Kotlin
@ExperimentalCoroutinesApi
class UserViewModelTest {

    private lateinit var viewModel: UserViewModel
    private val repository = mockk<UserRepository>()

    @Before
    fun setUp() {
        every { repository.getUsers() } returns listOf("Amol", "Akshay", "Swapnil")

        viewModel = UserViewModel(repository)
    }

    @Test
    fun `fetchUsers updates users state correctly`() {
       // We can also call the body of setUp() here, which is useful for individual test functions that need more customization.
        assert(viewModel.users.value is UIState.Success)
    }
}

This tests that fetchUsers() properly updates the UI state.

Conclusion

MVVM architecture enhances modularity, testability, and scalability in Android development. By using Jetpack Compose, Hilt for DI, StateFlow for state management, and UI state handling, we can build robust and maintainable applications.

The Ultimate Guide to Android Basics

The Ultimate Guide to Android Basics: Architecture, Components, Development, and More

Android is the world’s most popular mobile operating system, powering billions of devices worldwide. Whether you’re an aspiring developer or just curious about how Android works, understanding the fundamentals is crucial. This in-depth guide covers everything from Android’s architecture to app development essentials and best practices. Let’s dive in!

What is Android?

Android is an open-source operating system developed by Google, based on the Linux kernel. It provides a flexible ecosystem for developers to build mobile applications and supports a wide range of devices, including smartphones, tablets, smart TVs, and even wearables.

Android Architecture

Android’s architecture consists of multiple layers, each playing a critical role in its functionality. Here’s a breakdown:

1. Linux Kernel

At the core of Android is the Linux kernel, which manages low-level operations like memory management, process scheduling, security, and hardware communication.

2. Hardware Abstraction Layer (HAL)

HAL provides standard interfaces that allow the Android OS to communicate with different hardware components like cameras, sensors, and Bluetooth.

3. Native Libraries

These libraries include essential components like OpenGL (for graphics rendering), SQLite (database storage), and WebKit (browser engine).

4. Android Runtime (ART)

Android Runtime (ART) is responsible for executing applications. It uses Just-In-Time (JIT) and Ahead-Of-Time (AOT) compilation to optimize app performance.

5. Application Framework

This layer provides APIs and services for developers to build and manage applications, including:

  • Activity Manager: Controls app lifecycle and navigation.
  • Content Providers: Manages shared data between apps.
  • Resource Manager: Handles UI elements like layouts and strings.

6. Applications

At the top of the stack, we have the user-facing applications, including built-in Google apps (Phone, Messages, Maps) and third-party apps from the Play Store.

Core Android Components

Android applications are built using four main components:

1. Activities

An activity represents a single screen in an app. It contains the UI elements that users interact with. Activities follow a lifecycle, managed through methods like onCreate(), onResume(), and onDestroy().

2. Services

Services run in the background without a user interface. They are used for tasks like playing music or fetching data.

3. Broadcast Receivers

These listen for system-wide broadcast messages like battery low alerts or network connectivity changes.

4. Content Providers

Content providers manage shared data and allow different apps to access it securely, such as the Contacts or MediaStore databases.

Getting Started with Android Development

To start building Android applications, you need the right tools and languages.

Programming Languages

  • Kotlin: The preferred language for Android development, offering concise and expressive syntax.
  • Java: The traditional language, still widely used and supported.

Development Tools

  • Android Studio: The official IDE for Android development.
  • Android SDK (Software Development Kit): Provides the tools and libraries needed to build Android apps.
  • Gradle: Manages project dependencies and build automation.

AndroidManifest.xml

This file declares essential app information like activities, permissions, and services.

Building User Interfaces in Android

Android provides various UI components to design engaging applications.

Layouts

  • LinearLayout: Arranges elements in a single row or column.
  • ConstraintLayout: A flexible layout with constraints for responsive design.
  • RelativeLayout: Allows positioning elements relative to each other.

Common UI Elements

  • TextView: Displays text.
  • EditText: Accepts user input.
  • Button: Triggers actions when clicked.
  • RecyclerView: Efficiently displays large lists or grids.

Fragments

Fragments are modular UI components that allow flexible designs, especially for tablets and large-screen devices.

Understanding Android Lifecycle

Activities and fragments follow a structured lifecycle to manage user interactions efficiently. Key methods include:

  • onCreate(): Called when the activity is first created.
  • onStart(): When the activity becomes visible.
  • onResume(): When the user interacts with the activity.
  • onPause(): When the activity goes into the background.
  • onStop(): When the activity is no longer visible.
  • onDestroy(): When the activity is destroyed.

Data Storage in Android

Android provides multiple storage options based on application needs:

1. Shared Preferences

Used to store small key-value pairs, ideal for settings and preferences.

2. SQLite Database

A lightweight, local database for structured data storage.

3. Room Database

An abstraction layer over SQLite, making database management easier with an ORM approach.

4. Cloud & Firebase Storage

For cloud-based data storage and real-time updates.

Networking in Android

Most apps require network communication. Popular libraries include:

  • Retrofit: A type-safe HTTP client for interacting with APIs.
  • Volley: A fast networking library for handling multiple requests.
  • OkHttp: A low-level HTTP client for efficient network calls.

Security and Permissions

Android enforces strict security measures to protect user data.

Runtime Permissions

Apps must request permissions at runtime for sensitive actions like accessing the camera, location, or contacts.

Encryption

Ensures data security during storage and transmission.

ProGuard & R8

Used to minify and obfuscate code, making reverse engineering difficult.

Publishing Your Android App

Once your app is ready, follow these steps to publish it:

1. Google Play Console

Register as a developer and upload your app.

2. App Signing

Securely sign your app to ensure authenticity.

3. App Monetization

Options include ads (Google AdMob), in-app purchases, and subscriptions.

Conclusion

Android development is an exciting and ever-evolving field. By understanding its architecture, components, and best practices, you can create powerful applications that provide excellent user experiences. Whether you’re a beginner or an experienced developer, mastering these fundamentals will set you on the path to success in Android development.

Kotlin Multiplatform Mobile (KMM)

What Is Kotlin Multiplatform Mobile (KMM) and Why Developers Are Switching in 2025

In the rapidly evolving world of mobile app development, one question keeps popping up in 2025:
“Is Kotlin Multiplatform Mobile (KMM) finally ready for prime time?”

The answer is a resounding yes.

Kotlin Multiplatform Mobile (KMM) has matured into a powerful tool that allows developers to share code across Android and iOS while still delivering a native user experience. With growing community support, enhanced tooling, and major production apps going multiplatform, it’s clear why many developers are making the switch.

Let’s break it all down in a simple way.

What Is Kotlin Multiplatform Mobile (KMM)?

Kotlin Multiplatform Mobile (KMM) is a feature of JetBrains’ Kotlin language that enables code sharing between Android and iOS apps. Unlike other cross-platform solutions like Flutter or React Native that render UI across platforms, KMM focuses on sharing business logic, not UI.

This means:

  • You write platform-independent code in Kotlin (like data models, business rules, network calls).
  • You write platform-specific UI with SwiftUI on iOS and Jetpack Compose on Android.

Here’s a visual breakdown:

               ┌──────────────────────────────┐
               │   Shared Kotlin Code (KMM)   │
               │  (Network, DB, Logic, etc.)  │
               └──────────────────────────────┘
                      ▲                 ▲
                      │                 │
        ┌─────────────┘                 └──────────────┐
        │                                              │
┌────────────┐                               ┌────────────┐
│ Android UI │                               │  iOS UI    │
│ Jetpack    │                               │ SwiftUI    │
└────────────┘                               └────────────┘

Why Are Developers Switching to KMM in 2025?

There are several reasons why Kotlin Multiplatform Mobile is trending in 2025. Let’s unpack the big ones:

1. Save Time, Save Money

Instead of writing the same logic twice (once in Kotlin and once in Swift), you write it once and share it. Teams can move faster without compromising on performance or UX.

2. Native Experience, No Compromise

KMM doesn’t touch your UI code. You still get fully native interfaces using the best platform-specific tools (SwiftUI and Jetpack Compose). This means your app feels right at home on both platforms.

3. First-Class Kotlin Support

Kotlin is now officially backed by Google for Android development and tightly integrated into JetBrains’ ecosystem. KMM benefits from constant language updates, better IDE tooling (especially in Android Studio and IntelliJ IDEA), and strong community support.

4. Flexible Adoption

You don’t have to rewrite your entire app. KMM allows gradual adoption. You can start with one shared module and expand as needed. It’s perfect for teams who want to test the waters without a full migration.

How KMM Works — A Simple Code Example

Let’s take a real-world example: fetching user data from an API and displaying it.

Step 1: Define the Shared Code

Inside the shared module:

commonMain/kotlin/UserRepository.kt

expect class HttpClientEngine()

class UserRepository(private val client: HttpClient = HttpClient(HttpClientEngine())) {
    suspend fun fetchUser(): User {
        val response = client.get("https://api.softaai.com/user") // just an example
        return Json.decodeFromString(response.bodyAsText())
    }
}

Here, expect means “I need a platform-specific implementation.” Kotlin will look for it in androidMain and iosMain.

Step 2: Android Implementation

androidMain/kotlin/PlatformHttpClient.kt

actual class HttpClientEngine {
    fun getEngine(): HttpClientEngine = Android.create()
}

Use Android-specific networking, like Ktor’s Android engine.

Step 3: iOS Implementation

iosMain/kotlin/PlatformHttpClient.kt

actual class HttpClientEngine {
    fun getEngine(): HttpClientEngine = Ios.create()
}

Same logic, but for iOS. You keep platform differences isolated and the rest of your business logic remains untouched.

What Makes KMM Developer-Friendly?

  • IDE Support: JetBrains has invested heavily in IntelliJ and Android Studio plugins that make working with shared code intuitive.
  • Official Libraries: Ktor (networking), Kotlinx Serialization, SQLDelight, and Coroutines work seamlessly with KMM.
  • Robust Testing: You can write unit tests for shared logic and run them across platforms.

Is KMM Production-Ready in 2025?

Yes — and it’s not just startups using it anymore.

Companies like VMware, Netflix, and Philips have integrated KMM into their production apps. JetBrains themselves use KMM in their own apps.

With Kotlin 2.0 officially supporting KMM and Kotlin/Native seeing major improvements in performance and stability, developers can now trust it for large-scale, production-grade apps.

When Should You Use Kotlin Multiplatform Mobile?

KMM is a great fit if:

  • You want code sharing between Android and iOS.
  • You want to retain full native UI control.
  • You already have Android developers familiar with Kotlin.
  • You prefer gradual migration over rewriting from scratch.

When NOT to Use KMM?

It might not be ideal if:

  • You want shared UI (in which case Flutter or React Native may suit better).
  • Your team lacks experience with Kotlin.
  • You’re targeting multiple platforms beyond mobile (e.g., Web + Desktop + Mobile).

Conclusion

Kotlin Multiplatform Mobile (KMM) has truly come of age in 2025. It’s no longer a niche experiment — it’s a production-ready, efficient, and modern way to build mobile apps with shared business logic and native performance.

RemoteViews

RemoteViews in Android: What It Is, How It Works, and Why It Matters

RemoteViews might not be something you think about often, but it plays a big role in many Android experiences you use every day. From home screen widgets to media controls in your notifications — and even the UI in Android Automotive dashboards — RemoteViews is quietly working behind the scenes.

But what exactly is RemoteViews? Why does Android need it in the first place?

In this post, we’ll break it all down. We’ll explore what RemoteViews is, how it works under the hood, where it’s commonly used, its limitations, and how it’s changing with modern Android development.

TL;DR: What Is RemoteViews?

RemoteViews is a mechanism in Android that lets you define and update UI components across different processes. It’s primarily used in:

  • Home screen app widgets
  • Custom notifications
  • Android Auto / Automotive OS UI templates
  • Legacy lock screen widgets

Because apps in Android run in isolated sandboxes (i.e., processes), RemoteViews offers a way to package simple view updates and deliver them to another process, like the system UI or launcher.

Why Does Android Need RemoteViews?

Android enforces strict process separation for security and performance. Each app runs in its own process, and the system UI — like the launcher or notification shade — runs in another. This design prevents one app from injecting arbitrary UI or code into another.

But what if your app needs to show a widget on the home screen? Or customize a rich notification with buttons and thumbnails?

That’s where RemoteViews comes in.

It acts like a deferred UI recipe: your app says, “I want to show this layout, with this text and image,” and Android takes care of rendering it safely in another process.

How RemoteViews Works (Under the Hood)

Let’s break down what happens behind the scenes:

1. You define a layout in XML, typically using a subset of supported views (TextView, ImageView, etc.).

2. You create a RemoteViews object in your app: 

val views = RemoteViews(context.packageName, R.layout.my_widget)
views.setTextViewText(R.id.title, "Hello World")
views.setImageViewResource(R.id.icon, R.drawable.my_icon)

3. You send it to the host process, like the AppWidgetManager or NotificationManager, using something like:

appWidgetManager.updateAppWidget(widgetId, views)

4. The system applies the layout and updates the UI in the context of the host process, ensuring it can’t be tampered with or crash the system UI.

Where RemoteViews Is Used

1. App Widgets (Home Screen Widgets)

The most classic use case. These are interactive UI snippets on your launcher that update periodically or in response to events (weather updates, calendars, to-do lists, etc.).

2. Custom Notifications

RemoteViews powers notification templates that include custom layouts — like music player controls, media thumbnails, and action buttons.

3. Android Automotive OS

Automotive dashboards require safe rendering of media apps. RemoteViews is used to define UI layouts that can be shown in car displays without exposing full UI control.

4. Lock Screen Widgets (Pre-Android 5.0)

Before Android Lollipop, apps could show widgets directly on the lock screen using RemoteViews.

Supported Views in RemoteViews

Not all views work with RemoteViews. Since everything must be serialized and sent across processes, only a subset of safe, lightweight views are supported:

Supported ViewsSupported Actions
TextViewsetTextViewText()
ImageViewsetImageViewResource()
ProgressBarsetProgressBar()
LinearLayout(limited, for stacking views)
ViewFlippershowNext() or showPrevious()
Chronometer, AnalogClockPartially supported

You can attach PendingIntents to certain views using setOnClickPendingIntent() for basic interactivity.

Limitations of RemoteViews

While RemoteViews solves a specific problem well, it’s not without trade-offs:

LimitationDescription
No custom viewsYou can’t use your own View subclasses or Compose UI
No animationsNo property animations, transitions, or motion effects
No real-time interactionCan’t handle gestures or live two-way data binding
Limited click supportOnly supports triggering PendingIntents on click
Tedious to update frequentlyYou must manually update RemoteViews and push to the host

Because of this, RemoteViews isn’t a full replacement for an activity or fragment—it’s a lightweight display mechanism.

RemoteViews in the Modern Android World

While RemoteViews is still widely used, especially for backward compatibility and automotive use cases, Google has introduced modern alternatives to make UI composition easier and more declarative:

Jetpack Glance (Recommended for Widgets)

Jetpack Glance is a modern Kotlin-based library for building app widgets using a Compose-like DSL. It abstracts RemoteViews under the hood but gives you a much more developer-friendly experience.

Notification Styles

If you’re building rich notifications, use Android’s built-in notification styles (MediaStyle, MessagingStyle, etc.) before falling back to custom RemoteViews.

When to Use RemoteViews (And When Not To)

Use It When…Avoid It When…
Building widgets or media-style notificationsBuilding full-featured or interactive UIs
Working with Android AutomotiveNeeding real-time feedback from users
You need safe cross-process UI renderingYou want fluid animations or dynamic layouts

Conclusion

Even in 2025, RemoteViews is still a core part of the Android ecosystem. It’s reliable, secure, and ideal for situations where your UI needs to run in a different process — like home screen widgets or notifications — and stay lightweight and sandboxed.

That said, Android’s UI development is evolving quickly. With modern tools like Jetpack Glance and Jetpack Compose, building UIs has become much more flexible and developer-friendly.

So, stick with RemoteViews when you need to — but don’t hesitate to adopt these newer, more powerful APIs when you can

FAQ

Q: Can I use Jetpack Compose with RemoteViews?
A: Not directly. However, Jetpack Glance offers a Compose-like way to build RemoteViews-compatible layouts.

Q: Is RemoteViews deprecated?
A: No, it’s still fully supported and maintained, especially in system-level use cases like Android Automotive and app widgets.

Q: Can RemoteViews support animations or gestures?
A: No. RemoteViews supports only limited click interactions via PendingIntent. Animations and complex gestures aren’t allowed.

Jetpack Glance

Jetpack Glance: A Modern Way to Build App Widgets in Android

Widgets are one of the oldest and most-loved features of Android. They let users access app content directly from the home screen, offering convenience, quick interactions, and persistent information.

But let’s be honest — building widgets used to be a pain. If you’ve ever dealt with RemoteViews, you probably remember how clunky and restrictive it felt. From limited layout options to awkward state updates, it often felt like using outdated tools in a modern development world.

Enter Jetpack Glance— a fresh, modern, and composable way to build Android app widgets.

In this blog, we’ll explore what Jetpack Glance is, how it works, why it matters, and how you can start building beautiful widgets that feel right at home in 2025.

What is Jetpack Glance?

Jetpack Glance is an Android Jetpack library that lets developers build app widgets using a declarative Kotlin API, inspired by Jetpack Compose. It’s designed to bring the modern development experience of Compose to Android widgets — without completely replacing the underlying AppWidget system.

Glance provides a Compose-like DSL for creating UI elements, handling interactions, and managing widget state. Under the hood, it still translates your code to the RemoteViews used by the Android system, ensuring full compatibility with homescreens and launchers.

Why Jetpack Glance Matters

If you’ve ever built widgets with XML and RemoteViews, you know how painful it can be. Layout constraints, limited interactivity, and poor testability were common complaints.

Jetpack Glance solves this by offering:

  • Declarative UI: Say goodbye to boilerplate XML. Use familiar composables like Text, Image, Row, Column, and Box.
  • Kotlin-first Development: Leverage the benefits of modern Kotlin and Compose practices.
  • Theming Support: Build widgets that match your app’s Material design and even adapt to dynamic colors.
  • Improved Readability and Maintainability: Code that’s easier to read, test, and update.
  • Compatibility with AppWidget System: Works seamlessly with Android’s native widget infrastructure.

Building UI with Glance Composables

Jetpack Glance offers a minimal set of UI elements modeled after Compose. Here’s what you can expect:

  • Text, Button, Image — for basic elements.
  • Row, Column, Box — for layouts.
  • LazyColumn — for scrollable lists (with limitations).
  • Spacer, Modifier, Padding, Alignment — to structure your layout.

These components are optimized for the widget framework, so you can’t use every Compose API, but it’s still a huge leap forward compared to traditional methods.

Kotlin
@Composable
fun MyWidgetContent() {
    Column(
        modifier = GlanceModifier.padding(16.dp)
    ) {
        Text("Hello Widget!")
        Button(
            text = "Open App",
            onClick = actionStartActivity<MainActivity>()
        )
    }
}

Handling User Interactions

Widgets aren’t just for display — they should be interactive. Glance makes this easier by providing built-in Action APIs.

You can define actions such as:

  • Launching Activities
  • Triggering Services
  • Sending Broadcasts
  • Executing Callbacks (via actionCallback)
Kotlin
Button(
    text = "Launch",
    onClick = actionStartActivity<MyActivity>()
)

Handling interactions has never been this straightforward in a widget context.

Theming and Styling

Glance supports both Material 2 and Material 3 themes, including dynamic color integration on supported devices. You can wrap your UI in a GlanceTheme to ensure consistent styling.

Kotlin
@Composable
fun ThemedWidget() {
    GlanceTheme {
        Text("Styled with Material 3")
    }
}

Glance adapts to light/dark mode and the device’s color palette, ensuring your widget looks native and polished.

State Management and Updates

Unlike Compose, which is reactive by default, Glance widgets are stateless and passive. That means you control when and how the widget updates.

You’ll typically use:

  • GlanceAppWidget.update(context) — to trigger a UI refresh.
  • GlanceStateDefinition — to persist data across updates.

It’s your job to observe changes (e.g., LiveData, WorkManager, or repository data) and update the widget manually when needed.

How to Get Started

Let’s walk through a simple step-by-step guide to help you get started with building widgets using Jetpack Glance.

1. Add Dependencies

Kotlin
dependencies {
    implementation "androidx.glance:glance-appwidget:1.1.1"
    implementation "androidx.glance:glance-material3:1.1.1"
}

2. Enable Compose Support

Kotlin
android {
    buildFeatures {
        compose = true
    }
    composeOptions {
        kotlinCompilerExtensionVersion = "1.5.15"
    }
}

3. Define Your Widget

Kotlin
class MyGlanceWidget : GlanceAppWidget() {
    @Composable
    override fun Content() {
        MyWidgetContent() 
    }
}

4. Register the Widget

Update your AndroidManifest.xml and provide metadata via a resource XML file like res/xml/my_widget_info.xml.

Kotlin
<appwidget-provider
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:resizeMode="horizontal|vertical"
    android:minWidth="250dp"
    android:minHeight="100dp"
    android:initialLayout="@layout/placeholder"
    android:updatePeriodMillis="1800000" />

Known Limitations

While Glance is a significant improvement, it’s still bound by the limitations of Android’s RemoteViews system:

  • No complex animations
  • Limited custom drawing or gestures
  • Limited real-time data updates

Expect more support in future releases, but for now, design within these constraints.

Conclusion

Jetpack Glance is a game-changer for Android widget development. It modernizes an aging system with a declarative approach that feels right at home in the Jetpack ecosystem.

Whether you’re updating legacy widgets or building new ones from scratch, Glance provides a smoother, more maintainable path forward.

So go ahead — give your users beautiful, functional widgets without the pain of XML and RemoteViews.

system design interview in 2 hours

How to Prepare for a System Design Interview in Just 2 Hours (Without the Panic)

System design interviews can feel like a maze — especially if you’re racing against the clock. Maybe you’ve been coding for years but never built large-scale distributed systems. Or maybe your interview is… today, and you’ve only got two hours to prepare.

Good news? That’s enough time to cover the most critical concepts and give a confident, structured answer that impresses any interviewer.

Whether you’re targeting top tech companies like FAANG or startups, this crash course blog is your realistic, no-fluff roadmap to nailing your next system design round.

What Is a System Design Interview, Really?

At its core, system design is about how you architect scalable, reliable, and maintainable software systems. Interviewers aren’t just checking if you can code — they want to know:

  • How do you break down a vague product requirement?
  • Can your design scale to millions of users?
  • What trade-offs are you aware of (latency vs consistency, cost vs performance)?
  • Do you communicate your ideas clearly?

You don’t need to design Google’s infrastructure in 45 minutes — but you do need to show structured thinking.

The 5-Step Framework That Works Every Time

Every successful system design interview follows this rough structure. Memorize it. Practice it. Make it second nature:

1. Clarify Requirements

Ask smart questions like:

  • Who are the users?
  • What are the core use cases
  • Do we care about latency, consistency, or availability more?

Example: In a URL shortener, do links expire? Do we track click analytics?

2. Define High-Level Architecture

Sketch the key components: client, API gateway, backend services, database, cache, CDN, etc.

3. Design Data Models

  • What data do we store?
  • What queries do we need to support?
  • Should we go SQL or NoSQL?

4. Handle Scale and Traffic

Now talk real-world:

  • Use load balancers to handle traffic spikes
  • Add caching to reduce DB load (Redis/Memcached)
  • Use sharding to horizontally scale your database
  • Use message queues to decouple services

5. Discuss Trade-offs & Bottlenecks

This is where you show maturity:

  • “To reduce latency, I’d introduce a cache — but stale data could be a concern.”
  • “We could shard by user ID, but we’ll need a lookup service to find the right shard.”

30 Minutes to Learn Key System Components (You Must Know These)

Before jumping into real-world problems, lock in these foundational building blocks:

ComponentWhat It DoesReal-World Use
Load BalancerDistributes incoming requests to serversNGINX, HAProxy, AWS ELB
CacheSpeeds up frequent reads by avoiding DB hitsRedis, Memcached
DatabaseStores structured dataSQL (Postgres, MySQL), NoSQL (MongoDB, Cassandra)
ShardingSplits DB across nodes for horizontal scalingCommon in high-scale apps
QueueDecouples async tasksKafka, RabbitMQ, Amazon SQS
CDNSpeeds up static content deliveryCloudflare, Akamai

If you understand these six, you can talk confidently about most design problems.

Now Let’s Design: 2 Must-Know Systems

You only have 2 hours. So focus on the most frequently asked designs. Learn the structure, not just the answer.

1. Design a URL Shortener (Like Bit.ly)

Functional Requirements:

  • Generate short links
  • Redirect to original URL
  • Track click analytics (optional)

High-Level Architecture:

  • API server
  • Database (SQL or NoSQL)
  • Cache for popular links (e.g., Redis)
  • Optional analytics pipeline

Design Details:

  • Use base62 encoding of auto-incrementing IDs
  • Or use hashing (MD5/SHA) + collision resolution
  • Store mappings in a key-value DB (e.g., DynamoDB)

Scale Consideration:

  • Add read replicas
  • Cache hot URLs
  • Use CDN for redirection page

2. Design a Messaging System (Like WhatsApp)

Functional Requirements:

  • Send/receive messages
  • Delivery receipts
  • Message history

Architecture:

  • User Service
  • Messaging Queue (e.g., Kafka)
  • Notification Service
  • NoSQL DB for chat history (e.g., Cassandra)

Scalability Tips:

  • Use message queues to decouple send/receive
  • Store messages in time-series DB or partition by user ID
  • Use WebSockets for real-time delivery

How to Talk During the Interview (Very Important!)

Interviewers care just as much about how you explain as what you explain. Use clear transitions:

  • “Let’s start with a high-level overview…”
  • “To scale this component, I’d use horizontal sharding…”
  • “Here’s a potential bottleneck and how I’d solve it…”

Speak confidently, and don’t get stuck in code-level details.

Final Checklist: What to Say & Do in the Interview

  • Ask clarifying questions
  • Think out loud
  • Use diagrams (draw boxes + arrows!)
  • Talk about scalability, latency, trade-offs
  • Keep it structured, not rambling
  • Finish with bottlenecks & improvements

Want to Go Deeper? (After the Interview)

If you get more time later, here’s what to study next:

Final Words: Confidence Beats Perfection

You don’t need to know everything. But with this 2-hour plan, you’ll walk into your interview:

  • With a framework
  • With working knowledge of key components
  • With 1–2 solid design examples ready

Remember: structure, clarity, and trade-offs are what interviewers love most.

Mastering Lua

Mastering Lua: A Beginner’s Guide to This Lightweight Yet Powerful Language

If you’re stepping into programming or looking for a scripting language that is lightweight, fast, and powerful, Lua is an excellent choice. Used in game development, embedded systems, and even AI, Lua offers simplicity without sacrificing capability. This guide will walk you through the essentials, helping you master Lua with ease.

What Is Lua?

Lua is a high-level, lightweight scripting language designed for speed and efficiency. It was created in 1993 by a team of Brazilian developers and has since gained popularity in game development (Roblox, World of Warcraft mods) and embedded applications.

Why Learn Lua?

  • Easy to Learn: Lua has a simple syntax, making it beginner-friendly.
  • Lightweight and Fast: Lua is designed for speed, consuming minimal system resources.
  • Highly Flexible: It supports procedural, object-oriented, and functional programming.
  • Widely Used in Game Development: Many games and engines, like Unity and Love2D, use Lua.

Setting Up Lua

Before diving into Lua programming, you’ll need to install it.

Installing Lua

  1. Windows: Download Lua from https://www.lua.org/download.html and install it.
  2. Mac: Use Homebrew:
Lua
brew install lua

Linux: Use the package manager:

Lua
sudo apt-get install lua5.4

Online Lua Interpreter: If you don’t want to install Lua, try an online interpreter like Replit.

Verify installation by running:

Lua
lua -v

This will display the installed Lua version.

Lua Basics

1. Hello, Lua!

Let’s start with the classic “Hello, World!” program.

Lua
print("Hello, Lua!")

Simply run this script, and you’ll see Hello, Lua! printed on the screen.

2. Variables and Data Types

Lua has dynamic typing, meaning variables do not require explicit type definitions.

Lua
name = "Amol"
age = 25
height = 5.9
isLearning = true

Lua supports:

  • Strings: "Hello"
  • Numbers: 10, 3.14
  • Booleans: true, false
  • Tables (similar to arrays and dictionaries)
  • Nil (represents an absence of value)

3. Conditional Statements

Lua uses if-then statements for decision-making.

Lua
score = 85
if score >= 90 then
    print("Excellent!")
elseif score >= 70 then
    print("Good job!")
else
    print("Keep practicing!")
end

4. Loops

For Loop

Lua
for i = 1, 5 do
    print("Iteration: ", i)
end

While Loop

Lua
count = 1
while count <= 5 do
    print("Count: ", count)
    count = count + 1
end

Functions in Lua

Functions help in structuring code efficiently.

Defining and Calling Functions

Lua
function greet(name)
    print("Hello, " .. name .. "!")
end

greet("Amol")

Here, the .. operator is used for string concatenation.

Returning Values

Lua
function add(a, b)
    return a + b
end

result = add(5, 3)
print("Sum: ", result)

Working with Tables (Arrays and Dictionaries)

Lua tables function as both arrays and dictionaries.

Array-like Table

Lua
fruits = {"Apple", "Banana", "Cherry"}
print(fruits[1])  -- Output: Apple

Dictionary-like Table

Lua
person = {name = "Amol", age = 30}
print(person.name)  -- Output: Amol

Object-Oriented Programming in Lua

While Lua doesn’t have built-in OOP, it can be implemented using tables and metatables.

Creating a Simple Class

Lua
Person = {}
Person.__index = Person

function Person:new(name, age)
    local obj = {name = name, age = age}
    setmetatable(obj, Person)
    return obj
end

function Person:greet()
    print("Hi, I am " .. self.name .. " and I am " .. self.age .. " years old.")
end

p1 = Person:new("Amol", 25)
p1:greet()

Error Handling

Use pcall (protected call) to catch errors gracefully.

Lua
function divide(a, b)
    if b == 0 then
        error("Cannot divide by zero!")
    end
    return a / b
end

status, result = pcall(divide, 10, 0)
if status then
    print("Result: ", result)
else
    print("Error: ", result)
end

Conclusion

Mastering Lua opens doors to game development, scripting, and embedded systems. With its simple syntax, high efficiency, and flexibility, it’s a fantastic choice for beginners and experienced developers alike. Keep practicing, build projects, and explore Lua’s potential further!

Jetpack Glance Media Playback

A Deep Dive into Using Jetpack Glance for Media Playback in Android Automotive OS

As vehicles evolve into digital experiences, the need for glanceable, fast, and distraction-free interfaces becomes paramount. In Android Automotive OS (AAOS), this demand has led to the emergence of the Jetpack Glance framework — a powerful tool for creating UI surfaces that are lightweight, fast to load, and safe for drivers to interact with.

In this blog post, we’ll explore how Jetpack Glance can be used to build a media playback card for Android Automotive OS. From setting up dependencies to implementing a full-featured glanceable media widget with play/pause/skip functionality — we’ll walk through the full picture with code, context, and best practices.

What is Jetpack Glance?

Jetpack Glance is a declarative UI library designed for building remote user interfaces, including:

  • App widgets (for Android homescreens)
  • Glanceable UIs for wearables (e.g., Tiles)
  • Future-facing vehicle dashboards and clusters in Android Automotive

Think of Glance as the Compose-inspired sibling of RemoteViews, but tailored for rendering quickly, efficiently, and safely on surfaces with strict interaction rules — like a car’s infotainment screen.

Why Use Glance in Android Automotive?

Using Glance in AAOS allows developers to:

  • Create lightweight UIs for media, navigation, or vehicle info
  • Ensure low distraction by adhering to system-level constraints
  • Maintain fast rendering even on constrained hardware
  • Leverage Jetpack Compose-like syntax without full Compose overhead

Key Use Cases in AAOS

Use CaseDescription
Media CardsDisplay now-playing info and basic playback controls
Navigation PreviewsShow turn-by-turn summaries or route cards
Vehicle StatusFuel, tire pressure, battery charge level
Contextual AlertsDoor open, low fuel, safety notifications

Setting Up Jetpack Glance in Your Project

Add Required Dependencies

Update your build.gradle with the latest Glance libraries:

Kotlin
dependencies {
    implementation "androidx.glance:glance:1.0.0"
    implementation "androidx.glance:glance-appwidget:1.0.0"
    implementation "androidx.glance:glance-wear-tiles:1.0.0" // optional
    implementation "androidx.core:core-ktx:1.12.0"
}

Tip: Glance is backward-compatible with Android 12 and above, making it suitable for most AAOS setups.

Creating a Glanceable Media Widget for AAOS

Let’s walk through a full example where we build a media playback widget that can be shown in a center display or cluster (with OEM support).

Define the Glance Widget

Kotlin
class MediaGlanceWidget : GlanceAppWidget() {
    @Composable
    override fun Content() {
        val title = "Song Title"
        val artist = "Artist Name"

        Column(
            modifier = GlanceModifier
                .fillMaxSize()
                .padding(16.dp)
                .background(Color.DarkGray),
            verticalAlignment = Alignment.CenterVertically,
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Text("Now Playing", style = TextStyle(fontWeight = FontWeight.Bold, color = Color.White))
            Spacer(Modifier.height(8.dp))
            Text(title, style = TextStyle(color = Color.White))
            Text(artist, style = TextStyle(color = Color.LightGray))

            Spacer(Modifier.height(16.dp))
            Row(horizontalAlignment = Alignment.CenterHorizontally) {
                Image(
                    provider = ImageProvider(R.drawable.ic_previous),
                    contentDescription = "Previous",
                    modifier = GlanceModifier.size(32.dp).clickable {
                        actionStartService<MediaControlService>("ACTION_PREVIOUS")
                    }
                )
                Spacer(Modifier.width(16.dp))
                Image(
                    provider = ImageProvider(R.drawable.ic_play),
                    contentDescription = "Play",
                    modifier = GlanceModifier.size(32.dp).clickable {
                        actionStartService<MediaControlService>("ACTION_PLAY_PAUSE")
                    }
                )
                Spacer(Modifier.width(16.dp))
                Image(
                    provider = ImageProvider(R.drawable.ic_next),
                    contentDescription = "Next",
                    modifier = GlanceModifier.size(32.dp).clickable {
                        actionStartService<MediaControlService>("ACTION_NEXT")
                    }
                )
            }
        }
    }
}

Handling Playback Actions: MediaControlService

Since Glance doesn’t support direct onClick behavior like Compose, we use a Service to act on UI interactions.

Kotlin
class MediaControlService : Service() {
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        when (intent?.action) {
            "ACTION_PLAY_PAUSE" -> togglePlayPause()
            "ACTION_NEXT" -> skipToNext()
            "ACTION_PREVIOUS" -> skipToPrevious()
        }
        return START_NOT_STICKY
    }

    private fun togglePlayPause() {
        // Hook into MediaSession or ExoPlayer
    }

    private fun skipToNext() {
        // Forward playback command
    }

    private fun skipToPrevious() {
        // Rewind playback
    }

    override fun onBind(intent: Intent?): IBinder? = null
}

Integrating with AndroidManifest.xml

To register the widget and service:

Kotlin
<receiver
    android:name=".MediaGlanceWidgetReceiver"
    android:exported="true">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>
    <meta-data
        android:name="android.appwidget.provider"
        android:resource="@xml/media_widget_info" />
</receiver>

<service
    android:name=".MediaControlService"
    android:exported="false" />

Widget Configuration XML

In res/xml/media_widget_info.xml:

Kotlin
<appwidget-provider
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="180dp"
    android:minHeight="100dp"
    android:updatePeriodMillis="60000"
    android:widgetCategory="home_screen" />

Best Practices for Automotive Glance UI

  • Keep UI distraction-optimized
  • Use readable font sizes and sufficient contrast
  • Avoid overloading the interface — 2–3 actions max
  • Make controls large and touch-friendly
  • Always test on real AAOS hardware or emulator

Conclusion

Jetpack Glance is quickly becoming a go-to tool for developers looking to build safe, fast, and flexible UI surfaces across Android form factors. In the automotive space, it shines by helping deliver minimalist, glanceable media controls that respect both performance and safety constraints.

As AAOS continues to evolve, expect more OEM support for Glance in clusters, dashboards, and center displays — especially with the push toward custom car launchers and immersive media experiences

What Is KDoctor? The Essential Tool Every Kotlin Multiplatform Developer Must Know in 2025

If you’re diving into Kotlin Multiplatform Mobile (KMM) development in 2025, chances are you’ve already come across tools like Android Studio, Xcode, and Gradle. But there’s one small, powerful tool that can make or break your setup experience: KDoctor. In this blog, we’ll explore what KDoctor is, why it’s a must-have for Kotlin Multiplatform developers,...

Membership Required

You must be a member to access this content.

View Membership Levels

Already a member? Log in here
error: Content is protected !!