Skip to content

Fundamentals


What is the Activity Lifecycle?

beginner android lifecycle fundamentals
View Answer

The Activity Lifecycle is the sequence of states an Android Activity transitions through from creation to destruction.

Android manages lifecycle callbacks automatically to:

  • optimize memory usage

  • restore UI state

  • handle multitasking

  • manage interruptions

Core lifecycle methods:

  • onCreate()

  • onStart()

  • onResume()

  • onPause()

  • onStop()

  • onDestroy()

๐Ÿš€ See Full Deep Dive


What's the difference between onStart() and onResume()?

beginner android lifecycle callbacks
View Answer

onStart(): Called when Activity becomes visible to user.

  • Window not yet in focus

  • Activity cannot receive user input

  • Use for resource allocation needed for UI visibility onResume(): Called when Activity gains focus and is ready for interaction.

  • Window is in focus

  • Can receive user input

  • Use for animations, camera, location updates Simple rule: onStart = visible, onResume = interactive.

๐Ÿš€ See Full Deep Dive


What is savedInstanceState and when is it called?

intermediate android lifecycle state-preservation
View Answer

savedInstanceState is a Bundle used to preserve Activity state during predictable destruction (rotation, low memory).

Called in order:

  1. onPause()

  2. onSaveInstanceState()

  3. onStop()

Common use cases:

  • Save fragment state

  • Save scroll position

  • Save form data

  • Save UI state Note: NOT called during activity finish() or user back press.

๐Ÿš€ See Full Deep Dive


What happens during configuration changes (rotation)?

intermediate android lifecycle configuration
View Answer

When device is rotated or configuration changes:

  1. onPause() โ†’ onSaveInstanceState() โ†’ onStop() โ†’ onDestroy()

  2. onCreate() โ†’ onStart() โ†’ onResume() The Activity is DESTROYED and RECREATED.

To preserve data:

  • Store in savedInstanceState Bundle

  • Use ViewModel (survives config changes)

  • Use retained fragments

  • Add android:configChanges to manifest Best practice: Use ViewModel for non-UI state.

๐Ÿš€ See Full Deep Dive


How does Android handle process death?

intermediate android lifecycle process-management
View Answer

Process death occurs when Android kills app to free memory (no warning, no lifecycle callbacks).

Recovery steps when user returns:

  1. OS restarts app process

  2. Activity onCreate() called with savedInstanceState

  3. App can restore state from Bundle Without state saving: Data loss, UI reset.

Solutions:

  • Implement onSaveInstanceState()

  • Use ViewModel + Room

  • Persist critical data to disk/database

  • Use Hilt for dependency injection

๐Ÿš€ See Full Deep Dive


What is the exact order of lifecycle callbacks?

beginner android lifecycle callbacks
View Answer

NORMAL SEQUENCE: onCreate() โ†’ onStart() โ†’ onResume() โ†’ (user interaction) โ†’ onPause() โ†’ onStop() โ†’ onDestroy()

VISIBLE BUT NOT INTERACTIVE: onStart() (no onResume yet - dialog shown)

ANOTHER APP IN FOREGROUND: onPause() โ†’ onStop() (but not onDestroy)

BACK TO APP: onStart() โ†’ onResume()

DEVICE ROTATION: onPause() โ†’ onSaveInstanceState() โ†’ onStop() โ†’ onDestroy() โ†’ onCreate() โ†’ onStart() โ†’ onResume()

๐Ÿš€ See Full Deep Dive


What's the difference between explicit and implicit intents?

beginner android intents ipc
View Answer

EXPLICIT INTENT:

  • Specifies exact component (Activity/Service)

  • Requires package name and class name

  • Use for internal app communication

  • Guaranteed to reach target

IMPLICIT INTENT:

  • No target component specified

  • System matches intent to components via intent filters

  • Used for cross-app communication

  • May show chooser if multiple matches

Example explicit: Intent(this, MainActivity::class.java)

Example implicit: Intent(Intent.ACTION_VIEW, Uri.parse("https://..."))

๐Ÿš€ See Full Deep Dive


How do intent filters work?

intermediate android intents manifest
View Answer

Intent filters declare which implicit intents a component can handle. Defined in AndroidManifest.xml inside activity/service/broadcast receiver.

Components:

  • action: What operation the component can perform

  • category: Additional flags about component

  • data: URI patterns, MIME types component accepts

Matching process:

  1. System receives implicit intent

  2. Matches against all declared intent filters

  3. Returns list of matching components

  4. Shows chooser if multiple matches

Example:

  • ACTION_VIEW + http:// MIME โ†’ Browser

  • ACTION_VIEW + image/* MIME โ†’ Gallery

๐Ÿš€ See Full Deep Dive


How does intent resolution work?

intermediate android intents ipc
View Answer

Intent resolution is Android's process of finding the target component for an implicit intent.

Steps:

  1. Find all installed apps with matching intent filters

  2. Filter by action (must match exactly)

  3. Filter by category (must have all requested)

  4. Filter by data (URI, MIME type must match)

If multiple matches:

  • Shows chooser dialog

  • User selects preferred app

  • System can remember preference

If no matches:

  • ActivityNotFoundException thrown Optimization: Use explicit intents for internal communication.

๐Ÿš€ See Full Deep Dive


What are common intent flags and their purposes?

intermediate android intents backstack
View Answer

FLAG_ACTIVITY_NEW_TASK:

  • Starts activity in new task

  • Used with contexts without activity (Services)

FLAG_ACTIVITY_SINGLE_TOP:

  • If activity at top of stack, calls onNewIntent() instead of onCreate()

  • Prevents duplicate stack entries

FLAG_ACTIVITY_CLEAR_TOP:

  • Clears all activities above target in stack

  • Target becomes top (or recreated if not running)

FLAG_ACTIVITY_NO_HISTORY:

  • Activity won't be kept in history

  • Never appears in back button

FLAG_ACTIVITY_CLEAR_TASK:

  • Clears entire task when new activity starts

๐Ÿš€ See Full Deep Dive


What is a PendingIntent and when should you use it?

intermediate android intents notifications
View Answer

PendingIntent wraps an intent to be executed later by another app. Key property: Grants permission to foreign app to execute intent with YOUR app's identity and permissions.

Common uses:

  • Notification tap actions

  • Alarm Manager

  • Widget buttons

  • Broadcast receivers

Types:

  • PendingIntent.getActivity()

  • PendingIntent.getService()

  • PendingIntent.getBroadcast() Important: Use FLAG_IMMUTABLE (Android 12+) for security. Always provide proper flags when creating.

๐Ÿš€ See Full Deep Dive


What is the Fragment lifecycle?

beginner android fragments lifecycle
View Answer

Fragment lifecycle is similar to Activity but with additional callbacks.

Key lifecycle methods:

  • onCreate(): Fragment created

  • onCreateView(): Create fragment UI (return layout)

  • onViewCreated(): UI created, set up views

  • onStart(): Fragment visible

  • onResume(): Fragment interactive

  • onPause(): Fragment loses focus

  • onStop(): Fragment not visible

  • onDestroyView(): UI destroyed

  • onDestroy(): Fragment destroyed

Key difference from Activity:

  • Fragments can be added/removed without destroying

  • UI lifecycle separate (onCreateView, onDestroyView)

  • Dependent on host Activity

๐Ÿš€ See Full Deep Dive


What are the differences between Fragments and Activities?

intermediate android fragments architecture
View Answer

ACTIVITY:

  • Screen-level UI component

  • Entry point in manifest

  • Can exist standalone

  • Own window/UI context

  • Heavy component

FRAGMENT:

  • Reusable UI component

  • Must be hosted in Activity

  • Can be easily replaced/swapped

  • Shares Activity's window

  • Lightweight, composable

Use fragments for:

  • Modular UI components

  • Tab navigation

  • Master-detail layouts

  • Reusable screens

Use activities for:

  • Screen entry points

  • Standalone screens

  • Navigation between major app sections

๐Ÿš€ See Full Deep Dive


How do fragments communicate with each other?

intermediate android fragments communication
View Answer

APPROACH 1: Shared ViewModel (BEST PRACTICE)

  • Both fragments access same ViewModel

  • ViewModel lives in Activity scope

  • Use LiveData for reactive updates APPROACH 2: Interface Callback

  • Fragment implements listener interface

  • Activity receives callback

  • Activity communicates with other fragment

  • More verbose, legacy approach APPROACH 3: Shared Preferences / Database

  • Persist data to storage

  • Both fragments read/observe

  • Good for persistent data APPROACH 4: Bundle Arguments

  • Pass data between fragments

  • Only during fragment creation

  • Not for ongoing communication Modern approach: Use ViewModel + LiveData.

๐Ÿš€ See Full Deep Dive


How does fragment back stack work?

intermediate android fragments backstack
View Answer

Fragment back stack is managed by FragmentManager.

When you call: fragmentManager.beginTransaction() .replace(R.id.container, newFragment) .addToBackStack(null) .commit()

Steps:

  1. Current fragment state saved

  2. New fragment created and added

  3. Transaction added to back stack

  4. User presses back: transaction reversed

Key methods:

  • addToBackStack(): Add to back stack

  • popBackStack(): Remove from back stack

  • addToBackStack(tag): Named back stack entry

Back navigation:

  • Pops last transaction

  • Replaces new fragment with old one

  • Restores previous fragment state Each Activity has own FragmentManager back stack.

๐Ÿš€ See Full Deep Dive


What's the best way to pass data to a Fragment?

beginner android fragments data-passing
View Answer

BEST PRACTICE: Use Bundle with constants

Recommended pattern: companion object { private const val ARG_USER_ID = "user_id" fun newInstance(userId: Int) = MyFragment().apply { arguments = Bundle().apply { putInt(ARG_USER_ID, userId) } } }

In onCreate(): val userId = arguments?.getInt(ARG_USER_ID) ?: 0

Why this approach:

  • Survives configuration changes

  • Works across process death

  • Type-safe with constants

  • Replicates Android best practices

DON'T:

  • Pass large or non-Parcelable objects as arguments

  • Use constructors with parameters

  • Access fragments without factory method

๐Ÿš€ See Full Deep Dive


What is Context and what are its types?

beginner android context fundamentals
View Answer

Context is an abstract class that provides access to app resources and system services. Think of it as: "Reference to the current application state."

Primary types:

APPLICATION CONTEXT:

  • Lives entire app lifetime

  • Accessible via getApplicationContext()

  • Use for singletons, global listeners

ACTIVITY CONTEXT:

  • Tied to Activity lifecycle

  • Available via 'this' or getContext()

  • Use for UI operations, dialogs

  • Destroyed when Activity destroyed

Common uses:

  • Start activities/services

  • Get system services (LocationManager, etc)

  • Access resources (strings, drawables)

  • Create databases, SharedPreferences

  • Show toasts, dialogs

๐Ÿš€ See Full Deep Dive


How can Context cause memory leaks?

intermediate android context memory
View Answer

Context memory leaks occur when Activity Context is referenced by long-lived objects.

PROBLEMATIC PATTERNS:

Activity context in singletons

object MySingleton { var context: Context? = null // WRONG! }

Inner class references Activity

class MyInnerClass { // Holds Activity ref fun doWork() {} }

Static references to Activity

companion object { var activity: Activity? = null // WRONG! }

SOLUTIONS:

  • Use application context for singletons

  • Use static inner class + WeakReference

  • Use dependency injection

  • Never store Activity in long-lived objects Memory leak chain: Activity โ†’ thread โ†’ singleton โ†’ leak

๐Ÿš€ See Full Deep Dive


When should you use Application Context vs Activity Context?

intermediate android context best-practices
View Answer

USE APPLICATION CONTEXT:

  • Get SharedPreferences

  • Create global singletons

  • Get system services used globally

  • Database creation

  • Any operation not tied to UI

DON'T use for:

  • UI operations (dialogs crash if Activity destroyed)

  • Showing toasts in some cases

  • Creating LayoutInflater

USE ACTIVITY CONTEXT:

  • Show dialogs

  • Create LayoutInflater

  • Start activities/services

  • UI-dependent operations

  • Access Activity-specific services

DON'T use for:

  • Long-lived objects (memory leak risk)

  • Singletons

  • Static references Simple rule: Use app context if possible, activity context only when UI operation is tied to current Activity.

๐Ÿš€ See Full Deep Dive


Why is it important to match Context lifetime with usage?

intermediate android context lifecycle
View Answer

Mismatching Context lifetime with usage causes:

  • Memory leaks (Activity never garbage collected)

  • Crashes (UI operation on destroyed context)

  • Data loss (operations interrupted)

EXAMPLE - Wrong: class Manager(val context: Activity) { // Holds Activity ref fun work() { / does work / } } // Activity destroyed but Manager still referenced โ†’ leak

CORRECT - Right: class Manager(val context: Context) { // Use generic Context fun work() { / does work / } } val manager = Manager(applicationContext) // App context

Key principle: Lifetime of Context >= Lifetime of code referencing it If code runs longer than Activity: use app context. If code tied to Activity: safe to use Activity context.

๐Ÿš€ See Full Deep Dive


What is a memory leak in Android?

beginner android memory performance
View Answer

A memory leak occurs when an object is no longer needed but remains referenced, preventing garbage collection.

Memory leak chain:

  1. Object created

  2. No longer needed (Activity destroyed, etc)

  3. But still referenced by another object

  4. Garbage collector can't reclaim memory

  5. Memory usage grows

Consequences:

  • Out of Memory (OOM) exceptions

  • App crashes

  • Degraded performance

  • Battery drain

  • Reduced available memory for other apps

Common Android leak sources:

  • Static references to Activities

  • Long-lived objects holding Activity context

  • Unregistered listeners/callbacks

  • Handler messages with Activity context

  • Inner classes retaining Activity

๐Ÿš€ See Full Deep Dive


How do you detect memory leaks?

intermediate android memory debugging
View Answer

TOOLS:

LeakCanary library

  • Automatically detects leaks

  • Shows leak chain

  • Most practical tool

Android Studio Memory Profiler

  • Record heap allocations

  • Take heap dumps

  • Inspect object references

Logcat

  • Watch for OOM errors

  • Monitor memory growth

PROCESS:

  1. Run app with LeakCanary/Profiler

  2. Perform action multiple times (navigate, rotate, etc)

  3. Look for memory growth pattern

  4. Take heap dump

  5. Inspect object references

  6. Trace back to root reference Key: Always check that objects can be garbage collected after they're no longer needed.

๐Ÿš€ See Full Deep Dive


What are common memory leak patterns in Android?

intermediate android memory patterns
View Answer

PATTERN 1: Static Activity Reference companion object { var activity: Activity? = null // WRONG! } Fix: Don't store Activity references as static. PATTERN 2: Inner Class Holding Activity inner class MyThread : Thread() { // Holds Activity ref override fun run() { doWork() } } Fix: Use static inner class + WeakReference PATTERN 3: Unregistered Listeners registerReceiver(myReceiver, filter) // Never unregistered Fix: Always unregister in onPause/onDestroy PATTERN 4: Handler Messages handler.postDelayed({ toast.show() }, 60000) // If activity destroyed before delay ends: leak Fix: Remove messages in onDestroy PATTERN 5: Long-Lived Objects Holding Context singleton.context = this // Long-lived singleton Fix: Use app context or WeakReference

๐Ÿš€ See Full Deep Dive


What are best practices to prevent memory leaks?

intermediate android memory best-practices
View Answer
  1. Prefer application context over Activity context

  2. Singletons, databases, shared preferences

  3. Any global operation

  4. Use WeakReference for Activity references

  5. Long-lived objects needing Activity

  6. Handler.Callback with WeakReference

  7. Always unregister listeners

  8. Broadcast receivers: unregister in onDestroy

  9. Sensors: unregister in onStop

  10. Event buses: unsubscribe in onDestroy

  11. Remove handlers/callbacks before destroying

  12. handler.removeCallbacks()

  13. handler.removeMessages()

  14. In onDestroy/onPause

  15. Use ViewBinding over findViewById

  16. Automatic null-out in onDestroyView

  17. Prevents view references

  18. Close resources properly

  19. Close streams, databases, cursors

  20. Try-with-resources for auto-close

  21. Use LeakCanary in development

  22. Catches leaks automatically

  23. Part of development workflow

๐Ÿš€ See Full Deep Dive


What is an ANR (Application Not Responding)?

beginner android performance anr
View Answer

ANR (Application Not Responding) occurs when main thread blocks for too long, preventing UI updates or input handling.

Timeout thresholds:

  • Foreground input dispatch: ~5 seconds

  • Broadcast receiver: 10 seconds

  • Service timeouts vary by API level and state

When ANR triggered:

  1. OS detects main thread unresponsive

  2. OS kills app

  3. System shows "waiting for..." dialog

  4. User can close app or wait

Result:

  • App crash

  • Bad user experience

  • Potential uninstall

  • Play Store warnings

Common causes:

  • Blocking main thread (I/O, network, computation)

  • Heavy UI operations

  • Infinite loops

  • Deadlock situations

  • Unoptimized database queries

๐Ÿš€ See Full Deep Dive


How do you prevent ANRs?

intermediate android performance anr
View Answer

RULE 1: Keep main thread operations quick

  • Maximum 100-200ms for user-facing operations

  • Don't do I/O, network, or heavy computation on main thread

SOLUTIONS:

Use threads for heavy work

Thread { heavyWork() }.start()

Use coroutines (modern approach)

viewModelScope.launch(Dispatchers.Default) { heavyWork() // Off main thread }

AsyncTask (legacy)

AsyncTask.execute { heavyWork() }

Optimize database queries

  • Index frequently queried columns

  • Avoid complex queries on main thread

  • Use query optimization

Lazy load data

  • Load progressively

  • Show skeleton/placeholder

  • Fetch full data in background

Profile with Profiler

  • Find slow operations

  • Optimize hotspots

๐Ÿš€ See Full Deep Dive


Why shouldn't you do network/I/O on main thread?

intermediate android threading performance
View Answer

Main thread responsibilities:

  • Handle user input (taps, scrolls)

  • Update UI views

  • Render frames (16.67ms per frame)

  • Handle system messages

Network/I/O characteristics:

  • Unpredictable duration (100ms to seconds+)

  • Can block indefinitely

  • May fail and retry

If you block main thread with I/O:

  • Input not processed (janky/unresponsive)

  • Frames skipped (dropped frames, jank)

  • ANR timeout triggered

  • UI freezes visibly to user Solution: Off-load to background thread

  • Main thread: responsive UI

  • Background thread: I/O, network, computation

  • Post results back to main thread for UI updates Modern approach: Coroutines val data = withContext(Dispatchers.IO) { fetchData() } // Automatically switches context

๐Ÿš€ See Full Deep Dive


What's jank and how do you measure it?

intermediate android performance rendering
View Answer

JANK: Visible stutter in UI animations/scrolling. Cause: Dropping frames due to main thread blocking.

Expected frame rate:

  • 60fps devices: frame every 16.67ms

  • 90fps devices: frame every 11.11ms

  • 120fps devices: frame every 8.33ms

If main thread busy > frame time:

  • Frame dropped

  • Animation/scroll stutters visibly

  • User sees jank

Measurement tools:

Profile GPU Rendering (dev options)

  • Visual graph on screen

  • Shows frame times

  • Green = good, yellow/red = jank

Android Studio Profiler

  • CPU, Memory, Network profiling

  • See main thread operations

FrameMetrics API

  • Programmatically measure frame times

  • Real user monitoring

Firebase Performance Monitoring

  • Production monitoring

  • Real user metrics Prevention: Keep main thread responsive (<5ms per operation).

๐Ÿš€ See Full Deep Dive


What is Looper and how does it work?

intermediate android threading looper
View Answer

Looper: Thread mechanism for processing messages in a queue.

How it works:

  1. Thread has message queue

  2. Looper continuously loops through queue

  3. Processes one message per iteration

  4. Blocks if queue empty

  5. Exits when quit() called Each thread has max 1 Looper.

Main thread always has Looper:

  • Created automatically by Android system

  • Processes UI messages, events

Background threads:

  • No Looper by default

Create manually if needed

Thread { Looper.prepare() // ... do work ... Looper.loop() // Start looping }.start()

Why Looper matters:

  • Thread-safe message passing

  • Ordered message processing

  • Foundation for Handler/HandlerThread

  • UI updates only on main thread (main Looper)

๐Ÿš€ See Full Deep Dive


What is Handler and how does it relate to Looper?

intermediate android threading handler
View Answer

Handler: Interface for sending messages to a Thread's message queue.

Relationship with Looper:

  1. Handler posts messages to queue

  2. Handler associated with Looper

  3. Looper processes messages from queue

  4. Handler executes callbacks on Looper's thread

Creating Handler: Handler(Looper.getMainLooper()) // Posts to main thread Handler() // Posts to current thread's Looper

Common uses: handler.post(Runnable) // Execute on handler's thread handler.postDelayed(Runnable, delay) // Delayed execution handler.sendMessage(Message) // Send message

Example - Update UI after background work: Thread { val result = doHeavyWork() mainHandler.post { updateUI(result) // Runs on main thread } }.start() Key: Handler provides thread-safe way to run code on specific thread.

๐Ÿš€ See Full Deep Dive


What is HandlerThread and when should you use it?

intermediate android threading handler
View Answer

HandlerThread: Thread with built-in Looper for handling messages.

Benefits over plain Thread:

  • Looper automatically created and started

  • Ready to receive messages immediately

  • Clean shutdown with quit()

  • No need for manual Looper.prepare()/loop()

Creating HandlerThread: val handlerThread = HandlerThread("MyThread") handlerThread.start() val handler = Handler(handlerThread.looper)

Use cases:

  • Background image processing

  • File I/O operations

  • Database operations

  • Any repeatable background task Best practice: Combine with Handler for thread-safe updates. Handler posts work โ†’ HandlerThread queue โ†’ Looper processes Remember: Always call quit() when done to avoid thread leaks.

๐Ÿš€ See Full Deep Dive


How can Handler cause memory leaks?

intermediate android handler memory
View Answer

Handler with delayed messages can leak Activity context.

Problem scenario: handler.postDelayed(Runnable { // Runnable holds implicit 'this' reference (Activity) }, 60000) // If Activity destroyed before delay ends: leak

Memory leak chain:

  1. Handler post delayed message

  2. Message queued for 60 seconds

  3. Activity destroyed (user navigates away)

  4. Message still in queue, holds Activity reference

  5. Activity cannot be garbage collected

  6. After 60 seconds, message executed (too late) SOLUTION 1: Use Handler with WeakReference class MyActivity : AppCompatActivity() { private val handler = Handler(Looper.getMainLooper()) private inner class MyRunnable : Runnable { override fun run() { / ... / } } } SOLUTION 2: Remove messages in onDestroy override fun onDestroy() { handler.removeCallbacks(myRunnable) super.onDestroy() } MODERN: Use coroutines instead (automatic cleanup).

๐Ÿš€ See Full Deep Dive


What is a Service in Android?

beginner android service fundamentals
View Answer

Service: Component for long-running operations in background.

Key characteristics:

  • No UI (unlike Activity)

  • Can run in background

  • Continues running even if app minimized

  • Has own lifecycle

  • Must be declared in manifest

When to use:

  • Music playback

  • Download files

  • Upload media

  • Sync data with server

  • Long-running computations

Service types:

STARTED SERVICE:

  • Runs indefinitely

  • Stopped explicitly or by system

  • No connection to caller

BOUND SERVICE:

  • Connected to caller via IPC

  • Provides interface for interaction

  • Stops when all clients unbind

FOREGROUND SERVICE:

  • Runs with visible notification

  • Higher priority, but can still be stopped by system/user

  • Used for user-aware background work Important: Services run on main thread by default. Use threads inside service for heavy work.

๐Ÿš€ See Full Deep Dive


What's the difference between Service and Thread?

intermediate android service threading
View Answer

THREAD:

  • Tied to single process/app

  • Dies when app killed

  • Lightweight

  • No persistence

SERVICE:

  • Can outlive Activity

  • System prioritizes keeping running

  • Has manifest declaration

  • Can be started by other apps (permission-based)

  • Less likely to be killed, but still possible

USE CASE: Heavy computation + don't need UI after? โ†’ Thread Need background work to survive Activity destroy? โ†’ Service

Example distinction:

  • Play music in Thread (stops when app closed)

  • Play music in Service (continues when minimized)

KEY DIFFERENCE:

Process priority:

  • Running service: Higher priority (less likely to be killed)

  • Background app with thread: Lower priority (killed first)

System Management:

  • Service: Managed by system

  • Thread: Not managed by system

๐Ÿš€ See Full Deep Dive


What is a bound service and how do you use it?

intermediate android service ipc
View Answer

Bound Service: Service offering interface for IPC to clients.

Steps to implement:

Create Service with Binder

class MyBoundService : Service() { inner class LocalBinder : Binder() { fun getService() = this@MyBoundService } }

Override onBind()

override fun onBind(intent: Intent?): IBinder { return LocalBinder() }

Bind from Activity

bindService(Intent(...), connection, Context.BIND_AUTO_CREATE)

Use ServiceConnection

object : ServiceConnection { override fun onServiceConnected(...) { val binder = service as Binder val service = binder.getService() } }

Lifecycle:

  • onBind() when first client binds

  • onUnbind() when last client unbinds

  • Service stops if no clients bound and not started Key: Bound service tied to client lifecycle. Unbind in onDestroy/onStop to prevent leaks.

๐Ÿš€ See Full Deep Dive


What is IntentService and when should you use it?

intermediate android service background-work
View Answer

IntentService (deprecated): Subclass of Service handling asynchronous requests.

Benefits:

  • Background thread automatically created

  • Processes one intent at a time (queue)

  • Auto-stops when queue empty

  • No manual threading needed

  • Simple to use

How it works:

  1. Create IntentService subclass

  2. Override onHandleIntent() (runs on bg thread)

  3. Send intents with startService()

  4. Threading automatically handled

  5. Auto-stops after processing

Example: class DownloadService : IntentService("Download") { override fun onHandleIntent(intent: Intent?) { // Background thread, won't block UI val file = downloadFile() // Network call OK } }

Problems (Android 8.0+):

  • Background execution restrictions

  • Use WorkManager instead

MODERN APPROACH: Use WorkManager for background work (better lifecycle management, persistence, backoff policy). Legacy but useful for understanding architecture.

๐Ÿš€ See Full Deep Dive


What is a Broadcast Receiver?

beginner android broadcasting messaging
View Answer

Broadcast Receiver: Component for receiving system/app messages.

Characteristics:

  • Listens for broadcast intents

  • Executes onReceive() when broadcast received

  • Can run even if app not open

  • No UI capability

  • Must be declared in manifest or registered

System broadcasts:

  • ACTION_BATTERY_LOW

  • ACTION_CONNECTIVITY_CHANGE

  • ACTION_BOOT_COMPLETED

  • ACTION_PACKAGE_INSTALLED

Types of receivers:

STATIC (Manifest-declared):

  • Declared in AndroidManifest.xml

  • System can start app just to deliver broadcast

DYNAMIC (Runtime-registered):

  • Registered in code via registerReceiver()

  • Active only while app running

  • Better for app-specific broadcasts

Example: class MyReceiver : BroadcastReceiver() { override fun onReceive(context, intent) { // Process broadcast } } Use cases: Battery level, connectivity, SMS, time changes.

๐Ÿš€ See Full Deep Dive


How do you register broadcast receivers securely?

intermediate android broadcasting security
View Answer

DYNAMIC REGISTRATION (Recommended):

Register in onCreate/onStart

registerReceiver(myReceiver, IntentFilter(ACTION))

Unregister in onDestroy/onStop

unregisterReceiver(myReceiver)

STATIC REGISTRATION (Manifest):

SECURITY BEST PRACTICES:

  1. Use specific intent filters (not catch-all) Only catch broadcasts you need

Check sender permissions

In onReceive(), verify sender is trusted

Require permissions for safety

android:permission="my.permission"

Limit receiving broadcasts

Use specific actions, not generic patterns

Android 8.0+ restrictions

  • Static receivers limited (battery optimization)

  • Use dynamic registration

  • Or use JobScheduler/WorkManager

Always unregister dynamic receivers

Prevents memory leaks and battery drain

๐Ÿš€ See Full Deep Dive


What are ordered and sticky broadcasts?

intermediate android broadcasting messaging
View Answer

NORMAL BROADCAST:

  • Sent to all matching receivers simultaneously

  • No guaranteed order

  • Receivers cannot affect each other

ORDERED BROADCAST:

  • Delivered to receivers one at a time

  • In priority order

  • Each receiver can modify result or abort

  • Only next receiver gets modified data

  • Use: sendOrderedBroadcast()

STICKY BROADCAST:

  • Deprecated and removed in Android 5.0+

  • Previously: Last broadcast value retained

  • New receivers got last value on register

  • Caused security/memory issues

Example ordered broadcast: sendOrderedBroadcast(intent, null, resultReceiver, handler, resultCode, resultData, resultExtras)

Receiver can:

  • setResultCode(newCode)

  • setResultData(newData)

  • abortBroadcast() // Stop delivery to others

Use cases:

  • NORMAL: Multiple unrelated receivers

  • ORDERED: Chain of responsibility pattern

  • System broadcasts all normal Best practice: Prefer explicit app-scoped communication (shared ViewModel/Flow or explicit broadcasts). LocalBroadcastManager is deprecated.

๐Ÿš€ See Full Deep Dive


What is the Android permission model?

beginner android permissions security
View Answer

ANDROID 5.0 (API 21) and below:

  • All permissions granted at install time

  • User reviews app's permission list pre-install

  • Cannot revoke individual permissions

ANDROID 6.0+ (Runtime permissions):

  • Permissions granted at runtime

  • Dangerous permissions require explicit user request

  • User can revoke permissions anytime

  • App handles permission denials gracefully

Permission categories:

NORMAL PERMISSIONS (auto-granted):

  • ACCESS_NETWORK_STATE

  • INTERNET

  • Safe permissions, no user prompt

  • Declared only in manifest

DANGEROUS PERMISSIONS (runtime):

  • CAMERA, MICROPHONE

  • READ_CONTACTS, WRITE_CALENDAR

  • ACCESS_FINE_LOCATION

  • Require explicit user request via dialog

SIGNATURE PERMISSIONS:

  • Only apps signed with same cert

CUSTOM PERMISSIONS:

  • App-defined permissions Best practice: Request permissions only when needed (ask on usage).

๐Ÿš€ See Full Deep Dive


How do you implement runtime permissions?

intermediate android permissions runtime
View Answer

STEPS:

Declare in manifest

Check permission at runtime

if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { // Request permission } else { // Use camera }

Request permission

ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), 100)

Handle response

override fun onRequestPermissionsResult( requestCode: Int, permissions: Array, grantResults: IntArray) { if (requestCode == 100) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { useCamera() } else { showPermissionDeniedMessage() } } }

MODERN APPROACH (Activity Result Contract): val cameraPermission = registerForActivityResult( ActivityResultContracts.RequestPermission()) { isGranted -> if (isGranted) useCamera() else showDeniedMessage() } cameraPermission.launch(CAMERA) Always handle permission denials gracefully.

๐Ÿš€ See Full Deep Dive


What are permission groups and how do they work?

intermediate android permissions groups
View Answer

Permission Groups: Dangerous permissions organized by functional groups. System shows one prompt per group.

Example groups: CALENDAR: READ_CALENDAR, WRITE_CALENDAR CAMERA: CAMERA CONTACTS: READ_CONTACTS, WRITE_CONTACTS, GET_ACCOUNTS LOCATION: ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION MICROPHONE: RECORD_AUDIO PHONE: PROCESS_OUTGOING_CALLS, READ_PHONE_STATE, etc. SENSORS: BODY_SENSORS SMS: READ_SMS, SEND_SMS, RECEIVE_SMS, etc. STORAGE: READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE PHOTOS: READ_MEDIA_IMAGES, READ_MEDIA_VIDEO, READ_MEDIA_AUDIO

How it works:

  1. User grants CALENDAR group permission

  2. System may group prompts for user clarity

  3. Grant decisions are per permission and can vary by Android version Important: Each permission still must be declared in manifest.

Best practice:

  • Request permissions on-demand (when first needed)

  • Request least required permissions

  • Explain why permission needed (context)

  • Handle denials gracefully (skip feature)

๐Ÿš€ See Full Deep Dive


What is AndroidManifest.xml and what does it contain?

beginner android manifest fundamentals
View Answer

AndroidManifest.xml: Main configuration file for Android app.

Contains:

PACKAGE NAME

package="com.example.myapp"

COMPONENTS

  • Activities

  • Services

  • Broadcast receivers

  • Content providers

PERMISSIONS

  • Required permissions

  • Custom permissions

FEATURES

  • Hardware features (camera, GPS)

  • Software features

VERSION INFO

  • versionCode, versionName

  • targetSdkVersion, minSdkVersion

APPLICATION METADATA

  • App icon, label, theme

  • Backup agent

  • Hardware acceleration flags

INTENT FILTERS

  • Which implicit intents components handle

  • Which apps can start component

Example: Note: Some settings now in build.gradle (build tools).

๐Ÿš€ See Full Deep Dive


How do you declare intent filters in manifest?

intermediate android manifest intents
View Answer

Intent filters declare which implicit intents a component accepts.

STRUCTURE:

COMPONENTS: ACTION: What the component does CATEGORY: Additional info about component DATA: URI/MIME type patterns

MATCHING RULES:

  • Implicit intent must match ALL declared filters

  • If multiple matches: chooser shown

EXAMPLE - Web link handler:

๐Ÿš€ See Full Deep Dive


What is Binder and how does IPC work in Android?

intermediate android ipc binder
View Answer

Binder: Android's Inter-Process Communication (IPC) mechanism.

Architecture:

  • Client process passes data to kernel

  • Kernel validates and transfers to server process

  • Server Binder thread processes request

  • Response sent back through kernel

Why Binder:

  • More efficient than traditional sockets

  • Thread pool management automatic

  • Reference counting built-in

  • Security: UID/PID tracking

Common uses:

  • Bound services

  • System services (LocationManager, etc)

  • Inter-app communication

  • Activity manager, package manager

AIDL (Android Interface Definition Language):

  • Define service interface

  • Compiler generates Binder stub/proxy

  • Client calls via proxy

  • Server handles in onBind()

AIDL workflow:

  1. Define .aidl file

  2. Build system generates code

  3. Implement service

  4. Bind and call methods Most apps use high-level APIs (Intent, services) but Binder is underlying mechanism.

๐Ÿš€ See Full Deep Dive


What is Zygote and how does it create app processes?

advanced android internals process
View Answer

Zygote: Special system process that launches all app processes.

Problem it solves:

  • Android apps need Android runtime (VM, libraries)

  • Starting VM for each app slow

  • Zygote pre-starts VM with framework loaded

How it works:

  1. Boot: Zygote process starts

  2. Loads Android framework

  3. Pre-initializes VM

  4. Enters listening mode

App launch requested

  • Activity Manager requests process from Zygote

  • Zygote forks itself (fork = copy entire process)

  • Child process = new app process

App process

  • Inherits Zygote's loaded framework

  • Minimal initialization time

  • Ready to run app code

Benefits:

  • App launch much faster

  • Less memory per app (shared framework)

  • Faster development iteration

Process hierarchy: init โ†’ Zygote โ†’ ActivityManager โ†’ App processes

Native/Java boundary:

  • Zygote is Java (runs on runtime)

  • Child processes also Java

  • System services communicate via Binder

Multiple Zygotes:

  • Android 12+: Secondary Zygote for compatibility

๐Ÿš€ See Full Deep Dive


What is the difference between ART and Dalvik?

advanced android runtime performance
View Answer

DALVIK (Android 2.2 - 4.4):

  • JIT (Just-In-Time) compilation

  • Compiles bytecode to native during app execution

  • Every run: recompiled (slower)

  • Lower app install size

  • Higher app startup time

  • Higher runtime memory usage

ART (Android 5.0+):

  • AOT (Ahead-Of-Time) compilation

  • Compiles bytecode to native at install time

  • Always runs native code (faster)

  • Larger app install size

  • Faster app startup

  • Lower runtime memory usage

  • Predictable performance

COMPARISON: Performance: ART faster (precompiled) Startup: ART much faster Battery: ART better (less CPU work) Storage: Dalvik smaller app size Install time: ART slower (compilation)

JIT vs AOT:

  • JIT: optimize while running

  • AOT: optimize before running

ART advantages:

  • More predictable performance

  • Better garbage collection

  • Improved debugging

  • Better battery life

  • Faster app startup Modern Android: Hybrid

  • Base app compiled AOT at install

  • JIT during app execution

  • Combines both benefits

๐Ÿš€ See Full Deep Dive


What happens when you launch an app?

intermediate android startup lifecycle
View Answer

APP STARTUP FLOW:

  1. User taps app icon

  2. Launcher sends Intent to ActivityManager

  3. ActivityManager checks if process exists

  4. No: requests process from Zygote

  5. Yes: use existing process

  6. Zygote fork creates new process (or uses existing)

  7. New process reads app manifest

  8. Process loads Application class

  9. Application.onCreate() called

  10. Process loads Activity

  11. Activity lifecycle starts: onCreate โ†’ onStart โ†’ onResume

  12. Activity rendered on screen

OPTIMIZATION OPPORTUNITIES:

App startup time stages

  • Cold start: No process exists (slowest)

  • Warm start: Process exists but Activity not (medium)

  • Hot start: Activity in memory but paused (fastest)

Optimize for cold start

  • Lazy load modules

  • Don't block Application.onCreate()

  • Defer non-essential initialization

  • Use StartupManager library

  • Profiling: Use startup profiler

Improve perceived performance

  • Show splash screen

  • Load skeleton/placeholder

  • Progressive content loading

System captures startup metrics:

  • first frame (visible)

  • fully drawn (interactive) Modern approach: Activity Result API, lazy Fragment initialization.

๐Ÿš€ See Full Deep Dive


Why is RecyclerView more efficient than ListView?

intermediate android ui performance
View Answer

LISTVIEW DRAWBACKS:

  • Creates View for each list item

  • Never destroys views when scrolled off

  • List of 100 items = 100 Views in memory

  • Heavy GC pressure

  • Janky scrolling

RECYCLERVIEW IMPROVEMENTS:

  • Reuses View objects (recycled pools)

  • Only creates Views for visible items

  • Off-screen views returned to pool

  • Pool size = ~10-15 views

  • Original 100 items but only ~10 views created

How recycling works:

  1. View scrolls off screen

  2. Adapter called with holder+position

  3. onBindViewHolder updates data

  4. View repositioned with new content

  5. No new View created

ARCHITECTURE:

  • RecyclerView: Container

  • Adapter: Binds data to views

  • ViewHolder: Holds view references (pattern)

  • LayoutManager: Positions views

  • ItemAnimator: Animations

Key efficiencies:

  • View reuse (memory efficient)

  • Predictable scroll performance

  • Animations support

  • Multiple layout types

  • Item decoration/spacing

Best practices:

  • Use ViewBinding in ViewHolder

  • Avoid heavy operations in onBindViewHolder

  • Load images asynchronously

  • Use DiffUtil for updates

๐Ÿš€ See Full Deep Dive


How does Android render UI frames?

intermediate android rendering performance
View Answer

RENDERING PIPELINE (per frame):

MEASURE

  • Layout system calculates view dimensions

  • ViewGroup measures children

  • Recursive: child measures own children

LAYOUT

  • System positions views using measured sizes

  • ViewGroup places children at x,y coordinates

DRAW

  • Canvas API draws views

  • Each View.onDraw() paints content

  • Composited into single frame buffer

COMPOSITE

  • Hardware accelerator combines layers

  • Handles transparency, transformations

DISPLAY

  • GPU sends frame to display

  • Vsync synchronized (60/90/120 fps)

TIMING BUDGET (60 fps):

  • 16.67 milliseconds per frame

  • Measure/Layout/Draw/Composite: <16.67ms

  • Miss budget: Frame dropped, jank visible

OPTIMIZATION:

Reduce View hierarchy

  • Fewer views = faster measure/layout

  • Use merge, include, ViewStub

Use ViewHolder pattern

  • Avoid repeated findViewById

Avoid layout thrashing

  • Don't measure in layout

  • Batch layout updates

Use hardware acceleration

  • Enabled by default

  • Use Layer types for animations Profiling: GPU rendering debug, Layout Inspector.

๐Ÿš€ See Full Deep Dive


What are the different storage options in Android?

beginner android storage data
View Answer

SHARED PREFERENCES

  • Key-value store

  • SharedPreferences.getSharedPreferences()

  • Best for small data (settings, flags)

  • Lightweight

  • NOT encrypted

INTERNAL STORAGE

  • App-private directory

  • Deleted when app uninstalled

  • Default choice for app data

  • Secure (not accessible by other apps)

EXTERNAL STORAGE

  • Public folders (/DCIM, /Pictures, /Documents)

  • Shared with other apps

  • Requires permissions

  • May not exist on all devices

DATABASE (SQLite)

  • Structured data

  • Room library (ORM)

  • Relational queries

  • Good for complex data

CONTENT PROVIDERS

  • Expose data to other apps

  • Standardized data access interface

  • Used for contacts, photos, etc

CACHE

  • context.getCacheDir()

  • Temporary data

  • Can be cleared by system

  • Don't expect data persistence

Rules:

  • Small settings: SharedPreferences

  • Complex data: Room Database

  • Cross-app: ContentProvider

  • Temporary: Cache

  • Media: External storage Best practice: Use Room for structured data.

๐Ÿš€ See Full Deep Dive


What is a Task and back stack in Android?

intermediate android backstack navigation
View Answer

TASK: Collection of activities arranged in backstack.

Each task has:

  • One backstack

  • Activities from multiple apps possible

  • Identified by taskId

  • Shown in recents BACKSTACK: LIFO (Last-In-First-Out) structure

  • Activities arranged in order launched

  • Current activity at top

  • User press back: removes top activity

EXAMPLE BACKSTACK (top to bottom): [Activity D] โ† Current [Activity C] [Activity B] [Activity A] โ† Home/root

User presses back: [Activity D] removed โ†’ [Activity C] shown

FLAGS AFFECTING BACKSTACK:

FLAG_ACTIVITY_NEW_TASK:

  • New activity starts in new task

FLAG_ACTIVITY_CLEAR_TOP:

  • Removes all activities above target

  • Target becomes top

FLAG_ACTIVITY_SINGLE_TOP:

  • If activity at top: calls onNewIntent()

  • Doesn't create duplicate

MULTI-APP TASKS:

  • TaskX contains ActivityA(App1), ActivityB(App2)

  • Back press: goes to App1 or App2

  • Task spans apps

Best practice:

  • Use Navigation Component (handles backstack)

  • Understand task management

  • Use flags appropriately

๐Ÿš€ See Full Deep Dive


What happens to app state when process is killed?

advanced android lifecycle process
View Answer

PROCESS DEATH: OS kills app process to free memory (no warning).

BEFORE KILL (chance to save):

  • onSaveInstanceState() called

  • Stored in Bundle

  • Persisted by system

DURING KILL:

  • Process terminated

  • No cleanup callbacks possible

  • In-memory state lost

  • No warning given

ON USER RETURN:

If Activity saved state

  • OS recreates process

  • onCreate(savedInstanceState) called

  • App can restore Bundle data

If no saved state

  • Activity restarted fresh

  • UI reset

DATA LOSS:

  • In-memory variables lost

  • Unsaved changes lost

  • ViewModels destroyed

  • Connections closed

PRESERVATION STRATEGIES:

savedInstanceState

  • Light data (Bundles, primitives)

  • ~100KB limit

  • Configuration changes + process death

ViewModel

  • Survives configuration changes

  • Lost on process death

  • Use with savedInstanceState

Database

  • Persistent storage

  • Survives everything

  • Use for critical data

Preferences

  • Settings persistence

  • Survives everything Best practice: ViewModel + Room Database + savedInstanceState for robust state management.

๐Ÿš€ See Full Deep Dive


How does multitasking affect activity lifecycle?

intermediate android lifecycle multitasking
View Answer

MULTITASKING SCENARIOS:

SPLIT SCREEN

  • Two apps visible simultaneously

  • Both in foreground state

  • Both receive onResume()

  • Top activity interactive, other visible

PICTURE-IN-PICTURE

  • App playing video in small window

  • onPause() called (not visible)

  • Continues running

  • User can interact with background

APP SWITCHING (Recents)

  • Swipe from other app

  • Current Activity: onPause โ†’ onStop

  • Switched app: onStart โ†’ onResume

  • Current app not destroyed (still in memory)

LIFECYCLE IMPACT:

Old app (going background): onPause() โ†’ onStop()

New app (coming foreground): onStart() (if first time) or onStart() โ†’ onResume() (if was paused)

IMPORTANT:

  • onPause() called for BOTH foreground apps

  • Only top activity "interactive"

  • Other visible but not interactive

CONSEQUENCES:

  • Stop CPU-heavy operations in onPause()

  • Resume operations in onResume()

  • Don't assume onStop() means background

  • May be visible but not interactive Example: Video player in split screen

  • visible but onPause() called

  • Should pause playback in onPause()

  • Resume in onResume()

๐Ÿš€ See Full Deep Dive


Explain Android i18n correctness - plurals, gender-neutral text, number formatting, and locale handling

intermediate android i18n localization plurals
View Answer

Android i18n goes beyond string translation โ€” plurals, date/number formats, and text direction all change based on locale and must be handled by platform APIs, not hardcoded logic.

In interviews, cover:

  • plurals: use resources with quantity strings (zero, one, two, few, many, other); getQuantityString(R.plurals.x, count, count) โ€” never concatenate count + " items" in code

  • number formatting: NumberFormat.getInstance(locale).format(n) or NumberCompat; never hardcode commas or periods as decimal separators โ€” they are locale-specific

  • date formatting: use DateTimeFormatter with explicit locale; avoid toString() on Date/Calendar classes which use the system default locale

  • locale configuration changes: configuration change when the user switches language results in an Activity recreation; ensure ViewModels are locale-independent (store raw data, not formatted strings)

Strong answer tip:

  • test by forcing locale with LocaleList.setDefault() in an Espresso test or using the ADB command: adb shell am start -a android.intent.action.MAIN --locale de_DE

๐Ÿš€ See Full Deep Dive


Explain RTL layout support - bidirectional text, icon direction, and meaning preservation

intermediate android rtl bidirectional layout
View Answer

Android flips horizontal layout automatically in RTL locales when supportsRtl=true is set in the manifest, but logical mirroring of meaning (not just geometry) requires explicit design attention.

In interviews, cover:

  • enable RTL: android:supportsRtl="true" in ; use start/end instead of left/right in layout attributes; layout direction flips automatically

  • icons: directional icons (back arrow, forward arrow, skip) must be mirrored in RTL; non-directional icons (play, settings, share) must not; use android:autoMirrored="true" in SVG drawables for directional ones or provide explicit -ldrtl resources

  • bidirectional text (BiDi): a string with mixed Arabic and English characters; rely on BidiFormatter or android:textDirection="locale" rather than hardcoding LTR/RTL text direction on TextViews

  • padding/margin: Modifier.padding(start=16.dp) in Compose, paddingStart in Views โ€” these automatically flip in RTL

Strong answer tip:

  • test with: adb shell settings put global debug.force_rtl 1 (developer option) to force RTL on any locale without actually changing device language

๐Ÿš€ See Full Deep Dive


Explain accessibility at scale - audit strategy, semantics coverage, and keyboard/D-pad navigation

intermediate android accessibility a11y talkback keyboard
View Answer

Accessibility at scale requires systematic auditing, not ad-hoc fixes; semantic coverage, focus order, and touch target size are the three most common failure classes.

In interviews, cover:

  • semantic coverage: every interactive element needs a contentDescription or labelFor; group related elements with mergeDescendants; use Role (Button, Checkbox, Image) so TalkBack announces the correct interaction model

  • touch target size: Material spec recommends 48ร—48dp minimum; Modifier.minimumInteractiveComponentSize() enforces this in Compose; small tap targets fail WCAG 2.5.5

  • focus order: keyboard and D-pad navigation must follow a logical reading order; customise with Modifier.focusProperties { next = focusRef } in Compose or android:nextFocusDown in Views

  • audit tooling: Accessibility Scanner app, Android Studio Layout Inspector accessibility tab, and automated checks via UiAutomator with AccessibilityNodeInfoCompat

Strong answer tip:

  • integrate automated accessibility checks into your UI test suite using AccessibilityChecks.enable() in Espresso โ€” this runs Google's accessibility test framework on every test run and catches regressions before code review

๐Ÿš€ See Full Deep Dive