Why does a command time out, and how long should code wait?
Android lets code set a timeout per technology and resets it when the connection closes; the default is not documented, so read it rather than assume it. iOS exposes no timeout at all. In both cases the answer to a timeout is usually fewer commands, not a longer wait.
What Android exposes
setTimeout() on NfcA or IsoDep sets how long transceive() waits. Two details in the reference decide how it is used: the value returns to its default when the connection closes, so it is set again after every connect(), and the default itself is not documented, so getTimeout() is the only honest way to know it.
A longer value is for operations that take the tag time, key generation being the reference's own example. It does not make a tag answer that never would, and it does not help a tag that has left, which raises TagLostException instead, the subject of the tag lost page.
Reader mode adds a second clock: the delay the platform uses to check that a discovered tag is still present, set through the presence check extra, which the removal page covers.
What iOS does not
Core NFC has no timeout to set. The app sends a command and waits, and the framework reports readerTransceiveErrorRetryExceeded when too many retries have happened, or a connection lost error when the tag has gone.
The session has its own limit, an invalidation with no documented duration, which the invalidation page takes up. So on iOS the only lever is how much the app asks for, and how fast it answers: in card emulation Apple warns that a slow response may be read as a timeout by the reader.
What a round trip costs
Every command is a round trip, and the budget for a tap is small. Android's card emulation guide puts a reasonable upper bound at about 1 KB of data exchanged in some 300 ms, which is the clearest published yardstick for what fits while a hand holds still.
So read in the blocks the protocol gives you. A Type 2 READ returns four pages at once, sixteen bytes for one command, as the Type 2 page describes; a Type 4 read is capped by the container's own maximum, and asking for less than that maximum costs commands that buy nothing.
Designing inside the window
Do the work before the tap. Fetch what the exchange needs, build the frames, open the network connection, and keep the tag's time for the tag: an app that calls a server while holding a tag has put a network on the critical path of a hand gesture.
Then treat a timeout as unknown rather than failed, especially after a write, and read the tag back before deciding anything. A retry that assumes the previous command did nothing is how a counter gets incremented twice.
Frequently asked questions
What is the default timeout on Android?
Not documented. Read it with getTimeout on the technology you opened, and set your own value again after every connect.
Can I set a timeout on iOS?
No. Core NFC exposes none. It reports too many retries or a lost connection, and the session has its own undocumented limit.
How much can I exchange in one tap?
Android's card emulation guide gives about 1 KB in roughly 300 ms as a reasonable bound, which is a useful yardstick for reading too.
Is a timeout the same as a refusal?
No. A refusal comes back as a status word or an error flag from the tag. A timeout means nothing came back, so the outcome is unknown.