Skip to content

"Data intent is null" if we exit the application and open it again using the icon #1094

Open

Description

@Hloview

Issue

We have some issue when user exit the application and open it again using the app icon.

The tab closes with an error : Data intent is null

To solve this, we need to update android:launchMode in AndroidManifest.xml from singleTask to singleTop.

But react-native with deeplinking indicate to use singleTask : https://reactnative.dev/docs/linking#enabling-deep-links


Environment

Can be reproduce with the example project of the package.

Activity

  1. dparcerisa commented on Aug 31, 2026

    @dparcerisa

    We hit this in production and spent a while on it, so here is what we measured on an Android 15 emulator. Two things that may save someone else the time.

    The singleTop workaround in the issue body makes it worse, not better.

    We tried it. The error goes away, but the flow then neither resolves nor rejects — the promise just hangs forever. From the user's side that is a login that silently does nothing, which is harder to diagnose and worse UX than an error. We also tried android:alwaysRetainTaskState="true" on the launcher activity: no effect at all, it does not override singleTask's clear-top behaviour.

    The root cause is two independent problems, and fixing either alone does nothing.

    The task stack tells it:

    before:  AuthorizationManagementActivity   <- holds the pending request
             MainActivity
    (return to the app from the launcher)
    after:   MainActivity
    
    AppAuth: No stored state - unable to handle response
    
    1. AppAuth keeps the pending request inside AuthorizationManagementActivity, which lives in the caller's task. With MainActivity as singleTask, re-entering from the launcher clears the task above the root and destroys it. Even if the response is delivered perfectly, AppAuth has nothing to match it against — hence No stored state.

    2. authorizeWithConfiguration delivers via startActivityForResult(authIntent, 52), which is bound to the living activity instance and cannot cross tasks. When the activity is gone the result arrives as a null Intent, which is where Data intent is null comes from.

    What worked for us, keeping singleTask on MainActivity so React Native deep linking stays intact:

    • App side: give AuthorizationManagementActivity its own taskAffinity plus launchMode="singleInstance", so the app's task reset never touches it.
    • Library side: deliver the response through a PendingIntent addressed to the launcher activity — component only, no MAIN/LAUNCHER categories, since those are what trigger the reset — and complete the flow from onNewIntent, which the module declares but leaves empty today.

    After that the pending request survives the round trip and the response reaches JS normally. Verified twice in a row, and we checked that psb://-style deep links and universal links still resume a single MainActivity instance rather than spawning a second.

    Happy to open a PR for the library half if maintainers think the PendingIntent path is the right direction. It would need a decision on whether to make it opt-in, since it changes how the response arrives.

  2. dparcerisa commented on Sep 1, 2026

    @dparcerisa

    Correction to my earlier comment here — I proposed a direction, tried it in production, and it did not survive contact with real devices. Closing the PR I opened (#1137), and recording why so nobody repeats it.

    The PendingIntent approach makes things worse on the devices that actually hit this bug. It requires the app to launch itself from the background, which Android permits only briefly after the app loses focus, and which OEM skins restrict much harder. Measured on an Oppo A74 (Android 14, ColorOS, stock settings):

    Provider Result
    Spotify (mails a one-time code) Never completes — the mail round trip outlasts the allowance, and the promise never settles at all
    Google (fast) Completes, getting in under the wire
    Spotify with ColorOS "auto-launch" on Completes — confirming the mechanism

    So it converts Data intent is null, which you can at least catch, into an unobservable hang. That is a downgrade.

    And the host-app half I suggested — singleInstance plus a separate taskAffinity — breaks retrying. It does keep the activity alive across a task reset, but a second authorization can then never create a fresh instance: Android reuses the stale one, AppAuth reads the resume as a cancellation, and the browser never opens. Abandoning a login and trying again stops working. No emulator surfaced this; it took an explicit retry test on top of the fix.

    What worked for us, without touching the library: treat this as an interruption rather than a failure. Track that a flow is in the air, clear it on every settled path, and offer to resume when either Data intent is null arrives or the app comes back to the front with the flow still unsettled. Restarting the authorization is cheap because the provider session is still alive in the browser. It does not make the interruption invisible, but it needs no OEM permission and it does not break retrying.

    The underlying issue in this ticket is still real — I just no longer think the fix belongs where I first put it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions