Skip to content

Android Activity Result API — Complete Guide

DodaTech Updated 2026-06-24 2 min read

In this tutorial, you'll learn about Android Activity Result API. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.

The Problem

You use startActivityForResult() and onActivityResult() which are deprecated. Your result handling breaks when the Activity is recreated.

Wrong Approach ❌

// Deprecated approach
startActivityForResult(Intent(MediaStore.ACTION_IMAGE_CAPTURE), IMAGE_CAPTURE_CODE)

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    if (requestCode == IMAGE_CAPTURE_CODE && resultCode == RESULT_OK) {
        val bitmap = data?.extras?.get("data") as? Bitmap
    }
}

Output: Deprecated, fragment/activity coupling, lost results on rotation.

Right Approach ✅

class MainActivity : AppCompatActivity() {
    // Take a picture
    private val takePictureLauncher = registerForActivityResult(
        ActivityResultContracts.TakePicture()
    ) { success ->
        if (success) {
            // Image saved to URI provided earlier
            imageView.setImageURI(imageUri)
        }
    }

    // Pick a document
    private val pickDocumentLauncher = registerForActivityResult(
        ActivityResultContracts.GetContent()
    ) { uri: Uri? ->
        uri?.let { loadDocument(it) }
    }

    // Custom contract
    private val customLauncher = registerForActivityResult(
        CustomContract()
    ) { result ->
        handleResult(result)
    }

    private fun captureImage() {
        imageUri = createTempImageUri()
        takePictureLauncher.launch(imageUri)
    }

    private fun pickFile() {
        pickDocumentLauncher.launch("image/*")
    }
}

// Custom ActivityResultContract
class CustomContract : ActivityResultContract<InputType, ResultType>() {
    override fun createIntent(context: Context, input: InputType): Intent {
        return Intent(context, TargetActivity::class.java).putExtra("input", input)
    }

    override fun parseResult(resultCode: Int, intent: Intent?): ResultType {
        return if (resultCode == Activity.RESULT_OK) {
            intent?.getSerializableExtra("result") as? ResultType ?: defaultResult()
        } else defaultResult()
    }
}

Output: Clean, type-safe Activity result handling with lifecycle safety.

Prevention

  • Replace all startActivityForResult with registerForActivityResult.
  • Register launchers in onCreate() or early initialization.
  • Use built-in contracts for common operations (take picture, pick contact, etc.).
  • Create custom ActivityResultContract for complex interactions.

Common Mistakes with permission activity result

  1. Forgetting deriving (Show, Eq) on custom data types needed for debugging
  2. Placing the wildcard pattern first in case expressions, making all subsequent patterns unreachable
  3. Using head and tail instead of pattern matching, causing runtime errors on empty lists

These mistakes appear frequently in real-world Android code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

### When should I register the launcher?

Register at initialization (e.g., onCreate). Launchers are lifecycle-aware and survive configuration changes. Do NOT register inside click listeners.

### What contract should I use for picking a contact?

ActivityResultContracts.PickContact() returns a URI. Use ActivityResultContracts.GetContent() with "vnd.Android.cursor.item/contact" for broader support.

### Can I combine launcher registration with Compose?

Yes. Use rememberLauncherForActivityResult() in Compose. It's equivalent to registerForActivityResult and handles the Composable lifecycle.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro