Skip to content

Android App Development Interview Questions in Kolkata

36 practice questions with answers for Android App Development interviews in Kolkata.

Android App Development jobs in Kolkata

Kolkata has a steady IT-services and BFSI technology job market around Salt Lake Sector V and New Town. Many openings are with service companies and their delivery centres, with a focus on strong fundamentals.

Below are 36 questions that match the mix of service, product and domain employers hiring junior android developers in Kolkata.

Solved for KolkataStart practicing
3 QUESTIONS FREESign up to unlock the full question bank and track your progress.Unlock every question and answer, then continue practising company-wise and package-wise.
3 questions free Unlock the rest in seconds
01

The Play Store rejected your update for a policy violation about permissions. What do you do?

Save to ▾
Show answer
Read the rejection email and policy centre message carefully to see which permission or declaration failed, often SMS, call log, background location, all-files access or exact alarms. Remove the permission if a less sensitive alternative exists, such as the SMS Retriever API or photo picker. Otherwise update the permission declaration form with a clear use case and video. Check the merged manifest for permissions added by libraries.
02

What does R8 do in a release build?

Save to ▾
Show answer
R8 shrinks code by removing unused classes and members, optimises bytecode by inlining and removing dead branches, obfuscates names to make reverse engineering harder and reduce size, and shrinks resources when enabled. It needs keep rules for code accessed by reflection, such as some serialization or SDK classes. Upload the mapping file to Play Console and Crashlytics so obfuscated stack traces can be decoded.
03

Write a Hilt module that provides Retrofit and a repository binding.

Save to ▾
Show answer
@Module @InstallIn(SingletonComponent::class) object NetworkModule { @Provides @Singleton fun provideRetrofit(): Retrofit = Retrofit.Builder() .baseUrl("https://api.example.com/") .addConverterFactory(Json.asConverterFactory("application/json".toMediaType())) .build() @Provides @Singleton fun provideApi(retrofit: Retrofit): ShopApi = retrofit.create(ShopApi::class.java) } @Module @InstallIn(SingletonComponent::class) abstract class RepoModule { @Binds abstract fun bindRepo(impl: ProductRepositoryImpl): ProductRepository }
04

Write a use case that combines cart items and a coupon into a final total.

Save to ▾
Show answer
class GetCartTotalUseCase @Inject constructor( private val cartRepo: CartRepository, private val couponRepo: CouponRepository ) { operator fun invoke(): Flow<Double> = combine(cartRepo.items, couponRepo.activeCoupon) { items, coupon -> val subtotal = items.sumOf { it.price * it.qty } val discount = coupon?.let { minOf(subtotal * it.percent / 100, it.maxOff) } ?: 0.0 subtotal - discount } }
05

A crash says IllegalStateException: Can not perform this action after onSaveInstanceState. What is happening?

Save to ▾
Show answer
A fragment transaction or dialog show was committed after the Activity saved its state, usually because a network callback finished while the app was in background. Committing then would lose state. Fix by triggering navigation only when the lifecycle is at least STARTED, collecting events with repeatOnLifecycle, or deferring the action. commitAllowingStateLoss hides the crash but can lose the transaction, so use it only when that is acceptable.
06

What is a coroutine and how is it different from a thread?

Save to ▾
Show answer
A coroutine is a suspendable computation that can pause at suspension points without blocking the thread it runs on. Thousands of coroutines can share a small thread pool because suspended coroutines do not hold a thread. Threads are managed by the OS, are heavier in memory and context switching. On Android, coroutines let you write asynchronous code like network calls in a sequential style, without callbacks, while keeping the main thread free.
07

What happens on a configuration change such as screen rotation?

Save to ▾
Show answer
By default the system destroys and recreates the Activity so it can load resources for the new configuration, like landscape layouts or a new language. Fields in the Activity are lost, but a ViewModel survives because it is kept by the ViewModelStore. Views with IDs restore some state automatically, and rememberSaveable in Compose restores small state. Handling changes manually via configChanges is possible but should be a deliberate choice.
08

What is the difference between a deep link and an Android App Link?

Save to ▾
Show answer
A deep link is any intent filter that opens your app for a URI; if several apps can handle it, the user sees a chooser. An App Link is an HTTPS deep link verified with android:autoVerify and a Digital Asset Links file at /.well-known/assetlinks.json on your domain, containing your app's signing certificate fingerprint. Verified links open your app directly. Remember to include the Play App Signing key fingerprint.
09

