Amazon Android App Development Interview Questions & Answers
Curated interview practice questions with answers. These are practice scenarios, not a verified list of past interview questions.
About Amazon hiring for Android App Development roles
Amazon is a global technology company spanning e-commerce, cloud computing through AWS, devices, advertising and streaming. In India it runs large engineering, operations and analytics teams supporting both Amazon.in and global businesses. It hires for software development engineers, SDETs, quality assurance engineers, business intelligence engineers, data engineers and data scientists.
For Android App Development roles, this Amazon practice set focuses most on Networking and APIs (5), Testing, Performance and Play Store (5), Room, DataStore and WorkManager (5), Android Components and Lifecycle (4). It has 22 medium, 8 hard questions, so you can start easy and work up to the harder ones.
Company type
Product
Headquarters
Seattle, USA
Main India offices
Bengaluru, Hyderabad, Chennai, Pune, Gurugram
Amazon Android App Development interview process
Online assessment (coding + work style survey)
Technical round 1 (DSA)
Technical round 2 (DSA or system design)
Bar raiser round
Hiring manager round
Typical pattern based on public candidate experiences. Rounds vary by role, team and year.
Solved for AmazonStart 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
Images in a feed load slowly and the app runs out of memory. What do you change?
Use an image library like Coil, which handles memory and disk caching, request downsampling to the view size, and cancellation when items scroll away. Ask the backend or CDN for resized, compressed images such as WebP instead of full-size originals. Use placeholders and crossfade, avoid holding Bitmaps in ViewModels, and set memory cache limits. Profile with Memory Profiler to confirm the large allocations are gone.
02
What is a BroadcastReceiver and what limits apply since Android 8?
A BroadcastReceiver responds to broadcast intents. Since Android 8, most implicit broadcasts cannot be received by receivers declared in the manifest; you register them at runtime with registerReceiver while the app is running. A few exemptions exist, like BOOT_COMPLETED and locale change. Since Android 14, runtime receivers must specify RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED. onReceive runs on the main thread, so keep it short or use goAsync.
03
Users on slow 2G and 3G networks in small towns report the app keeps failing. How do you improve it?
Set reasonable connect and read timeouts, retry idempotent requests with exponential backoff, and cache responses so screens show something offline. Reduce payload size with gzip, pagination and fields filtering, and load images in smaller sizes with placeholders. Show clear offline and retry states instead of generic errors. Test with the emulator network throttling and real devices on poor connections, and track failure rates by network type.
04
Write a unit test for a ViewModel using a fake repository and runTest.
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)
}
}
05
Your banking app must pass a security audit. What would you check on the Android side?
Check secure storage with Keystore and no secrets in code, TLS only with pinning where justified, no sensitive data in logs, FLAG_SECURE on sensitive screens, root and tamper checks using Play Integrity, exported components reviewed, WebView with JavaScript bridges restricted, R8 obfuscation, session timeout, and biometric authentication with BiometricPrompt and CryptoObject. Use the OWASP MASVS as the checklist and fix findings by severity.
06
How should a Fragment or Activity collect a Flow safely?
Use lifecycleScope.launch with repeatOnLifecycle(Lifecycle.State.STARTED) so collection starts when the UI is visible and stops in the background, avoiding wasted work and crashes from updating views that are not ready. In a Fragment, use viewLifecycleOwner.lifecycleScope because the fragment view can be destroyed while the fragment lives. In Compose, use collectAsStateWithLifecycle(), which does the same lifecycle-aware collection.
07
What is the difference between a deep link and an Android App Link?
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.
Track crash-free users and ANR rate in Play vitals and Crashlytics, keeping them below Play's bad behaviour thresholds of 1.09 percent user-perceived crash rate and 0.47 percent ANR rate. Monitor startup time, slow and frozen frames, network error rates and key funnel metrics like login success. Read Play reviews and ratings by version. Set alerts and review these numbers in every release meeting.
A Baseline Profile is a list of classes and methods used in critical journeys like startup and scrolling, shipped with the app. The Android Runtime uses it to compile that code ahead of time on install, avoiding slow interpretation and JIT on first runs. You generate it with the Baseline Profile Gradle plugin and Macrobenchmark tests. Compose and many Jetpack libraries ship their own profiles, but an app-specific one gives larger gains.
SavedStateHandle is a key-value map available to a ViewModel that is saved into the instance state Bundle, so it survives process death as well as configuration changes. Navigation arguments are also placed in it automatically. Use it for small, essential UI state like a search query, selected filter or the ID of the item being edited. Do not put large lists in it; reload those from the repository.
11
Write code to fetch two API results in parallel inside a ViewModel.
Keep one Activity hosting a NavHost, and represent each screen as a Compose destination or Fragment. Define routes in a navigation graph, preferably with type-safe routes using Kotlin serialization in Navigation 2.8 and later. Use nested graphs for flows like login or checkout, pop the back stack with popUpTo when finishing a flow, and handle deep links on destinations. This simplifies shared transitions and state handling.
13
How do you share data between two screens in a checkout flow?
Options in order of preference: pass small IDs as navigation arguments and load the rest from a repository; store flow data in a repository scoped to the session; or use a ViewModel scoped to a nested navigation graph so all checkout screens share it and it is cleared when the flow ends. Avoid activity-scoped ViewModels holding everything, and avoid passing large objects through arguments.
14
How do you refresh an expired access token automatically?
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.
15
A WorkManager job is not running on some phones from certain manufacturers. How do you investigate?
Some manufacturers apply aggressive battery optimisations that delay or kill background work. Check the job state with WorkManager's getWorkInfosForUniqueWorkFlow and the background task inspector in Android Studio. Verify constraints are not too strict. Guide users to allow unrestricted battery for the app only where the feature truly needs it, use expedited work for urgent tasks, and use FCM to trigger sync when timely delivery matters.
16
Users who reinstall the app lose all their settings. How can you restore them?
Android Auto Backup automatically backs up app data to the user's cloud backup account for apps targeting API 23 and above, unless disabled. Configure dataExtractionRules for Android 12 and above to include settings files and exclude tokens or caches. For important data like notes, sync to your own server tied to the user's account, since backup is not guaranteed. Test with adb shell bmgr commands.
17
Your app shows duplicate orders when users tap Pay twice on a slow network. How do you fix it?
Disable the button and show progress once tapped, but do not rely only on the UI. Generate an idempotency key on the client for each checkout attempt and send it with the request so the server returns the same result for retries. Ensure the payment call is not retried automatically by OkHttp for non-idempotent POSTs, and let the user check order status if the response is lost.
18
Two screens show different values for the same cart count. How do you fix the architecture?
Each screen probably fetches and caches its own copy. Create a single CartRepository, scoped as a singleton, that owns cart data in Room or an in-memory StateFlow, and have both ViewModels observe its Flow instead of keeping private copies. Mutations go through the repository so every observer updates automatically. This enforces the single source of truth and removes the need for manual refresh calls between screens.
19
Write a Flow that combines user settings and product list into one UI state.
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https"
android:host="shop.example.com"
android:pathPrefix="/product" />
</intent-filter>
</activity>
<!-- autoVerify plus assetlinks.json on the domain makes it an App Link -->
21
Write a suspend function that wraps a callback-based API.
Store the response in Room, or a file for a single blob, and have the screen observe the cached data immediately while a refresh runs in the background, known as stale-while-revalidate. Store a timestamp to decide when cache is too old. HTTP caching with OkHttp Cache can also help for GET requests with proper cache headers. Show cached content first, then update smoothly when fresh data arrives.
23
Tell me about a time you worked closely with a backend team to solve a problem.
Situation: our feed took four seconds to load because the app made six API calls. Task: reduce load time. Action: I measured each call with network profiling, shared a timeline with the backend team, and we agreed on one aggregated endpoint with only the fields the screen used, plus pagination. I updated the client and added caching. Result: load time dropped to under one second and both teams reused the approach.
24
What is the Paging 3 library and how does it work with Room?
Paging 3 loads large datasets in pages to save memory and network. A PagingSource loads pages, Pager exposes Flow<PagingData>, and the UI uses LazyPagingItems in Compose or PagingDataAdapter in RecyclerView. With a RemoteMediator, the network fills Room and Room acts as the PagingSource, giving offline support and a single source of truth. Use cachedIn(viewModelScope) to survive configuration changes.
25
How does Compose interoperate with existing XML views?
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.
26
Explain LaunchedEffect, DisposableEffect and SideEffect.
LaunchedEffect(key) launches a coroutine when it enters composition and restarts when the key changes, used for one-time loads or showing a snackbar. DisposableEffect(key) runs setup and requires an onDispose block for cleanup, used for registering listeners or lifecycle observers. SideEffect runs after every successful recomposition to publish Compose state to non-Compose code, such as analytics. Choose keys carefully so effects do not restart unexpectedly.
27
What is CompositionLocal and when should you use it?
CompositionLocal passes data implicitly down the tree without threading it through every parameter, like LocalContext, LocalDensity or MaterialTheme values. Create one with compositionLocalOf when values change often, or staticCompositionLocalOf when they rarely change. Use it for cross-cutting values like theme or analytics loggers, not for regular screen data, because implicit dependencies make composables harder to understand and test.
28
Write a Gradle configuration for release signing and minification using environment variables.
Use SharedPreferencesMigration when creating the DataStore: preferencesDataStore(name = "settings", produceMigrations = { ctx -> listOf(SharedPreferencesMigration(ctx, "old_prefs")) }). On first access, DataStore copies the values and deletes the old file. Update all reads and writes to go through the new repository at once, because mixing both stores leads to inconsistent values. Test the migration with existing preference files.
Tips to crack the Amazon Android App Development interview
Prepare STAR-format stories for each Amazon Leadership Principle, such as Customer Obsession, Ownership and Dive Deep.
Practise medium-level DSA problems on arrays, trees, graphs and dynamic programming, explaining time and space complexity aloud.
For BIE or data roles, practise SQL window functions and metric-driven case questions on e-commerce funnels and delivery operations.
Keep a one-minute story ready for every project on your CV: problem, your part, tools, result.
Practise the hard questions on this page aloud; Amazon interviewers usually ask follow-ups on your first answer.
Frequently asked questions
How many rounds are there in the Amazon Android App Development interview?
Candidates usually go through 5 stages: Online assessment (coding + work style survey); Technical round 1 (DSA); Technical round 2 (DSA or system design); Bar raiser round; Hiring manager round. The exact rounds change with the role, team, location and your experience, so confirm the process with the recruiter.
Which topics should I prepare for the Amazon Android App Development interview?
This practice set leans on Networking and APIs (5), Testing, Performance and Play Store (5), Room, DataStore and WorkManager (5), Android Components and Lifecycle (4). Revise those first, then practise explaining one or two of your own projects end to end, because most Amazon interviewers ask you to walk through real work.
Are these the exact questions asked at Amazon?
No. These are curated practice questions that match the skills and difficulty usually tested in product interviews like Amazon's. They are not a leaked or verified list of past questions.
Where does Amazon hire Android App Development professionals in India?
Amazon has large teams in Bengaluru, Hyderabad, Chennai, Pune, Gurugram. Openings and locations change often, so check the Amazon careers page and filter by city and experience.
Android App Development questions for similar companies