Android
startActivityForResult
onActivityResult
Android Development
Mobile App Bugs

Android - startActivityForResult immediately triggering onActivityResult

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

If onActivityResult fires immediately after startActivityForResult, the usual reason is that the launched activity finished right away or never really entered a meaningful user flow. The callback itself is not broken. Android is simply telling you the child activity already ended, often with RESULT_CANCELED. In newer Android code, you should also know that startActivityForResult is deprecated in favor of the Activity Result API.

What "Immediate" Usually Means

The normal old-style flow is:

  1. parent calls startActivityForResult
  2. child activity opens
  3. child eventually calls setResult(...) and finish()
  4. parent receives onActivityResult

If step 2 and step 3 happen almost instantly, the parent callback also happens almost instantly. That is why the first debugging question is:

  • why did the launched activity finish so quickly

Common Cause: Child Activity Finishes In onCreate

The most common real cause is logic in the child activity that exits immediately.

kotlin
1class ChildActivity : AppCompatActivity() {
2    override fun onCreate(savedInstanceState: Bundle?) {
3        super.onCreate(savedInstanceState)
4
5        if (intent.getStringExtra("token") == null) {
6            setResult(Activity.RESULT_CANCELED)
7            finish()
8            return
9        }
10
11        setContentView(R.layout.activity_child)
12    }
13}

If the required extra is missing, the activity ends right away and the parent gets a quick callback.

That behavior is correct. The bug is in the launch conditions or validation logic.

Check The Result Code First

When the callback seems too early, inspect the result code and request code before anything else.

kotlin
1override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
2    super.onActivityResult(requestCode, resultCode, data)
3
4    if (requestCode == 1001) {
5        Log.d("Result", "resultCode=$resultCode data=$data")
6    }
7}

If you see RESULT_CANCELED, that is a strong clue that the launched activity exited without completing the expected action.

Other Reasons The Child Can End Immediately

Besides explicit finish(), common causes include:

  • missing required extras or invalid input state
  • activity crashes before UI is usable
  • manifest or theme setup leading to an immediate close
  • permission or login gate that cancels and exits
  • launching an activity that delegates elsewhere and returns without user interaction

A fast crash can sometimes feel like an instant result because the user never sees the intended screen long enough to understand what happened.

Old API Versus New API

startActivityForResult and onActivityResult are deprecated. The recommended modern replacement is registerForActivityResult.

kotlin
1class ParentActivity : AppCompatActivity() {
2    private val launcher = registerForActivityResult(
3        ActivityResultContracts.StartActivityForResult()
4    ) { result ->
5        Log.d("Result", "resultCode=${result.resultCode}")
6    }
7
8    fun openChild() {
9        val intent = Intent(this, ChildActivity::class.java)
10        intent.putExtra("token", "abc123")
11        launcher.launch(intent)
12    }
13}

This does not change the core issue, but it does make the result flow easier to manage in modern Android apps.

Verify The Launch Intent

The parent should build a valid intent and pass everything the child expects.

kotlin
val intent = Intent(this, ChildActivity::class.java)
intent.putExtra("token", "abc123")
startActivityForResult(intent, 1001)

If the child assumes that token exists and exits when it does not, the parent must guarantee it.

Debug The Child, Not Just The Parent

When onActivityResult seems suspicious, developers often stare at the parent callback only. That is usually the wrong place to focus. The child activity lifecycle is where the real explanation lives.

Useful checks:

  • log onCreate, onStart, and onResume in the child
  • log when setResult is called
  • log every code path that can call finish()
  • watch Logcat for crashes or exceptions

The parent callback is only the symptom reporter.

Common Pitfalls

  • Assuming the parent callback is wrong when the child actually finished immediately by design or by bug.
  • Ignoring resultCode, which often shows RESULT_CANCELED and explains the behavior.
  • Forgetting required intent extras so the child activity exits on startup validation.
  • Debugging only the parent activity instead of logging the child lifecycle.
  • Continuing to build new code on the deprecated startActivityForResult API.

Summary

  • Immediate onActivityResult usually means the launched activity ended immediately.
  • Check the child activity for early finish() calls, crashes, or failed startup validation.
  • Inspect requestCode and resultCode first, especially RESULT_CANCELED.
  • The parent callback is usually correct; the child flow is where the bug lives.
  • For new Android code, use the Activity Result API instead of startActivityForResult.

Course illustration
Course illustration

All Rights Reserved.