Modern Android applications commonly use Kotlin, AndroidX, Jetpack libraries, and
Jetpack Compose. Platform APIs remain in android.*; AndroidX supplies
version-compatible and higher-level APIs in androidx.*. An application package has
multiple system-managed entry points rather than a conventional process-wide
main() method.
Application Isolation #
Android assigns an installed package a Linux UID and gives its private files UID-based ownership. An application process runs its own Android Runtime instance, and cross-package component calls use Binder IPC. Runtime permissions, SELinux, and framework service checks supplement the UID boundary.
Shared UIDs were once available to equally signed packages but are deprecated for new applications because they weaken package isolation. Applications share data through explicit interfaces, such as a permission-protected content provider, document picker, URI grant, or Binder service, rather than through private paths.
Components and the Manifest #
Android has four component types:
- An activity hosts a focused user interface.
- A service performs work without an activity UI. Long-running user-visible work requires a foreground-service notification and is subject to platform limits.
- A broadcast receiver performs a short response to a broadcast and should delegate lengthy work to an appropriate scheduler.
- A content provider exposes structured data through a
ContentResolverAPI.
The manifest declares application components, permissions, package visibility where
needed, minimum SDK level, features, and application metadata. A component with an
intent filter is externally addressable only if its android:exported setting and
the applicable permissions permit it. Keep non-public components unexported.
Intents and Component Activation #
An explicit intent identifies a particular component. An implicit intent describes an action, data, categories, and optional extras; the system resolves it against exported intent filters. Use explicit intents for internal operations and services, because an implicit service intent can resolve to an unintended component.
Activities launch through startActivity or the Activity Result APIs. Services use
startService, startForegroundService, or bindService according to their
execution model. Content providers receive operations through ContentResolver.
Background work that does not need immediate execution belongs in WorkManager or,
where appropriate, JobScheduler rather than a long-lived background service.
Treat all incoming intents, extras, and URIs as untrusted input. Verify callers where the API permits it, validate values, require permissions for sensitive components, and grant URI permissions only as narrowly and briefly as required.
Activity Lifecycle and State #
The system creates an activity with onCreate, makes it visible through onStart,
and makes it interactive through onResume. onPause indicates that the activity
has lost foreground focus; it must return quickly. onStop follows when the
activity is no longer visible and is the appropriate place to release resources
needed only while visible.
An activity object can be destroyed because finish was requested or because the
system reclaims its process. onSaveInstanceState stores small, reconstructible UI
state for the latter case. The framework saves supported view-hierarchy state, but
application state belongs in a ViewModel, saved-state handle, database, or other
durable store according to its size and lifetime. Do not use a lifecycle callback to
perform an unbounded network transaction or database migration.
Resources #
The Android resource system compiles res/ entries into generated identifiers such
as R.string.app_name. Place each resource in a typed top-level directory, such as
layout, drawable, mipmap, values, xml, font, menu, raw, anim, or
animator. Assets placed in assets/ are not compiled into R and are opened
through AssetManager.
Resource qualifiers select the most appropriate alternative for configuration, locale, screen size, density, orientation, and night mode. Qualifiers must use the documented order and may not repeat a qualifier type. Keep a default resource for every resource the application references, because a device configuration might not match a specialized alternative.
Kotlin, Jetpack, and Compose #
Kotlin supplies null safety, extension functions, lambdas, sealed types, and
coroutines. AndroidX and Jetpack provide lifecycle-aware components, Navigation,
Room, WorkManager, and compatibility APIs. lifecycleScope and viewModelScope
tie coroutines to their owners, but cancellation does not remove the need to make
work idempotent and to handle failures.
Jetpack Compose expresses UI as composable functions. An activity enters Compose
with setContent; observable state collected into the composition causes the
affected UI to recompose. LazyColumn provides efficient item-based layouts, and
modifiers express layout, interaction, and decoration.
Keep screen state in a ViewModel, make composables primarily functions of state,
and use effect APIs for work whose lifetime depends on composition. Views and
Compose can interoperate during a staged migration, so a rewrite is not required to
adopt Compose.
Comments
Read or comment on GitHub (sign-in required to comment)