Bird
Raised Fist0
Android Kotlinmobile~20 mins

Activity results in Android Kotlin - Mini App: Build & Ship

Choose your learning style10 modes available
Build: MainActivity
This screen lets the user open a second screen to enter their name. When the user returns, the main screen shows the entered name.
Target UI
-------------------------
|       Main Screen      |
|                       |
|  Name: [___________]   |
|                       |
|  [Enter Name Button]   |
-------------------------
Add a button labeled 'Enter Name' on the main screen.
When tapped, open a second screen to enter a name.
The second screen has a TextField and a Save button.
When Save is tapped, return the entered name to the main screen.
Display the returned name on the main screen below the label 'Name:'.
Starter Code
Android Kotlin
package com.example.activityresults

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {
    private lateinit var nameTextView: TextView
    private lateinit var enterNameButton: Button

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        nameTextView = findViewById(R.id.nameTextView)
        enterNameButton = findViewById(R.id.enterNameButton)

        // TODO: Register activity result launcher and set button click listener
    }
}
Task 1
Task 2
Task 3
Solution
Android Kotlin
package com.example.activityresults

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {
    private lateinit var nameTextView: TextView
    private lateinit var enterNameButton: Button
    private lateinit var getNameLauncher: ActivityResultLauncher<Intent>

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        nameTextView = findViewById(R.id.nameTextView)
        enterNameButton = findViewById(R.id.enterNameButton)

        getNameLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
            if (result.resultCode == Activity.RESULT_OK) {
                val name = result.data?.getStringExtra("name") ?: ""
                nameTextView.text = "Name: $name"
            }
        }

        enterNameButton.setOnClickListener {
            val intent = Intent(this, EnterNameActivity::class.java)
            getNameLauncher.launch(intent)
        }
    }
}

// Second activity to enter name
import android.app.Activity
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import androidx.appcompat.app.AppCompatActivity

class EnterNameActivity : AppCompatActivity() {
    private lateinit var nameEditText: EditText
    private lateinit var saveButton: Button

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_enter_name)

        nameEditText = findViewById(R.id.nameEditText)
        saveButton = findViewById(R.id.saveButton)

        saveButton.setOnClickListener {
            val name = nameEditText.text.toString()
            val resultIntent = intent
            resultIntent.putExtra("name", name)
            setResult(Activity.RESULT_OK, resultIntent)
            finish()
        }
    }
}

We use registerForActivityResult with StartActivityForResult to launch the second screen and get the result back.

When the user taps the 'Enter Name' button, we start EnterNameActivity.

In EnterNameActivity, the user types a name and taps Save. We put the name into the result intent and finish the activity.

Back in MainActivity, the launcher callback receives the result and updates the TextView to show the entered name.

Final Result
Completed Screen
-------------------------
|       Main Screen      |
|                       |
|  Name: Alice           |
|                       |
|  [Enter Name Button]   |
-------------------------
User taps 'Enter Name Button'.
Second screen opens with a text field and Save button.
User types 'Alice' and taps Save.
Second screen closes and main screen shows 'Name: Alice'.
Stretch Goal
Add a Cancel button on the second screen that closes it without returning a name.
💡 Hint
Set result as RESULT_CANCELED and call finish() when Cancel is tapped.

Practice

(1/5)
1. What is the main purpose of registerForActivityResult in Android Kotlin?
easy
A. To create a new fragment instance
B. To start a new activity without expecting a result
C. To register a broadcast receiver
D. To safely receive data back from another activity

Solution

  1. Step 1: Understand the role of registerForActivityResult

    This function is designed to handle results from activities started for a result safely and simply.
  2. Step 2: Compare with other options

    Starting an activity without expecting a result or registering broadcast receivers are unrelated to this function.
  3. Final Answer:

    To safely receive data back from another activity -> Option D
  4. Quick Check:

    Activity result handling = A [OK]
Hint: Remember: registerForActivityResult handles returned data safely [OK]
Common Mistakes:
  • Confusing it with starting activities without results
  • Thinking it registers broadcast receivers
  • Assuming it creates fragments
2. Which of the following is the correct syntax to register an activity result launcher in Kotlin?
easy
A. val launcher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> /* handle result */ }
B. val launcher = registerActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> /* handle result */ }
C. val launcher = registerForResult(ActivityResultContracts.StartActivityForResult()) { result -> /* handle result */ }
D. val launcher = registerActivity(ActivityResultContracts.StartActivityForResult()) { result -> /* handle result */ }

Solution

  1. Step 1: Identify the correct function name

    The correct function is registerForActivityResult, not any shortened or altered form.
  2. Step 2: Check the contract and lambda syntax

    The contract ActivityResultContracts.StartActivityForResult() and lambda parameter { result -> } are correctly used in val launcher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> /* handle result */ }.
  3. Final Answer:

    val launcher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> /* handle result */ } -> Option A
  4. Quick Check:

    Correct function name and syntax = B [OK]
Hint: Look for exact function name: registerForActivityResult [OK]
Common Mistakes:
  • Using incorrect function names like registerActivityResult
  • Omitting parentheses in contract instantiation
  • Wrong lambda syntax
3. Given the following code snippet, what will be printed if the launched activity returns RESULT_OK with intent data containing key "username" = "Alice"?
val launcher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
    if (result.resultCode == Activity.RESULT_OK) {
        val name = result.data?.getStringExtra("username")
        println(name)
    } else {
        println("No data")
    }
}
medium
A. Crash due to null pointer
B. Alice
C. null
D. No data

Solution

  1. Step 1: Check the result code condition

    The code checks if result.resultCode == Activity.RESULT_OK, which is true in this case.
  2. Step 2: Extract the "username" from intent data

    The intent data contains key "username" with value "Alice", so name will be "Alice" and printed.
  3. Final Answer:

    Alice -> Option B
  4. Quick Check:

    Result OK with data returns value = D [OK]
Hint: Check resultCode and safely unwrap intent data [OK]
Common Mistakes:
  • Ignoring resultCode and printing 'No data'
  • Assuming data is null without checking
  • Not using safe call operator on intent data
4. Identify the error in this code snippet for handling activity results:
val launcher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
    val name = result.data!!.getStringExtra("username")
    if (result.resultCode == Activity.RESULT_OK) {
        println(name)
    }
}
medium
A. Unsafe call on result.data before checking resultCode
B. Missing lambda parameter in registerForActivityResult
C. Incorrect contract used for activity result
D. No error, code is correct

Solution

  1. Step 1: Analyze the order of operations

    The code force unwraps result.data!! before checking if result.resultCode == Activity.RESULT_OK.
  2. Step 2: Understand potential crash

    If the result is not OK or data is null, force unwrapping causes a crash. The check should come before accessing data.
  3. Final Answer:

    Unsafe call on result.data before checking resultCode -> Option A
  4. Quick Check:

    Check resultCode before accessing data = A [OK]
Hint: Always check resultCode before using intent data [OK]
Common Mistakes:
  • Force unwrapping nullable data without checks
  • Accessing data before verifying resultCode
  • Ignoring null safety in Kotlin
5. You want to start an activity to pick a contact and get the contact's URI back. Which approach correctly uses registerForActivityResult to achieve this?
hard
A. val pickContact = registerForActivityResult(ActivityResultContracts.RequestPermission()) { granted -> if (granted) println("Permission granted") }
B. val pickContact = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> println(result.data?.getData().toString()) }
C. val pickContact = registerForActivityResult(ActivityResultContracts.PickContact()) { uri -> if (uri != null) println(uri.toString()) }
D. val pickContact = registerForActivityResult(ActivityResultContracts.TakePicture()) { success -> if (success) println("Picture taken") }

Solution

  1. Step 1: Identify the correct contract for picking a contact

    ActivityResultContracts.PickContact() is designed to pick a contact and return its URI.
  2. Step 2: Check the lambda parameter and usage

    The lambda receives a URI nullable parameter, which is safely checked before printing.
  3. Step 3: Eliminate other options

    val pickContact = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> println(result.data?.getData().toString()) } uses a generic contract but does not check resultCode; A and D are unrelated contracts for permissions and taking pictures.
  4. Final Answer:

    val pickContact = registerForActivityResult(ActivityResultContracts.PickContact()) { uri -> if (uri != null) println(uri.toString()) } -> Option C
  5. Quick Check:

    Use PickContact contract for contact URI = C [OK]
Hint: Use specific contracts like PickContact for contact picking [OK]
Common Mistakes:
  • Using StartActivityForResult without checking resultCode
  • Confusing permission or picture contracts with contact picking
  • Not handling nullable URI safely
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard