Android Fundamentals: Activities, Services, Intents, Permissions

Android Development with Kotlin: 21 Real Projects · Kotlin and Android in Depth · 4 min read · Updated

Activity lifecycle

  1. onCreate runs once when the Activity is built. You call setContent here.
  2. The user sees the screen and can interact with it.
  3. When the user leaves, onPause and onStop run. Release things you no longer need.
  4. onDestroy follows if the screen is finished, or if rotation recreates it. Keep state in a ViewModel.

Compose hides much of Android, but every app still sits on the same foundation. You need it to debug lifecycle problems, handle links and notifications, and pass interviews.

The four app components

  • Activity: one screen with a window. Modern apps often have a single Activity that hosts all Compose screens.
  • Service: work that runs without a screen. A *foreground service* shows a notification and is used for music, navigation or uploads.
  • BroadcastReceiver: reacts to system or app messages, such as boot completed or battery low.
  • ContentProvider: shares structured data between apps, as the Contacts and Media stores do.

All components are declared in AndroidManifest.xml, together with permissions, the app icon and name, and intent-filters that say which links or actions a component can handle.

The Activity lifecycle

Android creates, pauses and destroys your Activity as the user moves around. The main callbacks are onCreate (set up, call setContent), onStart (becoming visible), onResume (in the foreground and interactive), onPause (losing focus), onStop (not visible) and onDestroy. Put start/stop work, such as listening for location, in the matching pair of callbacks, or better, use lifecycle-aware tools like collectAsStateWithLifecycle, which do it for you.

A configuration change, such as rotation, dark mode or a language switch, recreates the Activity by default. That is why state must live in a ViewModel or in rememberSaveable. The system can also kill your whole process while the app is in the background to free memory. Data that must survive that goes in SavedStateHandle, a database or DataStore.

Fragments

A Fragment is a reusable piece of UI with its own lifecycle that lives inside an Activity. Older apps use many Fragments with the Navigation Component. Its view has a separate lifecycle (onCreateView to onDestroyView), which is a common source of leaks: never keep a reference to the binding after the view is destroyed. In new Compose apps you rarely write Fragments, but you may maintain them.

Intents

An Intent is a message that asks the system to do something. An *explicit* intent names the target class. An *implicit* intent describes an action and lets Android pick an app.

// explicit: open another Activity of your own app
startActivity(Intent(this, DetailActivity::class.java).putExtra("id", 42))

// implicit: open a web page in whichever browser the user has
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://example.com")))

// share text
val send = Intent(Intent.ACTION_SEND).apply {
    type = "text/plain"
    putExtra(Intent.EXTRA_TEXT, "Look at this app")
}
startActivity(Intent.createChooser(send, "Share with"))

An intent-filter in the manifest lets your app receive such intents or open from a link (deep link). Since Android 12, any component with an intent filter must declare android:exported.

Permissions

*Normal* permissions (such as INTERNET) are granted at install. *Dangerous* permissions (camera, location, notifications, contacts) must be requested at run time, and the user can refuse. Use the Activity Result API, which Compose wraps as rememberLauncherForActivityResult.

val launcher = rememberLauncherForActivityResult(
    ActivityResultContracts.RequestPermission()
) { granted -> if (granted) startCamera() else showExplanation() }

Button(onClick = { launcher.launch(Manifest.permission.CAMERA) }) { Text("Scan") }

Context and resources

A Context gives access to resources, files and system services. The application context lives as long as the app. An Activity context lives as long as the screen and carries its theme. Never store an Activity context in a long-lived object, because the Activity then cannot be freed: that is a memory leak. Resources live in res/: strings.xml for text (so you can translate it), drawable for images, values for colours and dimensions, and qualifiers such as values-hi or values-night give alternatives for languages and dark mode.

Each Activity or navigation destination is pushed on a back stack. The Back button pops it. The launchMode and navigation options such as popUpTo change this. Android 14 and later support predictive back, so avoid intercepting Back unless you must.

Your task

  1. Add log lines to every Activity lifecycle callback and watch the order when you open the app, press Home, rotate and return.
  2. Share text from your app with an implicit intent.
  3. Request the camera permission and handle both answers.
  4. Add a deep link to one screen in the manifest and open it with adb shell am start -a android.intent.action.VIEW -d "myapp://item/1".

How to check it worked

  • You can describe what happens to your state on rotation.
  • You know which permissions are asked at run time.
  • You can explain explicit and implicit intents.

Frequently asked questions

Why does my state reset when I rotate the phone?

Rotation recreates the Activity. Keep state in a ViewModel, rememberSaveable or SavedStateHandle, which survive that.

Do I still need Fragments?

Not for new Compose apps, which use one Activity and Navigation Compose. You will meet Fragments in older code bases.

Foreground or background service?

A foreground service shows a notification and is allowed to keep running, for music or tracking. Background work is restricted by Android, so use WorkManager for deferred tasks.