User Interaction

Android Development Fundamentals
Course 1 ยท Chapter 4 ยท User Interaction

๐Ÿ‘† User Interaction

Chapter 3 built static screens; this chapter makes them respond to taps and navigate between each other. It covers click and text-change listeners, then Intents โ€” the object that both launches a new screen and carries data along with it, in one mechanism.

๐Ÿ–ฑ๏ธ Click Listeners

Chapter 3 already used setOnClickListener briefly โ€” here's the fuller picture, including the pattern for reading input at click time:

binding.submitButton.setOnClickListener { val name = binding.nameInput.text.toString() binding.nameLabel.text = "Hello, $name!" }

setOnClickListener takes a lambda โ€” this is exactly the same lambda-as-callback pattern from Kotlin Fundamentals Chapter 2, just receiving a View click event instead of, say, a collection element. There's also an older XML-attribute style (android:onClick="onSubmitClicked", referencing a method on the Activity) still seen in legacy code, but the Kotlin lambda form is the modern default and what this course uses throughout.

setOnLongClickListener

Fires on a press-and-hold, not a tap โ€” the lambda must return a Boolean (whether the long click was "consumed," suppressing any regular click that might otherwise also fire).

addTextChangedListener

Fires on every keystroke in an EditText โ€” the live-validation equivalent of a JavaScript input event listener, useful for things like a real-time character counter or inline form validation.

๐Ÿš€ Explicit Intents โ€” Launching Your Own Screens

An Intent is an object describing "an operation to perform" โ€” most commonly, "start this specific Activity." An explicit Intent names the target Activity directly:

val intent = Intent(this, DetailActivity::class.java) startActivity(intent)

this is the current Activity (acting as the required Context parameter), and DetailActivity::class.java identifies the destination โ€” both required arguments. startActivity(intent) then hands the Intent to the Android system, which creates and launches the new Activity, pushing the current one to onPause/onStop (Chapter 2) in the process.

๐Ÿ“ฆ Passing Data Along With an Intent

An Intent doubles as a small data carrier โ€” putExtra attaches key-value pairs, retrieved on the receiving end with the matching typed getter:

// Sending Activity val intent = Intent(this, DetailActivity::class.java) intent.putExtra("USER_NAME", "Philip") intent.putExtra("USER_AGE", 33) startActivity(intent)
// Receiving Activity โ€” DetailActivity override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_detail) val name = intent.getStringExtra("USER_NAME") ?: "Unknown" val age = intent.getIntExtra("USER_AGE", 0) // getStringExtra returns String? โ€” Elvis fallback handles the missing-key case // getIntExtra takes a default value directly as its second parameter instead }
โš  Extras Are Untyped Until You Retrieve Them

An Intent's extras are stored in a Bundle (the same type from Chapter 2's savedInstanceState) โ€” retrieving the wrong type for a given key, or a mistyped key entirely, doesn't fail at compile time. Keeping extra keys as const val constants (const val EXTRA_USER_NAME = "USER_NAME"), shared between sender and receiver, avoids typo-based bugs โ€” a small habit worth adopting early.

๐ŸŒ Implicit Intents โ€” Asking the System for Help

An implicit Intent doesn't name a specific Activity โ€” it describes an action, and lets Android find whatever app on the device can handle it:

// Open a URL in whatever browser is installed val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://osztromok.com")) startActivity(intent) // Share text via whatever apps offer sharing (Messages, Email, etc.) val shareIntent = Intent(Intent.ACTION_SEND).apply { type = "text/plain" putExtra(Intent.EXTRA_TEXT, "Check out this app!") } startActivity(Intent.createChooser(shareIntent, "Share via"))

ACTION_VIEW with a URI, ACTION_SEND for sharing, ACTION_DIAL for a phone number โ€” the action constant plus relevant data tells the system what's needed, and any installed app that's registered to handle that action becomes a candidate. Intent.createChooser(...) explicitly shows the picker UI even if only one app could handle it, which is usually the friendlier choice for a "Share" action specifically.

Intents vs Web Navigation

Web (window.location / React Router)Android
Navigate to a new "page"window.location.href = "/detail" or <Link to="/detail">startActivity(Intent(this, DetailActivity::class.java))
Pass data alongURL params, query strings, router stateIntent.putExtra(key, value)
Delegate to another app entirelyNot really applicable โ€” the browser IS the appAn implicit Intent (ACTION_VIEW, ACTION_SEND, ...)

The explicit/implicit split has no real web equivalent โ€” a web app effectively can't "hand off" to another completely separate application the way ACTION_SEND can open the user's choice of messaging app. It's a genuinely different, OS-level idea: apps on Android cooperate through Intents rather than staying fully siloed.

๐Ÿ’ป Coding Challenges

Challenge 1: Navigate Between Two Activities

Create a second Activity called DetailActivity with a simple layout (one TextView). In MainActivity, add a button that launches DetailActivity using an explicit Intent when clicked.

Goal: Practice the basic explicit-Intent navigation pattern.

โ†’ Solution

Challenge 2: Pass Data to the Second Activity

Extend Challenge 1: add an EditText to MainActivity, and when the button is clicked, pass its current text to DetailActivity via putExtra. In DetailActivity's onCreate, retrieve the extra (with an appropriate fallback if missing) and display it in the TextView.

Goal: Practice the full putExtra/getXExtra round trip.

โ†’ Solution

Challenge 3: An Implicit Share Intent

Add a "Share" button to DetailActivity that uses an implicit ACTION_SEND Intent to share the text it's displaying (from Challenge 2), wrapped in Intent.createChooser so a picker always appears.

Goal: Practice building and launching an implicit Intent.

โ†’ Solution

๐Ÿ’ก A New Activity Needs Registering โ€” Don't Forget the Manifest

Any new Activity created (like DetailActivity in the challenges) must be declared with an <activity> entry in AndroidManifest.xml (Chapter 1) before it can be launched โ€” Android Studio adds this automatically when using its "New โ†’ Activity" wizard, but a manually-created Activity class needs it added by hand, or startActivity() crashes with an ActivityNotFoundException.

๐ŸŽฏ What's Next

Next chapter: RecyclerView โ€” the adapter pattern, ViewHolder, DiffUtil, and click handling in scrollable lists.