How does Compose interoperate with existing XML views?

Save to ▾
Show answer
To use Compose inside views, add a ComposeView to an XML layout or Fragment and call setContent, setting a ViewCompositionStrategy suited to the lifecycle. To use a view inside Compose, wrap it with AndroidView(factory = { MapView(it) }, update = { }). This allows migrating screen by screen, starting with new screens or leaf components. Share the theme using a Compose theme adapter or by mirroring tokens.
10

Write a suspend function that wraps a callback-based API.

Save to ▾
Show answer
suspend fun FusedLocationProviderClient.awaitLastLocation(): Location? = suspendCancellableCoroutine { cont -> lastLocation .addOnSuccessListener { cont.resume(it) } .addOnFailureListener { cont.resumeWithException(it) } cont.invokeOnCancellation { /* cancel request if supported */ } } // For streams of callbacks, use callbackFlow { } with awaitClose { }.
11

What is the difference between Job and SupervisorJob?

Save to ▾
Show answer
With a regular Job, a failing child cancels its parent and all siblings. With a SupervisorJob, or inside supervisorScope, a child failure does not affect siblings or the parent; each child handles its own errors. viewModelScope uses a SupervisorJob, so one failed launch does not kill other work in the ViewModel. Use supervisor behaviour when tasks are independent, like loading separate widgets on a dashboard.
12

Where do you see yourself in five years as an Android developer?

Save to ▾
Show answer
Keep it genuine and tied to growth. For example: in five years I want to be a senior or lead Android engineer who owns the architecture of a large app, mentors juniors and works closely with product on decisions. I plan to deepen my skills in performance, Compose and Kotlin Multiplatform, and contribute to the team's engineering practices. I hope to grow that path in a company like this one.
13

How do you find and fix memory leaks in an Android app?

Save to ▾
Show answer
Add LeakCanary to debug builds; it detects retained Activities, Fragments and ViewModels and shows the reference chain. Common leaks are static or singleton references to Context or Views, listeners not unregistered, inner classes holding Activity references, and Fragment view bindings not cleared in onDestroyView. Fix by using application context, lifecycle-aware components and weak references only where needed. Confirm with Memory Profiler heap dumps.
14

Explain the three phases of a Compose frame.

Save to ▾
Show answer
Each frame goes through composition, which decides what UI to show by running composables; layout, which measures and places each element; and drawing, which renders pixels. State read in a phase only invalidates that phase and later ones. Reading scroll state inside Modifier.offset { } or drawBehind defers the read to layout or draw, skipping recomposition entirely, which is a key optimisation for animations and scrolling effects.
15

Write code to show a notification with a channel.

Save to ▾
Show answer
fun showOrderNotification(context: Context, text: String) { val channelId = "orders" if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel( channelId, "Order updates", NotificationManager.IMPORTANCE_DEFAULT) context.getSystemService(NotificationManager::class.java) .createNotificationChannel(channel) } val n = NotificationCompat.Builder(context, channelId) .setSmallIcon(R.drawable.ic_order) .setContentTitle("Order update") .setContentText(text) .setAutoCancel(true) .build() NotificationManagerCompat.from(context).notify(1001, n) }
16

Tell me about a time you handled a production crash under pressure.

Save to ▾
Show answer
Situation: after a release, crash-free users dropped from 99.6 to 97 percent. Task: stop the impact fast. Action: I checked Crashlytics, found a crash on Android 14 caused by a missing foreground service type, paused the staged rollout in Play Console, shipped a hotfix with a test on an emulator for that API level, and wrote a short postmortem. Result: crash rate recovered within a day and we added API-level checks to our release checklist.
17

What does the inline keyword do and when should you use reified?

Save to ▾
Show answer
inline tells the compiler to copy the function body and lambda bodies into the call site, avoiding the object allocation for lambdas and enabling non-local returns. It suits small higher-order functions called often. reified can only be used in inline functions and keeps the generic type available at runtime, so you can write inline fun <reified T> Gson.fromJson(json: String) and use T::class. Avoid inlining large functions since it increases bytecode size.
18

What is a use case in the domain layer and when is it worth adding?

Save to ▾
Show answer
A use case is a class with one job, like GetDiscountedCartTotalUseCase, typically exposing operator fun invoke. It holds business logic that combines repositories or is reused by several ViewModels. It keeps ViewModels thin and logic testable. For simple apps where the ViewModel only calls one repository method, use cases add boilerplate without benefit, so the domain layer is optional in the official guidance.
19

Write a unit test for a ViewModel using a fake repository and runTest.

Save to ▾
Show answer
class ProductViewModelTest { @get:Rule val mainRule = MainDispatcherRule() @Test fun loadsProductsIntoState() = runTest { val fake = FakeProductRepository(listOf(Product("1", "Pen", 10.0))) val vm = ProductViewModel(fake) advanceUntilIdle() val state = vm.state.value assertFalse(state.loading) assertEquals(1, state.items.size) assertNull(state.error) } }
20

How do you refresh an expired access token automatically?

Save to ▾
Show answer
Use an OkHttp Authenticator, which is called when the server returns 401. Inside it, synchronise so only one refresh runs at a time, call the refresh endpoint with the refresh token, save the new tokens and return the original request with the new header. If the request already carried the latest token and still failed, or refresh fails, return null and log the user out. Limit retries to avoid loops.
21

A teammate uses !! everywhere to silence compiler errors. How do you handle this in code review?

Save to ▾
Show answer
Explain calmly that !! converts a compile-time check into a possible runtime crash. Suggest alternatives per case: safe calls with ?.let, Elvis with a default or early return, requireNotNull with a clear message, or fixing the type at the source so it is non-null. Add a detekt rule to flag !! in new code. Pair with them on one file so the change feels like help, not criticism.
22

How do you write tests for a Room DAO?

Save to ▾
Show answer
Create an in-memory database with Room.inMemoryDatabaseBuilder in an instrumented test or with Robolectric, get the DAO, insert test data and assert query results. For Flow queries, collect the first value with first() or use Turbine. Close the database in @After. Test edge cases like conflict strategies and ordering. In-memory databases are fast and isolated, so each test starts clean.
23

The app shows an ANR when the user taps Save. The save function is suspend. What could be wrong?

Save to ▾
Show answer
A suspend function does not automatically run off the main thread. If it calls blocking code, like a synchronous file write, a SharedPreferences commit, a blocking SDK or heavy JSON parsing, it still blocks the main thread. Check with a profiler or StrictMode. Fix by wrapping the blocking part in withContext(Dispatchers.IO) or Default, or by using main-safe APIs such as Room suspend DAOs or DataStore.
24

A Compose list scrolls with jank on low-end phones. How do you investigate and fix it?

Save to ▾
Show answer
Test a release build with R8, since debug builds are much slower. Use Layout Inspector recomposition counts and a system trace or Macrobenchmark to find hot spots. Common fixes: add keys and contentType, avoid heavy work or sorting inside composables, move computation to the ViewModel, use derivedStateOf for scroll-based state, defer state reads with lambda modifiers like offset { }, load images at the right size with Coil, and add a Baseline Profile.
25

How do you handle exceptions in coroutines?

Save to ▾
Show answer
Use try-catch around suspend calls for expected failures like network errors; this is the clearest approach. A CoroutineExceptionHandler on a root launch catches uncaught exceptions as a last resort for logging, but it does not work for async or child coroutines. For async, exceptions surface at await. Always rethrow CancellationException. Many teams wrap results in a Result or sealed type so the UI layer gets an explicit error state.
26

How do you make Compose UI accessible?

Save to ▾
Show answer
Give icons and images a meaningful contentDescription, or null when decorative. Keep touch targets at least 48dp, which Material components handle by default. Use semantics modifiers to merge descendants for list items, mark headings with heading(), and describe custom actions. Support font scaling by using sp and avoiding fixed heights for text. Check colour contrast and test with TalkBack and the Accessibility Scanner.
27

What is the difference between remember and rememberSaveable?

Save to ▾
Show answer
remember keeps a value across recompositions but loses it when the composable leaves composition, on configuration change or process death. rememberSaveable stores the value in the saved instance state Bundle, so it survives rotation and process death; it works with types that can go in a Bundle or with a custom Saver. Use rememberSaveable for things like text input or selected tab, and a ViewModel for screen-level data.
28

A ViewModel has grown to 1500 lines handling many responsibilities. How would you refactor it?

Save to ▾
Show answer
First add tests around current behaviour so refactoring is safe. Then extract business logic into use cases or domain classes, move data mapping into repositories or mappers, and split UI state into smaller, focused data classes. If the screen truly has separate areas, consider separate state holders or child ViewModels per section. Refactor in small pull requests so reviewers can follow and regressions are easy to locate.
29

What is the difference between val and var in Kotlin?

Save to ▾
Show answer
val declares a read-only reference that cannot be reassigned after initialisation, while var declares a mutable reference. Note that val does not make the object immutable: a val pointing to a MutableList can still have items added. Prefer val by default because it makes code easier to reason about and safer in concurrent code, and switch to var only when reassignment is genuinely needed.
30

What is the difference between List and MutableList, and is List truly immutable?

Save to ▾
Show answer
List is a read-only interface exposing only reading operations, while MutableList adds add, remove and set. A List is not guaranteed immutable: the underlying object might be an ArrayList that another reference can still modify. For real immutability use kotlinx.collections.immutable or create defensive copies. In ViewModels, expose List or StateFlow<List> publicly and keep the mutable version private to protect state.
31

A crash report shows a NullPointerException in Kotlin code. How can that happen if Kotlin is null safe?

Save to ▾
Show answer
Common causes are the !! operator, platform types from Java code without nullability annotations, accessing a lateinit property before assignment, calling a function from a constructor before properties are initialised, and reflection-based libraries like Gson setting non-null fields to null. Fix it by removing !!, adding annotations or explicit nullable types at the Java boundary, and using a Kotlin-aware serializer such as kotlinx.serialization or Moshi with Kotlin codegen.
32

How do you handle a code review comment you disagree with?

Save to ▾
Show answer
I first assume the reviewer has a reason and ask questions to understand it. If I still disagree, I explain my reasoning with evidence, such as documentation, a benchmark or a test, and suggest a short call if comments go back and forth. If it is a matter of preference, I follow the team convention. The goal is the best code for the team, not winning the argument.
33

How do you implement theming with Material 3 in Compose?

Save to ▾
Show answer
Wrap the app in a MaterialTheme with a ColorScheme, Typography and Shapes. Use lightColorScheme and darkColorScheme, pick based on isSystemInDarkTheme(), and use dynamicLightColorScheme or dynamicDarkColorScheme on Android 12 and above for Material You colours. Components read MaterialTheme.colorScheme.primary and similar roles, so avoid hardcoding colours. Extend the theme with a custom CompositionLocal for brand-specific tokens.
34

Tell me about a time you learned a new language or framework quickly for a project.

Save to ▾
Show answer
Situation: my team switched a feature to Kotlin when I only knew Java. Task: deliver a profile screen in two weeks. Action: I spent the first evenings on the official Kotlin koans, converted small utility classes first, and asked a senior to review my early pull requests for idiomatic usage. Result: the screen shipped on time, and my later code needed far fewer review comments. I now learn by building something small immediately.
35

What is MVVM and why is it recommended for Android?

Save to ▾
Show answer
MVVM splits an app into Model (data and business logic), View (Activity, Fragment or composable that renders state) and ViewModel (holds UI state and handles user events). The ViewModel survives configuration changes and has no reference to views, so it is easy to unit test. The View observes state from the ViewModel through StateFlow or LiveData. This separation reduces bugs from lifecycle issues and keeps UI code thin.
36

Write a function that safely parses a string to an Int and returns a default on failure.

Save to ▾
Show answer
fun String?.toIntOrDefault(default: Int = 0): Int = this?.trim()?.toIntOrNull() ?: default // Usage val qty = input.text.toString().toIntOrDefault(1) val age = null.toIntOrDefault() // 0

Frequently asked questions

Which companies hire Android App Development professionals in Kolkata?

Companies with large offices in Kolkata include many IT services and product firms. Use their company pages below to practise employer-specific sets.

Are Android App Development interviews in Kolkata different from other cities?

The questions depend more on the company than the city. Kolkata's mix of employers decides the style: Many openings are with service companies and their delivery centres, with a focus on strong fundamentals

How do I find Android App Development jobs in Kolkata?

Shortlist companies with Kolkata offices, keep your CV focused on Android App Development projects, apply on company career pages and job portals with the Kolkata filter, and practise the questions on this page before each interview.